Workflows Guide
Workflows are multi-step operations that chain tools, connector actions and agent steps together with durable state persistence. They are the preferred way to run multi-step automation programmatically because a run survives restarts and can be started, watched, paused and cancelled by ID.
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?
A workflow runs on a durable executor, not inside a single request or a single
sandbox, and it does not hold your one tracked-execution slot. (Each user can
have only one skill execution running at a time; a
second returns EXECUTION_RUNNING.)
- Durability — workflow state is persisted server-side. If the server restarts, the run continues from where it left off.
- Multi-step operations — chain tool calls, connector operations and agent steps into pipelines.
- Error recovery — a single step failing doesn’t lose previous step results.
- Human in the loop — a run can suspend to wait for input and resume when you answer.
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]
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://next.clanker.engineer/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 human input (resume to continue) |
completed | All steps finished successfully |
failed | Execution failed |
cancelled | Cancelled by the user |
Suspended for input
A suspended run is waiting for something only you can give, such as approval
of a step. Resume it with POST /api/v1/workflows/runs/:runId/resume.
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 per user (fails if busy) | Durable runs, not counted against the execution slot |
| Multi-step | No | Yes |
| State persistence | In-memory | Durable, server-persisted |
| Crash recovery | Lost | Resumes |
When to use direct execution: one tracked skill run you want to stream, poll and cancel. In chat, asking the agent to use a skill is a third path: it carries the skill out in its own sandbox and creates no execution.
When to use workflows: bot integrations, CI/CD pipelines, and any automation that needs reliability, multi-step chaining or schedules.
MCP Tools Reference
start-workflow launches a workflow over MCP; search-workflows finds the ID, and
list-schedules, set-schedule and unset-schedule manage schedules. Run management
(list, inspect, cancel, resume) is 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": {
"runId": "wf_abc123",
"workflowId": "deep-research",
"conversationId": null
}
}
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://next.clanker.engineer/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 waiting for input; resume it when you have answered. - 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