Skip to content
Hermes Agent Kanban — Multi-Agent Profile Collaboration

Hermes Agent Kanban — Multi-Agent Profile Collaboration

Hermes Agent ships a built-in Kanban board — a durable SQLite-backed task queue for coordinating work across multiple named agent profiles. Unlike delegate_task (a single RPC-style fork-join), the Kanban is a persistent message bus where tasks survive restarts, support human-in-the-loop blocks, and leave a permanent audit trail.

This page covers the concepts and workflows. See the official Kanban docs and Kanban tutorial for the full reference.

Why Kanban over delegate_task?

Dimensiondelegate_taskKanban
ShapeRPC fork-joinDurable message queue + state machine
ParentBlocks until child returnsFire-and-forget after create
Child identityAnonymous subagentNamed profile with persistent memory
ResumabilityNoneBlock → unblock → re-run
Audit trailLost on compressionPermanent SQLite rows
CoordinationHierarchical (parent/child)Peer — any profile reads/writes any task
Human-in-loopNot supportedBlock reason + unblock flow
Survives restartNoYes (disk-backed)

Rule of thumb: delegate_task is a function call; Kanban is a work queue where every handoff is a row anyone can read and write.

Core Concepts

Board — a standalone SQLite DB. The default is ~/.hermes/kanban.db. You can create multiple boards (one per project) — workers physically cannot see tasks on other boards.

Task — a row with title, body, assignee (a profile name), and a status. Status flow:

triage → todo → ready → running → blocked → done → archived

Tasks support parent-child dependencies, priority levels, tags, file attachments, and structured metadata.

Workspace — the working directory a spawned worker operates in:

  • scratch (default) — ephemeral temp dir, deleted on completion
  • worktree — a git worktree for coding tasks
  • dir:<path> — an existing shared directory

Dispatcher — a loop running inside the gateway process. Every N seconds it: reclaims stale claims, promotes ready tasks when their parents complete, atomically claims ready tasks, and spawns the assigned profile as a worker.

Comment thread — an inter-agent protocol. Every agent and human can append comments. Workers read the full thread on spawn.

Two Surfaces

You drive the board through three interfaces:

  • CLI: hermes kanban <verb>
  • Slash command: /kanban <verb> from any gateway chat
  • Web dashboard: hermes dashboard → Kanban tab

Workers drive the board through a dedicated kanban_* toolset — the model calls tools directly, never hermes kanban CLI commands:

ToolPurpose
kanban_show()Read current task (title, body, parent handoffs, prior runs, comments)
kanban_list()List tasks with filters (orchestrator profiles)
kanban_complete(summary, metadata)Finish with structured handoff
kanban_block(reason)Stop and request human input
kanban_heartbeat(note)Signal liveness during long ops
kanban_comment(task_id, body)Append a durable note
kanban_create(title, assignee, ...)Fan out into child tasks
kanban_link(parent, child)Add a dependency link
kanban_unblock(task_id)Move a blocked task back to ready

Dashboard

The web dashboard (hermes dashboard → Kanban) shows:

  • Six columns: Triage → Todo → Ready → Running (grouped by profile) → Blocked → Done
  • Cards with id, title, priority, assignee, comment/link counts
  • Profile lanes inside Running — see at a glance what each worker is doing
  • Side drawer on click: editable title/body, dependency editor, status actions, comment thread, run history with per-attempt outcomes, file attachments
  • Live WebSocket updates — board refreshes instantly on any change
  • Nudge Dispatcher button — force an immediate dispatch tick
  • Auto triage — drop rough ideas in Triage; the decomposer LLM reads your profile roster and produces a graph of child tasks routed to the best-fit specialists

Run History

Every attempt on a task is recorded as a task_run with:

  • Outcome: completed, blocked, spawn_failed, crashed, timed_out, gave_up
  • Summary — the worker’s structured handoff text
  • Metadata — arbitrary JSON (changed files, decisions, test results)
  • Error — crash/error details
  • Duration, timestamps, worker identity

Retry history is the primary representation — not a conceptual afterthought. A retrying worker sees prior attempts in its kanban_show() context and knows exactly what went wrong.

Setup

# One-time init (auto-runs on first command)
hermes kanban init

# Start gateway (hosts the dispatcher)
hermes gateway start

# Open the dashboard
hermes dashboard

Workflows

Solo Dev — Feature with Dependencies

Create tasks with parent links so dependencies auto-promote:

SCHEMA=$(hermes kanban create "Design auth schema" \
  --assignee backend-dev --body "Design the user/session/token schema" --json | jq -r .id)

API=$(hermes kanban create "Implement auth API endpoints" \
  --assignee backend-dev --parent $SCHEMA \
  --body "POST /register, /login, /refresh, /logout" --json | jq -r .id)

hermes kanban create "Write auth integration tests" \
  --assignee qa-dev --parent $API \
  --body "Happy path, wrong password, expired token, concurrent refresh"

Only SCHEMA starts in ready. When it completes, API auto-promotes to ready. When API completes, the test task follows. The dispatcher spawns workers in sequence automatically.

The backend-dev worker’s loop:

# Worker: kanban_show() → sees task + parent handoffs
# (designs schema, writes migrations)
kanban_heartbeat(note="schema drafted, writing migrations now")
kanban_complete(
    summary="users(id, email, pw_hash), sessions(id, user_id, jti, expires_at)",
    metadata={
        "changed_files": ["migrations/001_users.sql", "migrations/002_sessions.sql"],
        "decisions": ["bcrypt for hashing", "JWT for session tokens"],
    },
)

The downstream API worker reads the schema task’s summary + metadata in its kanban_show() context — zero context-switching overhead.

Fleet Farming — Parallel Specialists

Drop a batch of independent tasks and walk away — the dispatcher spawns all specialist profiles in parallel:

for lang in Spanish French German; do
    hermes kanban create "Translate homepage to $lang" --assignee translator
done
for i in 1 2 3 4 5; do
    hermes kanban create "Transcribe Q3 customer call #$i" --assignee transcriber
done
for sku in 1001 1002 1003 1004; do
    hermes kanban create "Generate product description: SKU-$sku" --assignee copywriter
done

Three workers drain their queues concurrently. The dashboard shows In Progress grouped by profile. No further human input needed.

Role Pipeline with Retry

A three-stage pipeline with a rejection + retry:

# PM worker completes spec with acceptance criteria in metadata
kanban_complete(
    summary="spec approved; POST /forgot-password sends email...",
    metadata={"acceptance": [
        "expired token returns 410",
        "reused last-3 password returns 400",
        "successful reset invalidates all active sessions",
    ]},
)

# Engineer (attempt 1) — reads spec, implements, reviewer rejects
kanban_block(reason="password strength check missing, reset link isn't single-use")

# Human reads block reason, unblocks from dashboard / CLI / Telegram
# hermes kanban unblock $IMPL

# Engineer (attempt 2) — sees prior block reason in context, fixes both issues
kanban_complete(
    summary="added zxcvbn strength check, reset tokens are now single-use",
    metadata={"changed_files": ["auth/reset.py", "auth/tests/test_reset.py"],
              "review_iteration": 2},
)

The dashboard shows both runs on the same task card: Run 1 (blocked → why), Run 2 (completed → summary with metadata). The reviewer worker then picks up the child “Review password reset PR” task and sees the engineer’s handoff metadata before looking at a diff.

Orchestrator Decomposition

An orchestrator fan-out pattern — split a goal into routed sub-tasks:

kanban_create(title="research ICP funding, NA angle",
    assignee="researcher-a",
    body="Seed + Series A, North America, AI-adjacent")

kanban_create(title="research ICP funding, EU angle",
    assignee="researcher-b",
    body="Seed + Series A: UK, Germany, France focused")

kanban_create(
    title="synthesize findings into launch brief",
    assignee="writer",
    parents=["t_r1", "t_r2"],
    body="one-pager, 300 words, neutral tone")

kanban_complete(summary="decomposed into 2 research → 1 synthesis")

Auto Triage (Default)

Drop a rough idea into the Triage column. With kanban.auto_decompose: true (default), the dispatcher auto-runs the decomposer: it reads your installed profiles + descriptions, asks an LLM to produce a task graph, and creates child tasks routed to the best-fit specialists.

hermes kanban create "draft a launch post on ICP funding landscape" --triage
# → decomposer produces children routed to researcher-a, researcher-b, writer

Flip the Auto/Manual pill on the dashboard to switch modes. Or use ✨ Specify for a single-task spec rewrite without fan-out.

Goal-Mode Cards (Multiple Turns)

For open-ended tasks needing several iterations, pass --goal:

hermes kanban create "Translate the docs site to French" \
  --body "Acceptance: every page translated, no English left, links intact." \
  --assignee linguist --goal --goal-max-turns 15

The worker runs in a loop with an auxiliary judge checking output against the acceptance criteria. Keeps going until the judge agrees, the worker terminates, or the turn budget is exhausted.

Dispatcher Safeguards

  • Circuit breaker — auto-blocks a task after N consecutive spawn failures (kanban.failure_limit, default 2, or per-task --max-retries)
  • Crash detection — the dispatcher polls kill(pid, 0) and reclaims tasks whose worker process died mid-flight
  • TTL enforcement — workers must heartbeat or the dispatcher reclaims the task
  • Gateway notificationsgave_up events fire through Telegram/Discord/Slack so you hear about outages without checking the board

Structured Handoff

The critical design principle: kanban_complete(summary, metadata) is not decoration — it’s the primary handoff channel between stages.

When a worker on task B spawns and calls kanban_show(), its worker_context includes:

  1. B’s prior attempts — previous run outcomes, summaries, errors, metadata (so retrying workers don’t repeat failed paths)
  2. Parent task results — for each parent, the most-recent completed run’s summary + metadata (so downstream workers see why and how upstream work was done)

This replaces the “dig through comments and output” dance. A PM writes acceptance criteria in the spec’s metadata; the engineer’s worker reads it structurally in the parent handoff. An engineer records which tests passed; the reviewer has that list in hand before opening a diff.

Quickstart

# 1. Create the board
hermes kanban init

# 2. Start the dispatcher (embedded in gateway)
hermes gateway start

# 3. Drop a task
hermes kanban create "Experiment with Hermes Kanban" --assignee default

# 4. Watch it in the dashboard
hermes dashboard

# 5. Inspect from CLI
hermes kanban list
hermes kanban show <task-id>
hermes kanban runs <task-id>
hermes kanban watch --kinds completed,gave_up,timed_out

References