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

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

  1. SDK POSTs your alert text/JSON to /guild/api/v1/webhooks/trigger?orgId=…
  2. Aiden starts the target workflow. Newer motherships may return session_id on the 202 body; otherwise the SDK polls GET /webhooks/{webhook_id}/runs/{invocation_id} until session_id is set (same as Guild’s reference script).
  3. SDK waits until session-report.md (or your artifact name) appears
  4. SDK downloads the file to output_path

For queue + scheduler architectures, use stateless methods (trigger_webhook, wait_for_webhook_session, …) — see Async webhook CI.

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:

  1. POST the webhook (JSON or plain text)
  2. Read session_id from the 202 body when present, or poll run detail with wait_for_webhook_session
  3. 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

  1. SDK POSTs to /guild/api/v1/guild/ask/start?orgId=… with message (+ optional entity_refs)
  2. Response includes trace_id and usually session_id
  3. SDK polls /guild/api/v1/executions/{traceId} until status is terminal and trace_settled
  4. 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.

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