Workflows (/app/workflows) lists graph workflows and workflow chains together with All | Draft | Live filters. One New workflow dialog creates either type. Graph shells live at /app/workflows/graph/{id}/…; chain shells at /app/workflows/chain/{slug}/…. Sidebar badge counts both. Nothing is auto-seeded.

Landing page
- Orchestrations header with primitives legend (trigger, assistant, agent, decide, webhook, schedule, notify, human).
- chain them! design cue for composing chains.
- Unified cards — graph and chain rows share one grid; click opens the immersive shell default tab.
- New workflow — modal: name + type (Workflow graph | Workflow chain); POST /v1/workflows or POST /v1/workflow-chains.
- Filters — Draft/Live use graph publish state and chain status (draft | live | paused).

Access control
Workflow APIs use capability-based RBAC (mapped to workspace roles). Chain and graph routes no longer rely on coarse role checks alone.
| Capability | Minimum role | Used for |
|---|---|---|
| workflow.read | Viewer | List/read workflows and chains, validate-publish, paginated history |
| workflow.write | Editor | Create/update workflows, chains, save graph drafts |
| workflow.publish | Developer | Publish, delete workflows, restore versions |
| runtime.simulate | Editor | Simulator sessions, chain run/resume/ingress (studio) |
| runtime.sessions.read_all | Developer | Cross-agent session lists (assistant simulator) |
Workflow chains
Implementation path
- Choose a chain when the process can be described as ordered primitives; choose a graph workflow when visual routing and node-level branching matter.
- Name every step for the business action it performs, then bind Assistants, AI Agents, tools, and webhook endpoints.
- Add decide branches and human pauses before publish so exceptional paths are represented explicitly.
- Run the chain or workflow simulator, inspect run history, and verify ingress HMAC before external callers are connected.
- Set chains live only after the Deploy readiness panel clears every blocker.
Chains are edited in a dedicated form editor (not the React Flow canvas). PATCH /v1/workflow-chains/{slug} persists all fields. Run history is available per chain via GET /v1/workflow-chains/{slug}/runs and GET .../runs/{run_id}.

| Field | Description |
|---|---|
| name | Display name on the card |
| status | draft | live | paused |
| summary | One-line description on the card |
| when_label | Trigger description (e.g. On webhook received) |
| primary_steps | Ordered list of { kind, label, config } primitives |
| branches | Named branches each with their own step list |
Chain primitives
- trigger — entry condition label
- assistant — invoke a published Assistant by label/slug match
- agent — invoke an AI Agent (playground runtime) by label
- decide — branch on a condition label (substring match on running output)
- webhook — outbound HTTP POST/PUT/PATCH (url, secret, retries in step config); secret also used for inbound HMAC verification
- human — pauses run as awaiting_human until POST .../runs/{run_id}/resume
- schedule — records deferred-execution intent (external scheduler)
- notify — email via Resend/SMTP/console to email_to in config
Chain run & ingress
- POST /v1/workflow-chains/{slug}/run — studio test run (runtime.simulate, rate-limited)
- POST /v1/workflow-chains/{slug}/runs/{run_id}/resume — continue awaiting_human runs
- POST /v1/workflow-chains/{slug}/ingress — authenticated inbound webhook (HMAC + runtime.simulate)
- POST /v1/public/workflow-chains/{workspace_slug}/{chain_slug}/ingress — public inbound webhook (HMAC only, no cookie)
- POST/GET /v1/workflow-chains/{slug}/deployments — embed tokens scoped to a chain (workflow_chain_id on agent_deployments).
- Ingress and deployments require chain status live plus readiness validation; draft, paused, and invalid chains return 409.
- Channel connections may set workflow_chain_id; inbound omni-channel messages dispatch through execute_chain when the chain is live.
- Sign the raw JSON body with HMAC-SHA256 using the webhook step config.secret; send header X-Chain-Signature (hex or sha256=<hex>). Body: {"message": "..."}.
Legacy workflow graph
Graph workflows open at /app/workflows/graph/{id}/graph (Flow Canvas). Legacy /app/workflows/{id}/… URLs redirect into the graph shell. Draft graphs are saved with PUT /v1/workflows/{id}/graph (creates a new draft version). Publishing promotes the latest draft to a live version.
Unified workflow shell (graph and chain)
| Tab | Graph route | Chain route | Purpose |
|---|---|---|---|
| Graph / Chain | /graph | /chain | Design canvas or primitive step editor |
| Assistants | /assistants | — | Bind published Assistants (graph only) |
| Agents | /agents | — | Instruction-agent nodes (graph only) |
| Tools | /tools | /tools | Workspace tools catalog |
| Import / Export | /import, /export | — | Workflow JSON backup (graph only) |
| Deploy | /publish | /publish | Publish graph or set chain live/paused |
| Channels | /channels | /channels | Omni-channel deploy; chains also show webhook ingress |
| Playground | /playground | /playground | Simulator or chain run + trace |
| Conversations | /convos | /convos | Session history or chain runs |
| Events | /events | — | Welcome, fallback, and no-input event configuration |
| Analytics | /analytics | /analytics | Rollups and chain run stats |
| History | /history | — | Full session transcript explorer |
| Settings | /settings | — | Graph workflow metadata |

Publish & versions
- POST /v1/workflows/{id}/validate-publish — schema + runtime publish rules (Studio calls this before Publish)
- POST /v1/workflows/{id}/publish — promotes latest draft (workflow.publish)
- GET /v1/workflows/{id}/versions — list versions with limit/offset
- POST /v1/workflows/{id}/versions/{version_id}/restore — copy an older graph into a new draft
- Blocked node types at publish: script, datastore, set, human, parallel, wait
- Router/decision nodes must have at least one outgoing edge with condition.expr
Rate limits
Workspace Agent ops setting rpm_cap_per_agent applies per workflow id and per chain id for simulator starts, workflow turns, and chain run/resume/ingress (Redis-backed when Redis is available; 0 = unlimited). Additional slowapi limits apply on graph save, publish, restore, and chain endpoints.
Workflow vs single Assistant
| Assistant | Workflow | |
|---|---|---|
| Scope | One bot, intent sub-flows | Multi-bot orchestration graph or primitive chain |
| Editor | Intents + per-intent canvas | Workflow flow canvas or chain editor |
| Publish | Assistant Publish tab | Workflow Publish tab + validate-publish |
| Typical pattern | Single channel widget | Agent qualifies → Assistant runs regulated form |
API (summary)
# Workflow chains
GET/POST /v1/workflow-chains
GET/PATCH/DELETE /v1/workflow-chains/{slug}
POST /v1/workflow-chains/{slug}/run
GET /v1/workflow-chains/{slug}/runs
GET /v1/workflow-chains/{slug}/runs/{run_id}
POST /v1/workflow-chains/{slug}/runs/{run_id}/resume
POST /v1/workflow-chains/{slug}/ingress
POST /v1/public/workflow-chains/{workspace_slug}/{chain_slug}/ingress
# Legacy graph workflows
GET/POST /v1/workflows
GET/PATCH/DELETE /v1/workflows/{id}
PUT /v1/workflows/{id}/graph
POST /v1/workflows/{id}/validate-publish
POST /v1/workflows/{id}/publish
GET /v1/workflows/{id}/versions
POST /v1/workflows/{id}/versions/{version_id}/restore
# Workflow simulator & history
POST /v1/runtime/workflows/{id}/sessions
POST /v1/runtime/workflows/sessions/{session_id}/turns
GET /v1/runtime/workflows/{id}/sessions?limit=&offset=See Workflow canvas and Chain editor pages for node types, edge routing, and simulator behavior. Public workflow channel traffic uses deployment tokens via /v1/public/runtime/* (see Channels & deploy).