Aiden automation guide
This guide shows how to drive Aiden workflows and agents from CI, scripts, or backend jobs using the StackGen SDK. Every example uses explicit config (not a dozen environment variables) and is shown in Python and TypeScript.
Authoring vs running
- Create workflows in code with
createAgent/createStage/createWorkflowandclient.aiden.publishWorkflow— see Create a workflow. - Run existing workflows with webhook or Ask journeys below.
Quick links
| Topic | Jump to |
|---|---|
| Compose + publish a workflow | Create a workflow |
| Terms (session, trace, webhook, …) | Glossary |
| Install and connect | Setup |
| FAQ (install, auth, errors, reports) | FAQ |
| Alert → workflow (webhook) | Trigger a workflow |
| Natural language → workflow/agent | Ask Guild |
| Poll until work is ready | Wait for a session |
| Get the markdown report | Download artifacts |
| Runnable scripts | Code samples |
For SRE alerts and investigations see Usage.
Glossary
Plain-language definitions for terms you will see in responses and logs.
| Term | What it means |
|---|---|
| Mothership | Your StackGen cloud host, e.g. https://app.stackgen.com. Do not append /guild in config — the SDK adds product paths. |
Project / org (org_id) |
UUID of your StackGen project. Sent as the orgId query parameter on Aiden routes. |
| API token | Long-lived token starting with stackgen_…. Used to read sessions, poll executions, and download artifacts. |
| Webhook token | Token starting with sg_aios_…. Used only to POST an alert or payload to /webhooks/trigger. Think of it as “ring the doorbell for automation.” |
| Webhook | A configured entry point that maps an incoming payload to a workflow (or agent). Datadog/Grafana/your script POST to it. |
| Workflow | A multi-step automation (skills, tools, stages) registered in Aiden, e.g. incident-triage. |
| Agent | A conversational agent registered in Aiden. Ask can route to an agent when you pin one with entity_refs. |
| Trigger | The first HTTP call that starts work — either webhook POST or Ask start. |
Session (session_id) |
Conversation/workspace id for the run. You need it to list artifacts and continue a chat. |
Trace (trace_id) |
Execution trace id returned by Ask. Poll it until the run finishes. |
| Run / invocation | Webhook-specific ids in the trigger response (webhook_id, invocation_id, run_id) for tracking the invocation. |
| Execution settled | Ask poll is done when execution.status is completed or error and trace_settled is true. |
| Artifact | File produced in the session, usually session-report.md — the triage/RCA write-up. |
entity_refs |
Optional Ask body field that pins a workflow or agent by name so routing is deterministic in CI. |
| Poll | SDK repeatedly GETs an endpoint until a condition is met (session exists, execution settled, artifact listed). Default interval 5s, timeout 30 minutes. |
How it fits together
Two common paths:
flowchart LR
subgraph webhookPath [Webhook path]
A[Your alert or JSON] --> B[POST webhooks/trigger]
B --> C[Workflow runs]
C --> D[session_id]
D --> E[session-report.md]
end
subgraph askPath [Ask path]
F[Natural language message] --> G[POST guild/ask/start]
G --> H[Poll executions/traceId]
H --> I[session_id]
I --> E
end
Webhook path — best when you already have a webhook URL/token (e.g. wired from Datadog) and a structured alert body.
Ask path — best when you only have an API token and want to say “run workflow
X for this incident” in plain language. Pin the workflow with entity_refs in CI.
Setup
Install
pip install stackgen-sdk==0.1.5
npm install stackgen-sdk@0.1.5
Connect
Use three mothership fields everywhere. Add webhook_token only for webhook journeys.
Python
from stackgen import StackgenClient, StackgenConfig
client = StackgenClient(
StackgenConfig(
base_url="https://app.stackgen.com",
api_token="stackgen_…", # stackgen_… from StackGen UI
org_id="4f942a41-…", # project UUID → orgId
webhook_token="sg_aios_…", # only for webhook trigger
poll_interval_seconds=5,
timeout_seconds=1800, # 30 min default
artifact_name="session-report.md",
output_path="session-report.md",
)
)
TypeScript
import { StackgenClient, StackgenConfig } from "stackgen-sdk";
const client = new StackgenClient(
new StackgenConfig({
baseUrl: "https://app.stackgen.com",
apiToken: "stackgen_…",
orgId: "4f942a41-…",
webhookToken: "sg_aios_…", // only for webhook trigger
pollIntervalSeconds: 5,
timeoutSeconds: 1800,
artifactName: "session-report.md",
outputPath: "session-report.md",
}),
);
Optional convenience — three env vars only (STACKGEN_URL, STACKGEN_TOKEN,
STACKGEN_PROJECT), then set webhook token in code:
from dataclasses import replace
from stackgen import StackgenClient, StackgenConfig
client = StackgenClient(
replace(StackgenConfig.from_env(), webhook_token="sg_aios_…")
)
const base = StackgenConfig.fromEnv();
const client = new StackgenClient(
new StackgenConfig({ ...base, webhookToken: "sg_aios_…" }),
);
Which token when?
| Action | Token |
|---|---|
| POST webhook trigger | webhook_token / webhookToken |
| Poll webhook runs, list/download artifacts | api_token / apiToken |
| Ask start, poll execution, artifacts | api_token / apiToken only |
Journey 1: Trigger a workflow via webhook
Use this when a webhook is already configured to start a workflow (for example
incident-triage) and you have the sg_aios_… token.
What happens
- SDK POSTs your alert text/JSON to
/guild/api/v1/webhooks/trigger?orgId=… - Aiden starts the target workflow. Newer motherships may return
session_idon the 202 body; otherwise the SDK pollsGET /webhooks/{webhook_id}/runs/{invocation_id}untilsession_idis set (same as Guild’s reference script). - SDK waits until
session-report.md(or your artifact name) appears - SDK downloads the file to
output_path
For queue + scheduler architectures, use stateless methods (trigger_webhook, wait_for_webhook_session, …) — see Async webhook CI.
One call (recommended)
Python
from pathlib import Path
payload = Path("alert.json").read_text(encoding="utf-8")
# Or plain text: payload = "P1 | checkout-api error rate above SLO"
result = client.aiden.run_webhook_and_download_report(payload)
print("webhook_id", result.webhook_id)
print("session_id", result.session_id)
print("report", result.output_path)
TypeScript
import { readFileSync } from "node:fs";
const payload = readFileSync("alert.json", "utf8");
const result = await client.aiden.runWebhookAndDownloadReport(payload);
console.log("webhookId", result.webhookId);
console.log("sessionId", result.sessionId);
console.log("report", result.outputPath);
Equivalent curl
The SDK does the same as:
curl -X POST \
"https://app.stackgen.com/guild/api/v1/webhooks/trigger?orgId=<project-uuid>" \
-H "Authorization: Bearer sg_aios_…" \
-H "Content-Type: text/plain" \
-d @alert.txt
Then the SDK uses your API token to wait for the session artifact and download it.
Trigger only, wait for session yourself
If you only need session_id and will download the report later, see
Webhook → session only
on the code samples page. The step-by-step flow:
- POST the webhook (JSON or plain text)
- Read
session_idfrom the 202 body when present, or poll run detail withwait_for_webhook_session - Optionally wait for and download the report
Journey 2: Start work or an agent with Ask Guild
Use Ask when you have only the API token and want to send a natural-language
task. In CI, always pin the workflow or agent with entity_refs so routing is
predictable.
What happens
- SDK POSTs to
/guild/api/v1/guild/ask/start?orgId=…withmessage(+ optionalentity_refs) - Response includes
trace_idand usuallysession_id - SDK polls
/guild/api/v1/executions/{traceId}until status is terminal andtrace_settled - SDK waits for the session artifact and downloads it
There is no SSE in the SDK — polling only, which works in CI and locked-down networks.
One call — workflow pinned (recommended for CI)
Python
result = client.aiden.run_ask_and_download_artifact(
message="Run triage for checkout CPU alert",
entity_refs=[{"name": "incident-triage", "type": "workflow"}],
artifact_name="session-report.md",
output_path="session-report.md",
)
print("trace_id", result.trace_id)
print("session_id", result.session_id)
print("plan", result.plan)
print("report", result.output_path)
TypeScript
const result = await client.aiden.runAskAndDownloadArtifact({
message: "Run triage for checkout CPU alert",
entityRefs: [{ name: "incident-triage", type: "workflow" }],
artifactName: "session-report.md",
outputPath: "session-report.md",
});
console.log("traceId", result.traceId);
console.log("sessionId", result.sessionId);
console.log("plan", result.plan);
console.log("report", result.outputPath);
Pin an agent instead of a workflow
entity_refs=[{"name": "my-sre-agent", "type": "agent"}]
entityRefs: [{ name: "my-sre-agent", type: "agent" }]
Valid type values: workflow, agent, integration, knowledge, or any.
Agent query without pinning (interactive only)
Omitting entity_refs lets Aiden choose among candidates. That is fine for
exploratory chat; for pipelines, always pin a workflow or agent.
Waiting for a session
A session is created when Aiden starts handling your request. You need
session_id to fetch artifacts and to continue a conversation.
When do you get session_id?
| Path | When |
|---|---|
| Webhook trigger | In the POST response |
| Ask start | In the start response; execution poll is for completion, not discovery |
Ask — step by step (start → wait → optional download)
Advanced control when you want to branch between “started” and “finished”:
Python
start = client.aiden.start_ask(
"Run triage for checkout-api error rate alert",
entity_refs=[{"name": "incident-triage", "type": "workflow"}],
)
trace_id = start["trace_id"]
session_id = start.get("session_id")
print("started", trace_id, session_id)
# Block until execution is finished
trace = client.aiden.wait_for_execution(trace_id)
session_id = session_id or trace.get("session_id")
print("settled", trace["execution"]["status"], session_id)
TypeScript
const start = await client.aiden.startAsk(
"Run triage for checkout-api error rate alert",
{
entityRefs: [{ name: "incident-triage", type: "workflow" }],
},
);
const traceId = String(start.trace_id ?? "");
let sessionId = String(start.session_id ?? "");
console.log("started", traceId, sessionId);
const trace = await client.aiden.waitForExecution(traceId);
if (!sessionId) {
sessionId = String(trace.session_id ?? "");
}
console.log("settled", (trace.execution as { status?: string }).status, sessionId);
If start_ask returns inputs_required, the workflow needs more fields — pass them
via inputs={...} / inputs: { ... } or fix your message; the SDK raises
StackgenError on the one-shot helper.
Webhook — step by step
See Webhook → session → artifact for full Python and TypeScript scripts. Minimal CLI shape:
export WEBHOOK_TOKEN='sg_aios_…'
python webhook-wait-session.py \
--base-url https://app.stackgen.com \
--api-token stackgen_… \
--org-id 4f942a41-… \
--json-body \
--query-file alert.json
# prints session_id=… when ready
Download session artifacts
After you have session_id, the full journeys download session-report.md
by default. Customize:
client.aiden.run_ask_and_download_artifact(
"…",
entity_refs=[{"name": "incident-triage", "type": "workflow"}],
artifact_name="session-report.md",
output_path="./out/report.md",
)
await client.aiden.runAskAndDownloadArtifact({
message: "…",
entityRefs: [{ name: "incident-triage", type: "workflow" }],
artifactName: "session-report.md",
outputPath: "./out/report.md",
});
Artifact name matching is case-insensitive.
When no artifact file is present, export the session write-up:
Python
export = client.aiden.export_session(session_id, parts="report")
TypeScript
await client.aiden.exportSession(sessionId, { parts: "report" });
Search or cancel long runs from a scheduler:
Python
client.aiden.list_sessions(q="corr-123")
client.aiden.terminate_session(session_id, reason="scheduler timeout")
client.aiden.list_executions(session_id=session_id)
TypeScript
await client.aiden.listSessions({ q: "corr-123" });
await client.aiden.terminateSession(sessionId, { reason: "scheduler timeout" });
await client.aiden.listExecutions({ session_id: sessionId });
For SRE Copilot investigate-from-alert (alert already in the SRE app), see SRE → investigate alert and Automation surface.
Runnable examples
Full scripts with syntax highlighting are on the Code samples page — copy directly from your browser; no separate download required.
| Sample | Language | What it demonstrates |
|---|---|---|
| Webhook → session (step-by-step) | Python | Trigger → read session_id → optional download |
| Webhook → report (one call) | TypeScript | One-call webhook journey |
| Ask → report (CLI) | Python | Ask → poll → download |
| Ask → execution only | Python / TypeScript | Start + wait for execution |
Errors and timeouts
| Error | Meaning |
|---|---|
StackgenError |
Business failure (bad trigger, execution error, missing inputs, …) |
TimeoutError |
Poll exceeded timeout_seconds (session, execution, or artifact) |
HttpError |
HTTP status failure (check token and org_id) |
GET polling retries transient 429, 502, 503, 504. Trigger POST is not
retried automatically (avoid duplicate runs).
FAQ
Common questions about installation, tokens, webhooks, inputs/outputs, retries, and operational limits are answered in the dedicated FAQ (Guild + SRE use cases).
Quick picks
| Question | Answer |
|---|---|
| Webhook or Ask? | Webhook when you have sg_aios_… and alert payloads; Ask when you have only an API token and a message (pin with entity_refs in CI). |
| Why two tokens? | Webhook token starts automation; API token reads sessions and artifacts. |
| Live progress? | Polling only in this SDK — use the StackGen UI for live traces. |
| Full API list? | Product map |