← All code samples

Create a custom workflow (coding-style)

Compose an agent and workflow in Go, TypeScript, or Python, then publish it with one SDK call. Stages chain with .then(). You describe the steps in code instead of editing YAML by hand. Go names are CreateAgent, CreateStage, CreateWorkflow, and PublishWorkflow.

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 workspace workspace_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_…",
        workspace_id="<workspace-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 the Aiden depends_on field.

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_… \\
    --workspace-id <workspace-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("--workspace-id",
        "--org-id", default=os.environ.get("STACKGEN_WORKSPACE_ID", "") or os.environ.get("STACKGEN_PROJECT", ""))
    p.add_argument("--agent-name", default="hello-agent")
    p.add_argument("--workflow-name", default="hello-workflow")
    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,
            workspace_id=args.workspace_id,
        )
    )

    hello_agent = create_agent(
        name=args.agent_name,
        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=args.agent_name,
        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=args.workflow_name,
            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(f"run with: stackgen ai run workflow/{args.workflow_name} --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 Kinded YAML apply