Frequently asked questions
Answers for Aiden, SRE, DevOps, and Context Graph integrations using the StackGen SDK. For step-by-step samples see the Aiden guide and code samples.
Package installation and versioning
Which packages should I install?
| Language | Install | Import |
|---|---|---|
| Python | pip install stackgen-sdk==0.4.0 |
from stackgen import StackgenClient, StackgenConfig |
| TypeScript / Node 18+ | npm install stackgen-sdk@0.4.0 |
import { StackgenClient, StackgenConfig } from "stackgen-sdk" |
| Go (invite-only) | go get github.com/appcd-dev/stackgen-sdk/clients/go@v0.4.0 |
stackgen "github.com/appcd-dev/stackgen-sdk/clients/go" |
The PyPI/npm distribution name is stackgen-sdk; the Python import name is stackgen. Prefer the Go facade (stackgen.NewClient) over the generated client under clients/go/generated.
Go is invite-only while the SDK repository is private. Ask StackGen for GitHub access before go get; anonymous pulls fail. Python and TypeScript remain on public PyPI and npm.
Go today covers webhook → report, agent chat + SSE, workspaces, integrations, and Vault. Ask wait helpers, SRE investigate, chat subscriptions, audit export, and workflow builder remain on Python/TypeScript for now; more Go journeys are coming.
How should I pin versions in CI?
Always pin an exact release in pipelines (== for pip, @ for npm). The SDK exposes a
curated allowlist of HTTP operations per release — upgrading without reading the
Product map can surface
NotAllowlistedError for calls that are not yet in your pinned version.
How do I try a release candidate?
Every merge to main publishes a new RC so you can preview the next SDK before
it becomes the default install.
pip install stackgen-sdk==0.4.0rc1
npm install stackgen-sdk@0.4.0-rc.1
# or the moving npm preview pointer
npm install stackgen-sdk@next
Plain pip install stackgen-sdk and npm install stackgen-sdk stay on the last
stable release. Use pip install --pre stackgen-sdk only when you want pip to
consider pre-releases. See the Changelog
for what the preview includes.
What is included in the current release (v0.1.5)?
- Aiden — webhook trigger, Ask, session artifacts, high-level
run_webhook_and_download_reportandrun_ask_and_download_artifactjourneys - SRE — pull alerts, investigate and wait for RCA, triage
- DevOps — Ops Inbox sync, approve and wait, workflow discovery
- Vault — secrets (allowlisted separately)
- Context Graph — health, records, schema, connectors/syncs, graph search
See Product map → Public API surface for the full list.
Authentication and token management
What credentials do I need?
| Field | Example | Used for |
|---|---|---|
base_url |
https://app.stackgen.com |
Mothership host — no /guild suffix |
workspace_id |
Workspace UUID | Sent as orgId on Aiden routes (formerly org_id) |
api_token |
stackgen_… |
Sessions, artifacts, Ask, SRE reads/writes |
webhook_token |
sg_aios_… |
Only POST /webhooks/trigger |
SRE calls use the API token and base_url only (no webhook token, no separate SRE secret in this SDK).
Why two tokens for webhook automation?
Least privilege for CI secrets:
- Webhook token — permission to start automation (ring the doorbell).
- API token — permission to read sessions, poll executions, and download artifacts.
Store them in separate secret managers or CI variables when possible.
Can I use environment variables?
Optional convenience for the three core fields:
| Env var | Config field |
|---|---|
STACKGEN_URL |
base_url |
STACKGEN_TOKEN |
api_token |
STACKGEN_WORKSPACE_ID |
workspace_id (older STACKGEN_PROJECT / STACKGEN_ORG_ID still work) |
STACKGEN_LOG_LEVEL |
log_level / logLevel (debug, info, warn, error, silent) |
Use StackgenConfig.from_env() (Python) or StackgenConfig.fromEnv() (TypeScript), then set
webhook_token, poll timeouts, and artifact paths in code. For production pipelines,
prefer explicit StackgenConfig so every run is self-describing in logs.
webhook_token is not loaded from a default env var — pass it explicitly when using webhook helpers.
How do I enable SDK logs?
The SDK stays quiet by default (library-friendly). Turn levels on when debugging:
export STACKGEN_LOG_LEVEL=debug # or info / warn / error
Python uses the stdlib logger named stackgen (children like stackgen.http).
You can also call configure_logging("debug") or set log_level= on
StackgenConfig. TypeScript accepts logLevel / a custom logger on config.
At debug you see each HTTP attempt (URLs with tokens redacted). Retries and
subscribe reconnects log at warn. Failures log at error before the SDK
raises.
Where do I get tokens and the workspace UUID?
Create API tokens and webhook tokens in the StackGen UI for your workspace. The workspace UUID
is the workspace_id / workspaceId value (sent as orgId on Aiden API calls). If you see 401/403 from Aiden routes,
verify the token type matches the operation (webhook vs API) and that workspace_id matches the
workspace where the workflow is registered.
Webhook configuration
What must exist in Aiden before I call the SDK?
- A workflow registered in Aiden (for example
incident-triagefor alert triage). - A webhook mapped to that workflow, with a
sg_aios_…token issued for CI or your alerting tool.
The SDK can create agents and workflows in code (Create a workflow). Webhook tokens and mappings still come from Aiden after a webhook resource exists; for day-2 triggers you need a registered webhook pointing at the workflow you published.
What payload should I send?
The trigger POST accepts plain text or JSON (your alert body):
P1 | checkout-api error rate above SLO
Or structured JSON from Datadog, Grafana, or an internal alert bus. The SDK sends
Content-Type: text/plain with the bytes you provide; match what your webhook expects
when testing with curl.
What does the trigger response include?
On success the mothership returns JSON including at least:
| Field | Meaning |
|---|---|
webhook_id |
Webhook identifier |
invocation_id |
Invocation row id for run polling |
run_id |
Temporal dispatch workflow run id (older builds) |
session_id |
Session workspace — may appear on the acknowledgement body on newer motherships |
trace_id |
Execution trace — may appear on the body or after polling |
The HTTP status of that acknowledgement defaults to 202 Accepted. When you create
the webhook you can set response_status to 200, 201, 202, or 204, plus optional
response_headers, so providers that reject 202 (for example Linear) stay happy while
Aiden still processes asynchronously. See
Webhook acknowledgement (Linear-style).
Dual-path contract: If session_id is on the acknowledgement body, the SDK uses it immediately.
If not, run_webhook_and_download_report polls
GET /webhooks/{webhook_id}/runs/{invocation_id} until session_id is set.
The same sequence is in the
webhook session artifact script.
How do I stop a webhook from starting work for every delivery?
Set filter_cel on the webhook — a CEL
boolean expression over body (decoded JSON) and headers (sanitized,
lowercase). A delivery that evaluates to false still gets the configured
acknowledgement, but starts no run, writes no invocation row, and spends no
AI-query quota. Clear it with an explicit empty string on update_webhook /
updateWebhook; leaving the field out of an update keeps the current
condition. Try a draft condition against sample JSON and headers with
preview_webhook_filter / previewWebhookFilter before you save it — preview
never saves data or starts work. See
Webhook condition (filter_cel).
For split workers (queue + scheduler), use stateless methods on client.aiden:
trigger_webhook, get_webhook_run, wait_for_webhook_session, download_session_artifact.
See Async webhook CI.
Can Datadog or Grafana call the webhook directly?
Yes — that is the common SRE pattern: the observability tool POSTs to the webhook URL with
the sg_aios_… token. Use the SDK when your CI job (Jenkins, GitHub Actions, custom
runner) needs to trigger triage and wait for session-report.md in one script.
What about app-forward webhooks?
The wait/download journey targets Aiden session artifacts. App-forward or non-session
webhook flows are outside the SDK’s run_webhook_and_download_report helper — use lower-level
API calls or the StackGen UI for those paths.
End-to-end integration examples
Alert → triage report (webhook path)
Typical SRE pipeline:
- CI or alert router receives
P1 | checkout-api error rate above SLO. - Script calls
run_webhook_and_download_report(payload). - Pipeline uploads
session-report.mdto the ticket, Slack, or object storage.
Sample: Webhook → session → artifact
Natural language → triage report (Ask path)
When you only have an API token:
- Pin workflow:
entity_refs=[{"name": "incident-triage", "type": "workflow"}]. - Call
run_ask_and_download_artifact(message=…). - Consume
session-report.mdfromoutput_path.
Sample: Ask → artifact
Trigger only — handle download elsewhere
Use Webhook → session only
when another system owns artifact retrieval or you only need session_id for logging.
SRE alerts and investigations
List firing alerts, refresh the inbox, or start an investigation — API token only.
Prefer investigate_alert_and_wait so the SDK polls until the RCA is ready.
Python
client.sre.pull_alerts_and_wait(source="grafana")
alerts = client.sre.list_alerts(status="active", q="checkout CPU")
rows = alerts.get("alerts") or alerts.get("items") or []
inv = client.sre.investigate_alert_and_wait(rows[0]["id"])
# optional guild_session_id for Aiden artifacts
TypeScript
await client.sre.pullAlertsAndWait("grafana");
const alerts = await client.sre.listAlerts({ status: "active", q: "checkout CPU" });
const rows = ((alerts as { alerts?: Array<{ id: string }> }).alerts) ?? [];
const inv = await client.sre.investigateAlertAndWait(rows[0].id);
Sample: SRE → investigate alert · Pull alerts · Triage alerts
DevOps Ops Inbox
Sync tickets, wait for triage, approve a request, and discover workflows from
recent ticket history on client.devops.
Sample: Sync Ops Inbox · Approve request · Discover workflows
Context Graph
Probe health, read the schema catalog and record types, sync connectors, and
search graph tools on client.contextGraph / client.context_graph. Override
the edge prefix with contextGraphUrl / context_graph_url for local or
port-forward runs (default ${STACKGEN_URL}/context-graph).
Sample: Context Graph inventory
See Usage → Namespaces.
Runnable CLI scripts
Full flag-based examples live under Code samples (Python and TypeScript toggles on each journey page).
Expected inputs and outputs
Webhook journey (run_webhook_and_download_report)
| Input | Alert string or JSON file contents; config with webhook_token, api_token, workspace_id, optional artifact_name, output_path, timeout_seconds |
| Output | webhook_id, invocation_id, session_id, artifacts (listed metadata), output_path (local file) |
Ask journey (run_ask_and_download_artifact)
| Input | message; entity_refs (recommended in CI); optional inputs when workflow needs extra fields; API token only |
| Output | trace_id, run_id, session_id, plan, candidates, artifacts, output_path |
Ask start / wait (step-by-step)
| Step | API | Key response fields |
|---|---|---|
| Start | start_ask / startAsk |
trace_id, session_id, optional inputs_required |
| Poll | wait_for_execution / waitForExecution |
execution.status, trace_settled, session_id |
| Artifact | listSessionArtifacts + download |
File bytes at output_path |
| Subscribe wait | waitForSubscribeComplete |
ok when the run finishes (SSE with reconnect) |
Samples: Ask → execution, Ask → session artifacts · Ask → debug ZIP
Queue / scheduler (non-blocking)
Workers that must return immediately (submit on one process, poll from another)
should not call run_ask_and_download_artifact or wait_for_execution on the
submit path.
| Step | API | Blocks? |
|---|---|---|
| Start | start_ask / start_workflow_run |
no — persist session_id + trace_id |
| Follow-up | get_run_status(session_id=…, trace_id=…, ready_artifact="session-report.md") |
no — one shot |
| Download | download_session_artifact when ready |
no |
get_run_status / getRunStatus is the stateless “what’s the status of run X?”
primitive for a separate scheduler. Locks, stale detection, and retries stay in
your application code.
Sample: Async Ask worker
SRE namespace
| Method | Input | Output |
|---|---|---|
list_alerts() |
Optional query params | Alert list (JSON) |
get_alert(id) |
Alert id | Alert detail |
investigate_alert(id, body?) |
Alert id, optional body | Investigation start payload |
list_investigations() |
Optional filters | Investigation list |
get_investigation(id) |
Investigation id | Investigation detail |
Default artifact
Most triage workflows publish session-report.md — markdown RCA/summary. Override with
artifact_name / artifactName; matching is case-insensitive.
Error handling and retry behavior
What errors can the SDK raise?
| Error | When |
|---|---|
StackgenError |
Business failures — bad trigger body, missing session_id, Ask inputs_required, execution ended in error, unexpected JSON |
HttpError |
HTTP failure with statusCode when available — wrong token, wrong workspace_id, 404 workflow |
TimeoutError |
Poll exceeded timeout_seconds while waiting for session artifact, Ask execution, or similar |
NotAllowlistedError |
Method not in this SDK release (e.g. Vault) |
ValueError |
Missing required config such as webhook_token on webhook helpers |
What is retried automatically?
- Gateway 502/503/504 and transport errors (every method, including POST):
retry until the wall-clock budget elapses (default 120s via
STACKGEN_TRANSIENT_RETRY_BUDGET_MS/transient_retry_budget_ms). A CloudFront 502 means the edge never delivered the request. Passretry_gateway_outage=False/retryGatewayOutage: falseto fail fast instead. Go useshashicorp/go-retryablehttpwith the same policy by default. - GET (and other idempotent methods): also retry up to 3 attempts on
429, application5xx, and network errors, with exponential backoff (capped at 8 seconds). Poll loops (wait_for_execution, artifact waits, subscribe confirmation) use one attempt per tick and keep retrying insidetimeout_seconds. - Application 500 on POST/PATCH: fail fast (not a gateway drop).
How do timeouts work?
Config fields:
| Field | Default | Purpose |
|---|---|---|
poll_interval_seconds |
5 |
Sleep between poll ticks |
timeout_seconds |
1800 (30 min) |
Max wait for artifact or Ask execution |
Raise TimeoutError when exceeded. Increase timeout_seconds for long-running triage
workflows; decrease in fast-fail CI smoke tests.
Ask-specific failures
inputs_requiredin start response — workflow needs more structuredinputs; fix the message or passinputs={...}. One-shot helpers raiseStackgenError.execution.status=errorafter poll — workflow failed; inspect trace in StackGen UI; SDK raises on the download helper path.
Report retrieval and consumption
How does the SDK get session-report.md?
After session_id is known:
- Poll
listSessionArtifactsuntil the named artifact appears. - Download via
downloadSessionArtifacttooutput_path.
High-level helpers combine trigger/Ask + wait + download in one call.
If the workflow did not write an artifact file, call export_session(session_id, parts="report")
and read the report part content from the JSON manifest.
Where is the file written?
Default output_path is session-report.md in the process working directory. Set per run:
Python
StackgenConfig(..., output_path="./artifacts/incident-123/report.md")
TypeScript
new StackgenConfig({ ..., outputPath: "./artifacts/incident-123/report.md" });
How should SRE teams consume the report?
Common patterns:
- Attach the markdown file to PagerDuty, Jira, or ServiceNow.
- Upload to S3/GCS for audit retention.
- Parse sections (summary, timeline, recommendations) in a downstream linter — the SDK delivers raw file bytes; parsing is application-specific.
- Link
session_idin your ticket so operators can open the live session in StackGen UI.
Can I list artifacts without downloading?
Yes — use session helpers or listSessionArtifacts when you need metadata only, or when
multiple artifacts exist (logs bundle, structured JSON, etc.). The default journey targets
one named artifact.
Operational considerations and limitations
Polling and subscribe waits
Most status helpers use HTTP polling (CI-friendly). For Ask and webhook
runs you can also call wait_for_subscribe_complete /
waitForSubscribeComplete, which opens the execution subscribe stream (SSE)
and reconnects on drop or quiet stalls inside your timeout. Use the StackGen UI
when you want a live human-facing trace view.
To render reply text and tool calls in your own chat UI, use
stream_execution_events / streamExecutionEvents instead of waiting for
completion. See
Stream agent chat.
Curated API surface
The SDK wraps a subset of StackGen HTTP APIs. Calls outside the allowlist fail fast with
NotAllowlistedError. Regenerate or upgrade the SDK when new operations are added to the
product OpenAPI spec. Download the current allowlisted surface as
stackgen.openapi.yaml.
Mothership and workflow prerequisites
- Workflow and webhook must already exist in the target workspace.
base_urlmust be the mothership root (e.g.https://app.stackgen.com), not a path under/guild.workspace_idmust match the workspace where the workflow is registered.
Idempotency and duplicate runs
Each successful webhook POST starts a new workflow invocation. Do not blindly retry failed POSTs without an idempotency strategy. GET polls and downloads are safe to retry.
Exception: terminate_session / terminateSession is idempotent on the Aiden API
(no running workflows returns 200; cancellation intent is persisted before Temporal).
The SDK retries that call through a shared idempotent mutation policy
(retry_idempotent_op / retryIdempotentOp) on transient 5xx/429/network errors.
Subscribe waits use a separate reconnect policy (SUBSCRIBE_RECONNECT_MAX) for dropped
SSE streams. Webhook and workflow start POSTs are not covered by either policy.
Long-running and concurrent workflows
Default 30-minute timeout suits typical triage. Very large investigations may need a higher
timeout_seconds. Parallel CI jobs each get their own session_id; there is no global
queue limit enforced by the SDK.
Secrets hygiene
- Never commit tokens; use CI secret stores.
- Rotate API and webhook tokens independently.
- Scope webhook tokens to the minimum webhook entry points required.
Vault
Prefer client.aiden.upsert_integration_with_secrets /
upsertIntegrationWithSecrets when provisioning an integration from a vendor
token. Pass a plain secrets map; the SDK resolves Vault metadata keys, stores
the secret, and binds secret_ref_ids. Override with vault_category /
vault_subcategory when needed. For a granular path, use
client.vault.get_supported_metadata, store_secret / store_github_secret
(and grafana / kafka / generic helpers), then upsert_integration with
secret_ref_ids, and get_secret / delete_secret. Soft-ignore 404 on delete
stays in your teardown
code, not in the SDK.