Task Bus
Tasks represent units of work delegated from one agent to another. They form a parent-child tree — cancel a parent and every descendant is cancelled automatically.
Task lifecycle
SUBMITTED → ACCEPTED → IN_PROGRESS → COMPLETED
→ FAILED
→ CANCELLED
| Status | Meaning |
|---|---|
SUBMITTED | Created, waiting for agent to acknowledge |
ACCEPTED | Agent confirmed it received the task |
IN_PROGRESS | Agent is actively working |
COMPLETED | Finished successfully |
FAILED | Agent reported an error |
CANCELLED | Cancelled (propagates to all children) |
Submit a task
curl -X POST http://localhost:7474/v1/tasks \
-H "Content-Type: application/json" \
-d '{
"workflowId": "wf-1",
"agentId": "researcher-1",
"payload": {"query": "summarise Q4"}
}'
# {"id": "2Kx...", "status": "SUBMITTED", ...}
With a parent task
-d '{"workflowId": "wf-1", "agentId": "writer-1", "parentId": "2Kx..."}'
Idempotency
Submit the same task twice safely by passing an idempotency key — duplicate submissions within 60s return the existing task:
-d '{"workflowId": "wf-1", "agentId": "researcher-1", "idempotencyKey": "research-q4-2024"}'
Lifecycle transitions
# Agent accepts the task
curl -X POST http://localhost:7474/v1/tasks/{id}/accept
# Agent marks it in progress (happens automatically on accept in most flows)
curl -X POST http://localhost:7474/v1/tasks/{id}/accept
# Agent completes it
curl -X POST http://localhost:7474/v1/tasks/{id}/complete \
-d '{"result": "<base64-encoded-result>"}'
# Agent reports failure
curl -X POST http://localhost:7474/v1/tasks/{id}/fail \
-d '{"error": "Ollama connection timed out"}'
Cancel a task (and its subtree)
curl -X DELETE http://localhost:7474/v1/tasks/{id}
# {"cancelled": true}
This recursively cancels all child and grandchild tasks in parallel.
View the task tree
curl "http://localhost:7474/v1/tasks/tree?workflowId=wf-1" \
-H "Accept: text/plain"
wf-1
├── researcher-1 [COMPLETED] 2Kx...
│ └── writer-1 [IN_PROGRESS] 2Ky...
│ └── reviewer-1 [SUBMITTED] 2Kz...
SDK reference
// Submit
const task = await client.tasks.submit({ workflowId, agentId, payload, parentId? })
// Get
const task = await client.tasks.get(taskId)
// List all tasks in a workflow
const { tasks } = await client.tasks.list(workflowId)
// Cancel (recursive)
await client.tasks.cancel(taskId)
// Accept / Complete / Fail (called by the agent)
await client.tasks.accept(taskId)
await client.tasks.complete(taskId, result?)
await client.tasks.fail(taskId, errorMessage)