Workflow reference
Operations, permissions, limits and errors. Keep this beside your code.
Start with the complete SDK example. All paths below are relative to /v1/workflows; use your project key on the backend. MCP clients should load STACKLINK_WORKFLOWS → contract for exact schemas.
Definitions and publication
| TypeScript / Python | REST | Purpose |
|---|---|---|
list | GET / | Page through definitions (limit, cursor, search) |
create | POST / | Create a draft |
get / update | GET / PATCH /:id | Read/edit with the current revision |
validate | POST /validate | Check a typed definition |
publish | POST /:id/publish | Publish graph and draft triggers together |
versions | GET /:id/versions | Inspect published setups |
setState / set_state | POST /:id/state | Set { paused } |
source: "visual" permits canvas editing. "code" makes the canvas read-only. Set it explicitly: Python defaults to code; the backend defaults to visual. Optional deployment records repositoryUrl (HTTPS), commit and definitionKey.
A duplicate name receives (1), (2), etc. Keep the returned ID and saved name. Creating again is not updating.
Runs and recovery
| TypeScript / Python | REST |
|---|---|
run | POST /:id/runs |
runs | GET /:id/runs |
getRun / get_run | GET /:id/runs/:runId |
events | GET /:id/runs/:runId/events |
action | POST /:id/runs/:runId/actions |
Public starts require sessionId and jobKey. mode is simulation or live; purpose is test or operational. A draft test also supplies revision. Samples are keyed by node ID. If supplied, Idempotency-Key must match jobKey.
Lists return runs and nextCursor. Events use before for the next page. Save workflow/run IDs; one getRun() does not wait for completion.
// IDs come from the saved run and selected step, never their display names.
const current = await stacklink.workflows.getRun(workflowId, runId);
await stacklink.workflows.action(workflowId, current.id, {
action: 'reconcile', nodeId,
});Actions: retry, reconcile, confirm, repeat, signal, cancel. Confirm/repeat need a reason; signals supply event and value. Read the recovery rules before choosing one. A fresh run uses run() with a new key.
Run status values
queued, running, waiting, waiting_for_approval, retrying, needs_attention, failed, completed, cancel_requested, cancelled.
Waiting and needs-attention are not completion. A recovered failed run remains the same run. Historical run definitions are immutable even while the current draft changes.
Triggers
| TypeScript / Python | REST |
|---|---|
triggers | GET /:id/triggers |
saveTrigger / save_trigger | POST /:id/triggers |
deleteTrigger / delete_trigger | DELETE /:id/triggers/:triggerId |
invokeTrigger / invoke_trigger | POST /:id/triggers/:triggerId/invoke |
previewSchedule / preview_schedule | POST /schedule/preview |
Read returns revision, draft triggers and liveTriggers. Save/delete require expectedRevision (Python: expected_revision); publish the returned revision to activate. Invocation uses requestId and input; its optional idempotency header must match requestId. Examples →
Drafting and mentions
searchMentions / search_mentions searches the permitted catalog before paging. Query: search, optional workflowId / kind, offset, limit. Each group returns total and nextOffset.
resolveMentions / resolve_mentions rechecks exact references. suggest(id, description, revision, sessionId, mentions?) returns a proposal, not an applied change. Use update() to accept a reviewed definition.
| Reference | Shape |
|---|---|
| App, Bot or workflow | { kind, id } with kind app, bot or workflow |
| Saved API operation | { kind: "api", id, callId } |
| Mention in a description | { reference, start, end } |
Offsets are UTF-16 positions; end is exclusive. Ranges must not overlap or split a surrogate pair. Server-side resolution rechecks identity and access; labels or pasted chips cannot grant authority. Mention APIs require server SDK 0.6.3 or later.
Permissions
| Scope | Use |
|---|---|
workflows:read | Inspect permitted definitions and runs |
workflows:manage | Author, publish and manage triggers/settings |
workflows:run | Submit runs and request recovery; action-specific checks still apply |
sessions:create, sessions:read | Create and inspect the execution identity |
tools:execute, connection/Bot/Memory scopes | Required by the actual steps you choose |
billing:read | Authorized financial reporting |
Project membership, customer ownership and step-specific policy still apply. A scope does not create an app connection or grant somebody else’s account. Embedded roles and approvals →
Limits
| Setting | Current limit |
|---|---|
| Graph | 200 nodes; 500 edges; no cycles |
| Code step | 1 second–10 minutes; default 60 seconds |
| Automatic attempts | 1–10; default 3 including the first try |
| Timer / event / approval / form wait | Up to one year |
| Workflow concurrency | 1–100 per customer; default 10 |
| Record concurrency | Default 1 when a record key is used |
| For each | Up to 1,000 items; concurrency up to 20 |
| Nested executions | Maximum child depth 10; recursive calls blocked |
| Schedule interval | Minimum five minutes |
| Remove-duplicates retention | 1–365 days; default 30 (separate from run job keys) |
Common errors
| Code | Next step |
|---|---|
api_key_scope_missing | Check the key’s required scope |
workflow_not_published | Publish, or explicitly select a draft revision for a test |
workflow_revision_changed | Reload the current draft and review conflicting changes |
workflow_job_key_conflict | Reuse the original request; use a new key only for new work |
workflow_mention_unavailable | Choose an accessible resource again |
workflow_record_key_missing | Supply the configured record field |
workflow_api_revision_changed | Select the current saved API operation revision |
workflow_not_found / workflow_run_not_found | Check identity, ownership and ID |
approval_not_assigned | The authenticated person is not assigned this task |
The embedded browser maps missing/inaccessible workflows and runs to workflow_unavailable. Do not try another customer’s context as a fallback.