Workflows & Architect API
Workflow definition CRUD, run lifecycle, approvals, and the AI-assisted Architect panel.
This page documents the gateway endpoints that manage workflow definitions and workflow runs, plus the Architect panel that proposes AI-assisted revisions to a workflow. These are the routes the dashboard’s Workflows pages call, and they are what you script when you want to create, run, approve, retry, or monitor workflows without clicking through the UI.
Workflow definitions are declarative YAML pipelines stored in Kumiho graph memory and executed by the operator-mcp backend. If you are writing the YAML itself, start with Your first workflow and the Workflow YAML reference; this page covers the HTTP surface around it. For the dashboard equivalents, see Workflows, editor & runs.
Authentication
Section titled “Authentication”Every route on this page requires the pairing bearer token:
Authorization: Bearer <token>Obtain the token through the flow in Pairing & authentication. A missing or invalid token returns 401. Most routes share the gateway’s default 64 KiB JSON body cap and request timeout, with two exceptions called out below: POST/PUT on workflow definitions accept a 16 MiB body (real workflows can exceed 64 KiB), and operator-tool-backed routes (run, approve, retry, cancel, Architect) each have a fixed operator timeout.
How storage works
Section titled “How storage works”Workflow definitions and run history live in Kumiho, not config.toml:
| Resource | Kumiho space | Item kind |
|---|---|---|
| Definitions | Revka/Workflows | workflow |
| Run history | Revka/WorkflowRuns | workflow_run |
| Run requests | Revka/WorkflowRunRequests | workflow-run-request |
Each definition is a Kumiho item whose latest published revision holds the metadata, with the YAML itself stored as a workflow.yaml revision artifact rather than inline metadata (to stay under Kumiho’s size limit). Every save writes a new revision and tags it published, so history is preserved and each run can be pinned to the exact revision it executed. The gateway creates the project and spaces lazily on first write.
Workflow definitions
Section titled “Workflow definitions”Endpoints
Section titled “Endpoints”GET /api/workflowsPOST /api/workflows (16 MiB body)PUT /api/workflows/{*kref} (16 MiB body)DELETE /api/workflows/{*kref}POST /api/workflows/deprecateGET /api/workflows/revisions/{*kref}The {*kref} segment expects the bare path after the scheme — for example Revka/Workflows/my-flow.workflow (no kref:// prefix). PUT and DELETE prepend the scheme themselves and will double it if you include it. The exception is GET /api/workflows/revisions/{*kref}, which does strip a leading kref:// prefix before looking up the item.
List definitions
Section titled “List definitions”GET /api/workflows?include_deprecated=false&include_definition=true&q=reportAuthorization: Bearer <token>| Query param | Type | Default | Meaning |
|---|---|---|---|
include_deprecated | bool | false | Include deprecated workflows in the result. |
include_definition | bool | true | Include the full YAML in each entry. Set false for a lighter list. |
q | string | — | Full-text search across definitions. |
Non-search list responses are served from a short in-process cache (about 30 s) to absorb dashboard polling, and the cache is invalidated on every write.
Create a definition
Section titled “Create a definition”POST /api/workflowsAuthorization: Bearer <token>Content-Type: application/json{ "name": "daily-report", "description": "Summarise yesterday and email the team.", "definition": "name: daily-report\nversion: \"1.0\"\nsteps:\n - id: summarize\n action: summarize\n agent:\n prompt: \"Summarise ${inputs.topic}.\"\n", "version": "1.0", "tags": ["reporting"]}| Field | Required | Meaning |
|---|---|---|
name | yes | Display name; slugified into the item identifier. |
description | yes | Human-readable purpose. |
definition | yes | The full workflow YAML, as a string. |
version | no | Semantic version label. |
tags | no | Classification list for search and filtering. |
Before persisting, the gateway validates the YAML by calling the operator’s validator (see Validation). On success it slugifies name, writes the metadata revision, stores the YAML as the workflow.yaml artifact, tags the revision published, and returns 201 Created with { "workflow": { ... } }. It also syncs cron jobs and broadcasts a workflow.revision.published event.
Update a definition
Section titled “Update a definition”PUT /api/workflows/Revka/Workflows/daily-report.workflowAuthorization: Bearer <token>Content-Type: application/jsonThe body has the same shape as create. An update writes a new revision (it never edits the old one in place), re-tags it published, re-syncs cron jobs, and broadcasts workflow.revision.published. Because old revisions are retained, in-progress and historical runs continue to display the YAML they actually executed.
Deprecate a definition
Section titled “Deprecate a definition”POST /api/workflows/deprecateAuthorization: Bearer <token>Content-Type: application/json
{ "kref": "kref://Revka/Workflows/daily-report.workflow", "deprecated": true }Deprecation is a soft toggle. Deprecated workflows are hidden from the default list (pass include_deprecated=true to see them) and their cron jobs are removed. Set "deprecated": false to restore the workflow and re-register its cron triggers.
Delete a definition
Section titled “Delete a definition”DELETE /api/workflows/Revka/Workflows/daily-report.workflowAuthorization: Bearer <token>Returns 204 No Content. This permanently removes the item and its cron jobs. Prefer deprecation when you only want to disable a workflow.
Fetch a specific revision
Section titled “Fetch a specific revision”GET /api/workflows/revisions/kref://Revka/Workflows/daily-report.workflow?r=3Authorization: Bearer <token>Returns { "workflow": { ... } } with the YAML pinned to that exact revision kref, independent of whatever is currently tagged published. The dashboard run viewer uses this to render the exact definition a run executed. A revision whose workflow.yaml artifact is missing returns 404.
Workflow runs
Section titled “Workflow runs”A run is one execution of a definition. Triggering a run creates a durable workflow-run-request item in Kumiho and immediately invokes the operator’s run_workflow tool for fast startup; if that direct call fails, the request item is still picked up by the operator’s listener. Run state is reported by overlaying local checkpoint data on top of the Kumiho run record, so progress stays current.
Endpoints
Section titled “Endpoints”GET /api/workflows/runsGET /api/workflows/runs/{run_id}POST /api/workflows/run/{name}POST /api/workflows/runs/{run_id}/approvePOST /api/workflows/runs/{run_id}/retryPOST /api/workflows/runs/{run_id}/cancelDELETE /api/workflows/runs/{run_id}Run statuses
Section titled “Run statuses”| Status | Meaning |
|---|---|
pending | Created but not yet picked up by the executor. |
running | The executor is active. |
paused | Waiting at a human-approval or human-input gate. |
completed | All steps finished successfully. |
failed | A step failed; the checkpoint is preserved so the run can be retried. |
cancelled | Stopped by a user or the system. |
stale | Non-terminal status with no checkpoint and no live lock (for example, after a redeploy wiped local state). |
List runs
Section titled “List runs”GET /api/workflows/runs?limit=20&workflow=daily-reportAuthorization: Bearer <token>| Query param | Type | Default | Meaning |
|---|---|---|---|
limit | int | 20 | Maximum number of recent runs to return. |
workflow | string | — | Filter to runs of a single workflow by name. |
Returns { "runs": [...], "count": N }, newest first.
Get one run
Section titled “Get one run”GET /api/workflows/runs/{run_id}Authorization: Bearer <token>Returns { "run": { ... } } with per-step detail. Live runs are read from the executor’s in-memory status; finished runs are resolved from the Kumiho run record. An unknown run_id returns 404.
Trigger a run
Section titled “Trigger a run”POST /api/workflows/run/daily-reportAuthorization: Bearer <token>Content-Type: application/json{ "inputs": { "topic": "AI safety" }, "cwd": "/path/to/project", "target_step_id": "summarize"}| Field | Required | Meaning |
|---|---|---|
inputs | no | Object mapping workflow input names to values. |
cwd | no | Working directory for shell/agent steps. |
target_step_id | no | ”Run to here” — execute only the transitive ancestors of this step, plus the step itself, then stop. |
The path segment is the workflow name (not a kref). The workflow is validated before dispatch; an invalid definition or an unknown target_step_id returns 400 with a validation-error body. On success the response is:
{ "run_id": "<uuid>", "workflow": "daily-report", "status": "pending" }Human approval gate
Section titled “Human approval gate”A workflow can pause at a human_approval step (defined in the YAML) until an operator approves or rejects. Resolve the gate with:
POST /api/workflows/runs/{run_id}/approveAuthorization: Bearer <token>Content-Type: application/json{ "approved": true, "feedback": "LGTM" }| Field | Required | Meaning |
|---|---|---|
approved | yes | true to continue the workflow, false to reject. |
feedback | no | Free-text note recorded with the decision. |
The gateway atomically claims the approval from an internal registry before resuming, so concurrent approvals (for example, a dashboard click and a Discord reply arriving at the same time) cannot double-resolve the gate. It then calls the operator’s resume_workflow tool, audits the decision, and broadcasts a human_approval_resolved SSE event. A successful call returns:
{ "status": "ok", "message": "Workflow approved", "run_id": "<uuid>", "approved": true }Retry a failed run
Section titled “Retry a failed run”POST /api/workflows/runs/{run_id}/retryAuthorization: Bearer <token>Content-Type: application/json
{ "cwd": "/path/to/project" }The body is optional. Retry re-executes from the first failed step — successful step outputs are preserved from the checkpoint, so only the failed step and its downstream steps run again. It broadcasts a workflow_retry SSE event and returns the operator tool’s result payload.
Cancel a running run
Section titled “Cancel a running run”POST /api/workflows/runs/{run_id}/cancelAuthorization: Bearer <token>No body. Cancel sets the executor’s cancel flag via the cancel_workflow tool; the executor reads it at the next step boundary, kills any in-flight shell or python subprocesses, and transitions the run to cancelled. The HTTP status reflects the outcome:
| Status | Condition |
|---|---|
200 OK | The run was active and cancellation was requested. |
404 Not Found | The run is not in the active registry (already finished or unknown). |
409 Conflict | The run is already in a terminal state. |
A successful cancel broadcasts a workflow_cancel SSE event.
Delete a run
Section titled “Delete a run”DELETE /api/workflows/runs/{run_id}Authorization: Bearer <token>Returns 204 No Content. Deletes the run record from Revka/WorkflowRuns and best-effort cleans up local files — the checkpoint at ~/.revka/workflow_checkpoints/{run_id}.json and any per-run artifacts directory.
Dashboard stats endpoint
Section titled “Dashboard stats endpoint”A single aggregated call powers the Workflows landing page so it does not need to fan out into separate definition and run requests:
GET /api/workflows/dashboard?include_definition=trueAuthorization: Bearer <token>include_definition (default true) controls whether the YAML is included for each definition. The response is wrapped in dashboard:
{ "dashboard": { "definitions_count": 12, "definitions": [ ... ], "active_runs": 2, "recent_runs": [ ... ], "total_runs": 47 }}active_runs counts runs in running or paused state, and recent_runs holds the most recent runs.
Agent activity log
Section titled “Agent activity log”For the dashboard’s Live Execution View, each agent that runs inside a workflow keeps a per-agent JSONL run log. Read it for drill-down into that agent’s tool calls, messages, and results:
GET /api/workflows/agent-activity/{agent_id}?view=summary&limit=100Authorization: Bearer <token>| Query param | Type | Default | Meaning |
|---|---|---|---|
view | string | summary | One of summary, tool_calls, messages, errors, full. |
limit | int | 100 | Max entries to return (capped at 500). |
The summary view returns header, total event count, tool-call count, error count, the last message (truncated), recent tool calls, and aggregated token-usage stats. The other views return the matching filtered entries, newest first. An agent with no log returns 404. Log files live at ~/.revka/operator_mcp/runlogs/{agent_id}.jsonl.
Architect — AI-assisted workflow revision
Section titled “Architect — AI-assisted workflow revision”The Architect panel in the workflow editor proposes structured edits to a workflow and lets you preview, validate, and revert revisions. All four routes require auth, and the operator-backed ones use a 30 s operator-tool timeout. The Architect requires the operator-mcp server to be connected.
POST /api/architect/revisePOST /api/architect/validate_yamlGET /api/architect/revisions?workflow_kref=kref://...POST /api/architect/republishPropose a revision
Section titled “Propose a revision”POST /api/architect/reviseAuthorization: Bearer <token>Content-Type: application/json{ "workflow_kref": "kref://Revka/Workflows/daily-report.workflow", "operations": [ { "op": "add_step", "step": { "id": "review", "action": "review" } } ], "rationale": "Add a review gate before publishing."}| Field | Required | Meaning |
|---|---|---|
workflow_kref | yes | The workflow item to revise. |
operations | yes | Non-empty array of operation objects, forwarded verbatim to the operator’s revise_workflow tool. The tool defines and validates the operation shapes. |
rationale | no | Human explanation attached to the revision. |
The structured result from revise_workflow is returned unchanged.
Validate a YAML proposal
Section titled “Validate a YAML proposal”POST /api/architect/validate_yamlAuthorization: Bearer <token>Content-Type: application/json{ "yaml": "<proposed workflow yaml>", "base_yaml": "<current yaml, optional>", "intent_summary": "Add a review gate"}This routes the proposed YAML through the same propose_workflow_yaml operator tool the LLM uses, returning { valid, errors, warnings, yaml, summary, added_step_ids, modified_step_ids, removed_step_ids }. It is validation only — nothing is persisted. The editor uses this for the chat-fallback path: when the Architect emits YAML in chat instead of calling the tool, the client posts the extracted YAML here so it still passes schema and workflow-level checks before reaching the canvas.
List revisions
Section titled “List revisions”GET /api/architect/revisions?workflow_kref=kref://Revka/Workflows/daily-report.workflowAuthorization: Bearer <token>Returns { "revisions": [ { "kref": "...?r=N", "number": N, "created_at": "...", "tags": [...], "metadata": { ... } } ] } — a thin summary of the workflow item’s revision history, used by the editor’s history strip.
Republish (revert)
Section titled “Republish (revert)”POST /api/architect/republishAuthorization: Bearer <token>Content-Type: application/json
{ "revision_kref": "kref://Revka/Workflows/daily-report.workflow?r=2" }Re-tags an earlier revision as published. This is the UI-safe revert: it points the workflow back at a previous revision without deleting anything. The published tag is hardcoded — callers cannot use this route to set arbitrary tag values. On success it returns { "ok": true, "revision_kref": "..." }, invalidates the workflow list cache, and broadcasts a workflow.revision.published event so the editor refreshes the canvas and YAML.
SSE events
Section titled “SSE events”Workflow state changes are pushed to dashboard clients over the Server-Sent Events stream (GET /api/events). The relevant event types are:
Event type | Emitted when |
|---|---|
workflow.revision.published | A definition is created, updated, or reverted via republish. |
human_approval_resolved | A run’s approval gate is approved or rejected. |
workflow_retry | A run retry is requested. |
workflow_cancel | A run cancellation is requested. |
human_approval_resolved, workflow_retry, and workflow_cancel carry run_id and a timestamp. workflow.revision.published carries workflow_kref, revision_kref, revision_number, name, published_at, and originating_session. For the full SSE envelope and other event types, see Realtime: WebSocket, SSE & Live Canvas.
Validation
Section titled “Validation”Saving or running a workflow validates its YAML through the operator’s validate_workflow tool, which runs a six-pass check (duplicate step IDs, dependency references, cycle detection, per-step config, variable references, and trigger fields). On failure, POST/PUT definitions and POST /api/workflows/run/{name} reject with 400 and a body of this shape:
{ "error": "Workflow validation failed: ...", "valid": false, "errors": [ ... ], "warnings": [ ... ]}If validation cannot run because of an infrastructure error (for example, the operator is briefly unreachable), it is skipped rather than blocking the save (fail-open). For the validation rules in depth, see Workflow YAML reference.
Related pages
Section titled “Related pages”- Gateway API overview — transports, auth, and shared conventions.
- Workflows, editor & runs — the dashboard UI for these endpoints.
- Runs, approvals & checkpoints — run lifecycle, retry, and checkpoint behavior.
- Workflow YAML reference — the definition format these routes store and validate.
- Agents, skills & teams API — where workflow
assign:andteam:slugs come from. - Realtime: WebSocket, SSE & Live Canvas — the SSE stream and approval delivery to channels.