Skip to content

Workboard API

The Workboard is Soulacy's Kanban task board: create tasks, assign them to agents, run them, review results, and download produced files. Everything the Workboard GUI does goes through these endpoints.

All routes live under /api/v1 and require authentication. They return 503 {"error": "workboard not enabled"} when no workboard store is wired.

Tasks

Method Path Description
GET /workboard/tasks?status=&agent_id= List tasks, optionally filtered
POST /workboard/tasks Create a task (201)
GET /workboard/tasks/:id Get one task
PATCH /workboard/tasks/:id Update fields (partial)
DELETE /workboard/tasks/:id Delete a task (204)

Create a task

curl -X POST http://localhost:18789/api/v1/workboard/tasks \
  -H "Authorization: Bearer $SOULACY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Summarize this weeks support tickets",
    "description": "Group by product area, flag anything urgent.",
    "agent_id": "support-bot",
    "priority": "high",
    "tags": ["support", "weekly"],
    "due_at": "2026-07-01T10:00:00Z"
  }'

Body fields (all optional except a meaningful title): title, description, agent_id, status, owner, priority, tags (string array), due_at (RFC3339).

Update a task

PATCH sends only the fields you want to change. An empty-string due_at clears the due date:

curl -X PATCH http://localhost:18789/api/v1/workboard/tasks/12 \
  -H "Authorization: Bearer $SOULACY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status": "done", "due_at": ""}'

List tasks

curl -H "Authorization: Bearer $SOULACY_API_KEY" \
  "http://localhost:18789/api/v1/workboard/tasks?status=running&agent_id=support-bot"
{
  "tasks": [ { "id": 12, "title": "…", "status": "running", "agent_id": "support-bot",  } ],
  "statuses": ["todo", "running", "needs_review", "done", "failed"]
}

(The statuses array is the server's authoritative status list — render columns from it rather than hard-coding.)

Runs

Method Path Description
POST /workboard/tasks/:id/run Start a run through the task's assigned agent (202)
GET /workboard/tasks/:id/runs List the task's run history

POST …/run returns 202 Accepted with the run record; the agent executes asynchronously (a single run is bounded at 15 minutes). Errors: 400 when the task has no agent_id, 409 when a run is already active for the task.

curl -X POST -H "Authorization: Bearer $SOULACY_API_KEY" \
  http://localhost:18789/api/v1/workboard/tasks/12/run

Follow progress via the event stream: run.started, run.finished / run.failed, and run.artifact events carry task_id, run_id, and attempt.

Artifacts

Files produced during a run (detected from file-writing tool calls) are attached to the task automatically.

Method Path Description
GET /workboard/tasks/:id/artifacts List a task's artifacts
GET /workboard/artifacts/:id/download Download one artifact file
curl -H "Authorization: Bearer $SOULACY_API_KEY" \
  http://localhost:18789/api/v1/workboard/tasks/12/artifacts
{
  "artifacts": [
    { "id": 3, "path": "/Users/you/reports/summary.md",
      "size_bytes": 14302, "tool": "write_file",
      "created_at": "2026-06-06T21:04:05Z" }
  ],
  "count": 1
}

The download endpoint streams the file with a Content-Disposition: attachment header. It returns 404 for an unknown artifact and 410 Gone when the recorded file no longer exists on disk.

Comments & reviewer notes

Method Path Description
GET /workboard/tasks/:id/comments List comments on a task
POST /workboard/tasks/:id/comments Add a comment (201)
DELETE /workboard/comments/:id Delete a comment (204)
curl -X POST http://localhost:18789/api/v1/workboard/tasks/12/comments \
  -H "Authorization: Bearer $SOULACY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"author": "vasu", "body": "Looks good — ship it.", "kind": "review"}'

Error shapes

Status Meaning
400 Invalid body, non-integer ID, bad due_at, or task missing an agent
404 Task / comment / artifact not found
409 Task already has an active run
410 Artifact file no longer exists on disk
503 Workboard store not configured

All errors use the standard {"error": "…"} envelope.