← All code samples

Create a custom workflow (coding-style)

Compose an Agent + Workflow in TypeScript or Python, then publish it with one SDK call. Stages chain with .then() — the same idea as step builders in other agent frameworks — instead of editing YAML by hand.

Step What you write
1. Agent createAgent({ name, persona, … })
2. Stage createStage({ id, agent, note, needs? })
3. Workflow createWorkflow({ name, domain, … }).then(stage).commit()
4. Publish client.aiden.publishWorkflow(workflow, { agents, approve: true })

Requires an API token and project org_id. Agents are registered (or updated on conflict); the workflow is created or updated as a draft, then approved so it can run.

Minimal — compose and publish

from stackgen import (
    StackgenClient,
    StackgenConfig,
    create_agent,
    create_stage,
    create_workflow,
)

client = StackgenClient(
    StackgenConfig(
        base_url="https://app.stackgen.com",
        api_token="stackgen_…",
        org_id="<project-uuid>",
    )
)

agent = create_agent(
    name="hello-agent",
    persona="Turn a short topic into three clear bullets.",
    always_allowed_tools=["note"],
    auto_approve_tools=[{"tool": "note"}],
)

workflow = (
    create_workflow(
        name="hello-workflow",
        domain="product",
        required_inputs=["topic"],
    )
    .then(
        create_stage(
            id="summarize",
            agent="hello-agent",
            note="Read required input `topic`. Reply with exactly three bullets.",
        )
    )
    .commit()
)

result = client.aiden.publish_workflow(workflow, agents=[agent], approve=True)
print(result.workflow_name, result.version, result.status)

Chain a second stage

Add another agent and stage. Set needs: ["summarize"] (Python needs=["summarize"]) so the second stage waits for the first — the SDK maps that to Guild depends_on.

critique_agent = create_agent(
    name="hello-critic",
    persona="Critique a short summary for gaps. Stay brief.",
    always_allowed_tools=["note"],
)

workflow = (
    create_workflow(name="hello-workflow", domain="product", required_inputs=["topic"])
    .then(create_stage(id="summarize", agent="hello-agent", note="Three bullets."))
    .then(
        create_stage(
            id="critique",
            agent="hello-critic",
            needs=["summarize"],
            note="Read the summarize output. List up to three improvements.",
        )
    )
    .commit()
)

Runnable CLI

#!/usr/bin/env python3
"""Create a custom hello workflow with the StackGen SDK (coding-style).

Usage:
  python examples/create-workflow/create-hello-workflow.py \\
    --base-url https://app.stackgen.com \\
    --api-token stackgen_… \\
    --org-id <project-uuid>
"""

from __future__ import annotations

import argparse
import os
import sys

from stackgen import (
    StackgenClient,
    StackgenConfig,
    create_agent,
    create_stage,
    create_workflow,
)


def main() -> int:
    p = argparse.ArgumentParser(description=__doc__)
    p.add_argument("--base-url", default=os.environ.get("STACKGEN_URL", ""))
    p.add_argument("--api-token", default=os.environ.get("STACKGEN_TOKEN", ""))
    p.add_argument("--org-id", default=os.environ.get("STACKGEN_PROJECT", ""))
    args = p.parse_args()
    if not args.base_url or not args.api_token:
        print("Need --base-url and --api-token (or STACKGEN_URL / STACKGEN_TOKEN)", file=sys.stderr)
        return 1

    client = StackgenClient(
        StackgenConfig(
            base_url=args.base_url,
            api_token=args.api_token,
            org_id=args.org_id,
        )
    )

    hello_agent = create_agent(
        name="hello-agent",
        persona=(
            "You turn a short topic into a clear three-bullet summary.\n"
            "Stay concrete. Do not invent sources."
        ),
        always_allowed_tools=["note"],
        auto_approve_tools=[{"tool": "note"}],
    )

    summarize = create_stage(
        id="summarize",
        agent="hello-agent",
        description="Summarize the topic in three bullets.",
        note=(
            "Read the workflow required input `topic`.\n"
            "Reply with exactly three bullets, then stop."
        ),
    )

    workflow = (
        create_workflow(
            name="hello-workflow",
            domain="product",
            required_inputs=["topic"],
            tags=["example"],
        )
        .then(summarize)
        .commit()
    )

    published = client.aiden.publish_workflow(
        workflow,
        agents=[hello_agent],
        approve=True,
    )
    print(
        f"published {published.workflow_name} v{published.version} ({published.status})"
    )
    print("run with: stackgen ai run workflow/hello-workflow --input 'topic=…'")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

After publish, run with Ask (same SDK) or the CLI:

stackgen ai run workflow/hello-workflow --input 'topic=on-call handoff notes'

Related: Ask → artifact · YAML apply alternate in solutions Create a custom workflow