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)import {
StackgenClient,
StackgenConfig,
createAgent,
createStage,
createWorkflow,
} from "stackgen-sdk";
const client = new StackgenClient(
new StackgenConfig({
baseUrl: "https://app.stackgen.com",
apiToken: "stackgen_…",
orgId: "<project-uuid>",
}),
);
const agent = createAgent({
name: "hello-agent",
persona: "Turn a short topic into three clear bullets.",
alwaysAllowedTools: ["note"],
autoApproveTools: [{ tool: "note" }],
});
const workflow = createWorkflow({
name: "hello-workflow",
domain: "product",
requiredInputs: ["topic"],
})
.then(
createStage({
id: "summarize",
agent: "hello-agent",
note: "Read required input `topic`. Reply with exactly three bullets.",
}),
)
.commit();
const result = await client.aiden.publishWorkflow(workflow, {
agents: [agent],
approve: true,
});
console.log(result.workflowName, 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()
)const critiqueAgent = createAgent({
name: "hello-critic",
persona: "Critique a short summary for gaps. Stay brief.",
alwaysAllowedTools: ["note"],
});
const workflow = createWorkflow({
name: "hello-workflow",
domain: "product",
requiredInputs: ["topic"],
})
.then(createStage({ id: "summarize", agent: "hello-agent", note: "Three bullets." }))
.then(
createStage({
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())/**
* Create a custom hello workflow with the StackGen SDK (coding-style).
*
* Usage:
* npx tsx examples/create-workflow/create-hello-workflow.ts \
* --base-url https://app.stackgen.com \
* --api-token stackgen_… \
* --org-id <project-uuid>
*/
import {
StackgenClient,
StackgenConfig,
createAgent,
createStage,
createWorkflow,
} from "stackgen-sdk";
function arg(name: string, fallback = ""): string {
const idx = process.argv.indexOf(name);
if (idx >= 0 && process.argv[idx + 1]) {
return process.argv[idx + 1];
}
return fallback;
}
const baseUrl = arg("--base-url", process.env.STACKGEN_URL || "");
const apiToken = arg("--api-token", process.env.STACKGEN_TOKEN || "");
const orgId = arg("--org-id", process.env.STACKGEN_PROJECT || "");
if (!baseUrl || !apiToken) {
console.error("Need --base-url and --api-token (or STACKGEN_URL / STACKGEN_TOKEN)");
process.exit(1);
}
const client = new StackgenClient(
new StackgenConfig({ baseUrl, apiToken, orgId }),
);
const helloAgent = createAgent({
name: "hello-agent",
persona: `You turn a short topic into a clear three-bullet summary.
Stay concrete. Do not invent sources.`,
alwaysAllowedTools: ["note"],
autoApproveTools: [{ tool: "note" }],
});
const summarize = createStage({
id: "summarize",
agent: "hello-agent",
description: "Summarize the topic in three bullets.",
note: `Read the workflow required input \`topic\`.
Reply with exactly three bullets, then stop.`,
});
const workflow = createWorkflow({
name: "hello-workflow",
domain: "product",
requiredInputs: ["topic"],
tags: ["example"],
})
.then(summarize)
.commit();
const published = await client.aiden.publishWorkflow(workflow, {
agents: [helloAgent],
approve: true,
});
console.log(
`published ${published.workflowName} v${published.version} (${published.status})`,
);
console.log("run with: stackgen ai run workflow/hello-workflow --input 'topic=…'");
console.log("or: client.aiden.runAskAndDownloadArtifact(…, { entityRefs: [{ name: 'hello-workflow', type: 'workflow' }], inputs: { topic: '…' } })");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