Workflows Guide
Workflows are multi-step operations that chain tools together with durable state persistence. They are the preferred way to run skills programmatically because they handle execution queueing automatically.
Workflows are started two ways:
- Manual — launch via the REST API or MCP
- In chat — the workspace agent assembles and runs a workflow from a natural-language request
Why Use Workflows?
The One-Execution-At-A-Time Rule
Each workspace can only have one skill execution running at a time. If you start a second execution while one is in progress, you get an EXECUTION_RUNNING error.
This ensures quality and resource management, but it makes running several skills in sequence awkward — you’d have to wait for each to finish before starting the next.
Workflows Solve This
Workflows handle the queueing for you. When a step needs to execute a skill but the slot is occupied:
- The workflow pauses automatically
- It waits for the current execution to finish
- When the slot frees up, it resumes and continues
This happens transparently — no manual intervention.
Additional Benefits
- Durability — workflow state is persisted server-side. If the server restarts, the run continues from where it left off.
- Multi-step operations — chain skills and connector operations into pipelines.
- Error recovery — a single step failing doesn’t lose previous step results.
Launching a Workflow
Each workflow has a kebab-case workflowId (e.g. deep-research, pr-review,
analyse-csv) and an inputs schema. List the available workflows first
(GET /api/v1/workflows) to discover valid IDs and their inputs.
Via the Chat Agent
The easiest path is chat. The agent assembles and runs a workflow for you:
You: "Research the current state of solid-state batteries"
Agent: [proposes the deep-research workflow]
You: [confirm]
Agent: [workflow runs, shows results inline]
If you’re already running another skill, the workflow suspends and resumes automatically — no error, no retry.
Via MCP
{
"tool": "start-workflow",
"arguments": {
"workflow_id": "deep-research",
"inputs": { "topic": "the current state of solid-state batteries" }
}
}
Via REST API
curl -X POST https://clanker.net/api/v1/workflows/deep-research/launch \
-H "x-api-key: ck_live_xxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"inputs": { "topic": "the current state of solid-state batteries" }
}'
Response:
{
"runId": "wf_abc123",
"workflowId": "deep-research",
"status": "started",
"conversationId": null
}
Multi-Step Workflow Examples
Example 1: Deep Research
deep-research searches several angles of a topic and synthesizes the findings into a structured report:
{
"tool": "start-workflow",
"arguments": {
"workflow_id": "deep-research",
"inputs": { "topic": "the current state of solid-state batteries" }
}
}
This workflow:
- Gathers sources on the topic
- Follows up on recent developments
- Synthesizes the results into a report artifact
Example 2: Pull Request Review
pr-review fetches a GitHub pull request and produces a structured summary (requires the GitHub connector):
{
"tool": "start-workflow",
"arguments": {
"workflow_id": "pr-review",
"inputs": { "owner": "my-org", "repo": "my-repo", "pullNumber": 42 }
}
}
Retrieving Results
A launched run is asynchronous. Get its outcome one of these ways:
- Poll the run —
GET /api/v1/workflows/runs/:runIduntil the status is terminal (completed/failed/cancelled). - Stream it —
GET /api/v1/workflows/runs/:runId/eventsstreams a run’s live step events over SSE (use therunIdfrom launch). - In chat — a workflow started from a conversation reports completion back into that thread automatically.
Workflow States
| Status | Description |
|---|---|
running | Actively executing steps |
suspended | Paused awaiting a free execution slot or human input (resume to continue) |
completed | All steps finished successfully |
failed | Execution failed |
cancelled | Cancelled by the user |
Suspended for an Execution Slot
This is the automatic queueing in action. When a run is suspended waiting on a slot:
- Another skill execution is currently running
- The workflow will resume automatically when the slot frees up
- No action needed from you
Monitoring Workflow Runs
List your runs
GET /api/v1/workflows/runs
Get run details
GET /api/v1/workflows/runs/:runId
{
"run": {
"runId": "wf_abc123",
"workflowId": "deep-research",
"status": "completed"
},
"steps": [
{
"stepId": "initial-search",
"status": "completed",
"output": {
"executionId": "exec_456",
"artifactId": "a1b2c3d4-5678-90ab-cdef-1234567890ab"
},
"completedAt": "2026-02-12T10:00:30.000Z"
}
]
}
Cancel a run
POST /api/v1/workflows/runs/:runId/cancel
Workflows vs Direct Skill Execution
| Feature | Direct Execution | Workflow |
|---|---|---|
| Trigger | API/MCP call | API / MCP / chat |
| Concurrent runs | 1 (fails if busy) | 1 active, auto-queues |
| Multi-step | No | Yes |
| State persistence | In-memory | Durable, server-persisted |
| Crash recovery | Lost | Resumes |
When to use direct execution: simple interactive use from the dashboard or an MCP/IDE client. Not suited to bots or CI/CD.
When to use workflows: bot integrations, CI/CD pipelines, and any automation that needs reliability, multi-step chaining, or automatic queueing.
MCP Tools Reference
One workflow tool is exposed over MCP: start-workflow. Workflow discovery and run
management are done through the REST API. See Workflow MCP Tools
for full details.
start-workflow
Start a workflow by ID.
{
"tool": "start-workflow",
"arguments": {
"workflow_id": "deep-research",
"inputs": { "topic": "solid-state batteries" }
}
}
Response:
{
"success": true,
"data": {
"workflowId": "deep-research",
"workflowName": "Deep Research Report",
"inputs": { "topic": "solid-state batteries" }
}
}
To check on a run afterward, poll GET /api/v1/workflows/runs/:runId.
Node.js Bot Example
A minimal bot that starts a workflow and polls for the result:
import express from "express";
const app = express();
app.use(express.json());
const CLANKER_API_KEY = process.env.CLANKER_API_KEY;
const BASE_URL = "https://clanker.net/api";
async function pollRun(runId) {
while (true) {
const res = await fetch(`${BASE_URL}/v1/workflows/runs/${runId}`, {
headers: { "x-api-key": CLANKER_API_KEY },
});
const { run } = await res.json();
if (["completed", "failed", "cancelled"].includes(run.status)) return run;
await new Promise((r) => setTimeout(r, 2000));
}
}
app.post("/webhook", async (req, res) => {
res.sendStatus(200);
const { input } = req.body;
const launch = await fetch(`${BASE_URL}/v1/workflows/deep-research/launch`, {
method: "POST",
headers: {
"x-api-key": CLANKER_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ inputs: { topic: input } }),
});
const { runId } = await launch.json();
const run = await pollRun(runId);
console.log(`Workflow ${runId} finished: ${run.status}`);
});
app.listen(3000);
Best Practices
- Store run IDs — track runs in your database for audit trails.
- Poll or stream for results — use
GET /workflows/runs/:runId, or theGET /workflows/runs/:runId/eventsSSE endpoint; don’t assume synchronous completion. - Handle long runs — workflows with several LLM steps can take many minutes.
- Watch for
suspended— it means the run is queued behind another execution and will auto-resume. - Always handle failure — a run can end
failed; check the terminal status.
Next Steps
- Workflow API Reference — full REST API documentation
- Workflow MCP Tools — MCP tool reference
- Execution Concepts — the execution model