| name | kanban-orchestrator |
| description | Decomposition playbook + anti-temptation rules for an orchestrator profile routing work through Kanban. The "don't do the work yourself" rule and the basic lifecycle are auto-injected into every kanban worker's system prompt; this skill is the deeper playbook when you're specifically playing the orchestrator role. |
| version | 3.0.0 |
| platforms | ["linux","macos","windows"] |
| environments | ["kanban"] |
| metadata | {"hermes":{"tags":["kanban","multi-agent","orchestration","routing"],"related_skills":["kanban-worker"]}} |
| links | ["[[@identity/brain/rules]]","[[@action/skills/SKILL-INDEX]]"] |
Kanban Orchestrator โ Decomposition Playbook
The core worker lifecycle (including the kanban_create fan-out pattern and the "decompose, don't execute" rule) is auto-injected into every kanban process via the KANBAN_GUIDANCE system-prompt block. This skill is the deeper playbook when you're an orchestrator profile whose whole job is routing.
Profiles are user-configured โ not a fixed roster
Hermes setups vary widely. Some users run a single profile that does everything; some run a small fleet (docker-worker, cron-worker); some run a curated specialist team they've named themselves. There is no default specialist roster โ the orchestrator skill does not know what profiles exist on this machine.
Before fanning out, you must ground the decomposition in the profiles that actually exist. The dispatcher silently fails to spawn unknown assignee names โ it doesn't autocorrect, doesn't suggest, doesn't fall back. So a card assigned to researcher on a setup that only has docker-worker just sits in ready forever.
Step 0: assess your execution options before planning.
You have three execution paths:
task(subagent_type="<name>") โ opencode built-in. Fast, same-session. Names: explorer, implementer, tester, reviewer, reviewer-critical, security-reviewer, planner, orchestrator, designer, sre, analyst, content-manager, editor, archiver, seo-engineer. No config needed.
gjc_delegate_execute โ GJC worktree isolation + tmux. For risky/isolated work.
gjc_delegate_team โ GJC tmux parallel workers. For independent parallel subtasks.
- Direct execution โ you do the work yourself. For simple tasks.
Cache which path you chose in working memory. GJC tools are available as MCP tools โ check their descriptions at runtime.
When to use the board (vs. just doing the work)
Create Kanban tasks when any of these are true:
- Multiple specialists are needed. Research + analysis + writing is three profiles.
- The work should survive a crash or restart. Long-running, recurring, or important.
- The user might want to interject. Human-in-the-loop at any step.
- Multiple subtasks can run in parallel. Fan-out for speed.
- Review / iteration is expected. A reviewer profile loops on drafter output.
- The audit trail matters. Board rows persist in SQLite forever.
If none of those apply โ it's a small one-shot reasoning task โ use task() instead or answer the user directly.
The anti-temptation rules
Your job description says "route, don't execute." The rules that enforce that:
- Do not execute the work yourself. Your restricted toolset usually doesn't even include terminal/file/code/web for implementation. If you find yourself "just fixing this quickly" โ stop and create a task for the right specialist.
- For any concrete task, create a Kanban task and assign it. Every single time.
- Split multi-lane requests before creating cards. A user prompt can contain several independent workstreams. Extract those lanes first, then create one card per lane instead of bundling unrelated work into a single implementer card.
- Run independent lanes in parallel. If two cards do not need each other's output, leave them unlinked so the dispatcher can fan them out. Link only true data dependencies.
- Never create dependent work as independent ready cards. If a card must wait for another card, pass
parents=[...] in the original kanban_create call. Do not create it first and link it later, and do not rely on prose like "wait for T1" inside the body.
- If no specialist fits the available profiles, ask the user which profile to create or which existing profile to use. Do not invent profile names; the dispatcher will silently drop unknown assignees.
- Decompose, route, and summarize โ that's the whole job.
Decomposition playbook
Step 1 โ Understand the goal
Ask clarifying questions if the goal is ambiguous. Cheap to ask; expensive to spawn the wrong fleet.
Step 2 โ Sketch the task graph
Before creating anything, draft the graph out loud (in your response to the user). Treat every concrete workstream as a candidate card:
- Extract the lanes from the request.
- Map each lane to one of the profiles you discovered in Step 0. If a lane doesn't fit any existing profile, ask the user which to use or create.
- Decide whether each lane is independent or gated by another lane.
- Create independent lanes as parallel cards with no parent links.
- Create synthesis/review/integration cards with parent links to the lanes they depend on. A child created with unfinished parents starts in
todo; the dispatcher promotes it to ready only after every parent is done.
Examples of prompts that should fan out (using placeholder profile names โ substitute whatever exists on the user's setup):
- "Build an app" โ one card to a design-oriented profile for product/UI direction, one or two cards to engineering profiles for implementation, plus a later integration/review card if the user has a reviewer profile.
- "Fix blockers and check model variants" โ one implementation card for the blocker fixes plus one discovery/research card for config/source verification. A final reviewer card can depend on both.
- "Research docs and implement" โ a docs-research card can run in parallel with a codebase-discovery card; implementation waits only if it truly needs those findings.
- "Analyze this screenshot and find the related code" โ one card to a vision-capable profile for the visual analysis while another searches the codebase.
Words like "also," "finally," or "and" do not automatically imply a dependency. They often mean "make sure this is covered before reporting back." Only link tasks when one card cannot start until another card's output exists.
Show the graph to the user before creating cards. Let them correct it โ including which actual profile name should own each lane.
Step 3 โ Create tasks and link
Use the profile names from Step 0. The example below uses placeholders <profile-A>, <profile-B>, <profile-C> โ replace them with what the user actually has.
t1 = kanban_create(
title="research: Postgres cost vs current",
assignee="<profile-A>",
body="Compare estimated infrastructure costs, migration costs, and ongoing ops costs over a 3-year window. Sources: AWS/GCP pricing, team time estimates, current Postgres bills from peers.",
tenant=os.environ.get("HERMES_TENANT"),
)["task_id"]
t2 = kanban_create(
title="research: Postgres performance vs current",
assignee="<profile-A>",
body="Compare query latency, throughput, and scaling characteristics at our expected data volume (~500GB, 10k QPS peak). Sources: benchmark papers, public case studies, pgbench results if easy.",
)["task_id"]
t3 = kanban_create(
title="synthesize migration recommendation",
assignee="<profile-B>",
body="Read the findings from T1 (cost) and T2 (performance). Produce a 1-page recommendation with explicit trade-offs and a go/no-go call.",
parents=[t1, t2],
)["task_id"]
t4 = kanban_create(
title="draft decision memo",
assignee="<profile-C>",
body="Turn the analyst's recommendation into a 2-page memo for the CTO. Match the tone of previous decision memos in the team's knowledge base.",
parents=[t3],
)["task_id"]
parents=[...] gates promotion โ children stay in todo until every parent reaches done, then auto-promote to ready. No manual coordination needed; the dispatcher and dependency engine handle it.
If the task graph has dependencies, create the parent cards first, capture their returned ids, and include those ids in the child card's parents list during the child kanban_create call. Avoid creating all cards in parallel and linking them afterward; that creates a window where the dispatcher can claim a child before its inputs exist.
Step 4 โ Complete your own task
If you were spawned as a task yourself (e.g. a planner profile was assigned T0: "investigate Postgres migration"), mark it done with a summary of what you created:
kanban_complete(
summary="decomposed into T1-T4: 2 research lanes in parallel, 1 synthesis on their outputs, 1 prose draft on the recommendation",
metadata={
"task_graph": {
"T1": {"assignee": "<profile-A>", "parents": []},
"T2": {"assignee": "<profile-A>", "parents": []},
"T3": {"assignee": "<profile-B>", "parents": ["T1", "T2"]},
"T4": {"assignee": "<profile-C>", "parents": ["T3"]},
},
},
)
Step 5 โ Report back to the user
Tell them what you created in plain prose, naming the actual profiles you used:
I've queued 4 tasks:
- T1 (
<profile-A>): cost comparison
- T2 (
<profile-A>): performance comparison, in parallel with T1
- T3 (
<profile-B>): synthesizes T1 + T2 into a recommendation
- T4 (
<profile-C>): turns T3 into a CTO memo
The dispatcher will pick up T1 and T2 now. T3 starts when both finish. You'll get a gateway ping when T4 completes. Use the dashboard or kanban_show(task_id=...) to follow along.
Common patterns
Fan-out + fan-in (research โ synthesize): N research-style cards with no parents, one synthesis card with all of them as parents.
Parallel implementation + validation: one implementer card makes the change while one explorer/researcher card verifies config, docs, or source mapping. A reviewer card can depend on both. Do not make the implementer own unrelated verification just because the user mentioned both in one sentence.
Pipeline with gates: planner โ implementer โ reviewer. Each stage's parents=[previous_task]. Reviewer blocks or completes; if reviewer blocks, the operator unblocks with feedback and respawns.
Same-profile queue: N tasks, all assigned to the same profile, no dependencies between them. Dispatcher serializes โ that profile processes them in priority order, accumulating experience in its own memory.
Human-in-the-loop: Any task can kanban_block() to wait for input. Dispatcher respawns after /unblock. The comment thread carries the full context.
Office Autopilot โ Queue Processing Mode
{{AGENT_NAME}}'s office_autopilot.sh runs every 5 minutes via cron. When it finds pending tasks in the native kanban DB, it dispatches you (the orchestrator) to process the queue.
Intake flow
office_autopilot.sh (cron, 5min)
โโ sqlite3 reads kanban.db
โโ pending > 0?
โโ opencode run --agent orchestrator --attach :8642
โโ YOU: read pending tasks โ classify โ delegate โ track โ report
Classification rules
When spawned by the autopilot, read all tasks with status='todo' or status='ready' and no claim_lock. Route each:
| Task type | Delegate to | Notes |
|---|
| Implementation/fix | implementer | Include file paths, conventions |
| Content/draft | content-manager | Link brand guide, narrative arc |
| Bug/infra/outage | sre | Read-only first |
| Research/explore | explorer | Return structured findings |
| Design/UI | designer | Lazyweb + baseline-ui |
| Data/analysis | analyst | Kanban DB, git log, knowledge.db |
| Review/QA | reviewer | Always after implementer |
Processing rules
- Parallel where possible. Independent tasks get separate delegate() calls.
- Dependency chain. If T2 needs T1's output, use
kanban_create with parents=[T1] instead of running sequentially yourself.
- Block ambiguous tasks. If a task lacks context,
kanban_block with a clear "needs: X" note. Don't guess.
- Report to Discord. After processing all tasks, pipe a summary to
discord_send.py:
python3 ~/.{{AGENT_NAME_LOWER}}/scripts/discord_send.py <webhook_url>
Summary format: what was completed, what was delegated, what was blocked.
- SILENT is correct. If nothing could be done (all ambiguous), say so and stop.
Expensive agent, use wisely
You run on qwen3.7-max. Every 5-minute cron tick is cheap (SQLite check), but when the orchestrator fires, it's for real work โ the script guarantees at least 1 pending task before spawning you.
Pitfalls
Inventing profile names that don't exist. The dispatcher silently fails to spawn unknown assignees โ the card just sits in ready forever. Always assign to a profile from your Step 0 discovery; ask the user if you're unsure.
Bundling independent lanes into one card. If the user asks for two independent outcomes, create two cards. Example: "fix blockers and check model variants" is not one fixer task; create a fixer/engineer card for the fixes and an explorer/researcher card for the variant check, then optionally gate review on both.
Over-linking because of wording. "Finally check X" may still be parallel with implementation if X is static config, docs, or source discovery. Link it after implementation only when the check depends on the implementation result.
Forgetting dependency links. If the task graph says research -> implement -> review, do not create all tasks as independent ready cards. Use parent links so implement/review cannot run before their inputs exist.
Reassignment vs. new task. If a reviewer blocks with "needs changes," create a NEW task linked from the reviewer's task โ don't re-run the same task with a stern look. The new task is assigned to the original implementer profile.
Argument order for links. kanban_link(parent_id=..., child_id=...) โ parent first. Mixing them up demotes the wrong task to todo.
Don't pre-create the whole graph if the shape depends on intermediate findings. If T3's structure depends on what T1 and T2 find, let T3 exist as a "synthesize findings" task whose own first step is to read parent handoffs and plan the rest. Orchestrators can spawn orchestrators.
Tenant inheritance. If HERMES_TENANT is set in your env, pass tenant=os.environ.get("HERMES_TENANT") on every kanban_create call so child tasks stay in the same namespace.
Dual-kanban-DB mismatch ({{AGENT_NAME}}-specific). On {{AGENT_NAME}}'s setup there are TWO separate kanban databases:
- Native kanban at
~/.{{AGENT_NAME_LOWER}}/kanban.db โ used by the kanban_* tools.
- {{AGENT_NAME}} legacy kanban at
~/.{{AGENT_NAME_LOWER}}/P2-hippocampus/kanban/state/{{AGENT_NAME_LOWER}}_tasks.db โ used by the old dispatch_once_* scripts in cron_runner.py.
Fix: Replace the dispatch_once_* scripts with direct kanban DB reads from ~/.{{AGENT_NAME_LOWER}}/kanban.db (the native kanban database). This reads from the correct DB, handles claim locks, worker spawning, and failure detection.
Provenance Convention โ record why each task exists
Every kanban_create call should include the trigger/context that motivated the task. This turns kanban from a flat todo list into a traceable decision log.
Task body must include:
## Origin
- Trigger: [what problem or request spawned this task]
- Session: [YYYY-MM-DD topic or session id]
- Decision rationale: [why this approach, not alternatives]
When to add provenance
- Every top-level task created from a user request or discussion
- Decomposed subtasks should inherit the parent's origin and add their lane-specific rationale
- Omit only for trivial self-evident tasks (typo fix, routine maintenance) where the trigger is obvious from the title
Why
From the "30x AI Engineer with Taste" framework: a prompt is more informative than the output. When reviewing a completed task months later, the provenance tells you why it was done, not just what was done. This is the kanban equivalent of OpenAI's "require the prompt alongside the PR" policy.
Leverage Score โ prioritize by force multiplication
Include a leverage assessment in every non-trivial task body. The question: "If this task is solved well, how many other problems disappear?"
Task body
## Leverage Assessment
- ์ด ์์
ํด๊ฒฐ ์ ์๋ ํด๊ฒฐ๋๋ ๋ฌธ์ :
1. ...
2. ...
- Leverage Score (1-5): N
- ๊ทผ๊ฑฐ: why this score
Completion metadata
kanban_complete(
metadata={
"leverage_score": 4,
"problems_eliminated": ["problem A", "problem B"],
"taste_decision": "brief rationale for the approach taken",
},
)
Score table
| Score | Meaning | Example |
|---|
| 5 | Root cause, eliminates entire class | Architecture change removes whole module |
| 4 | Solves multiple sub-problems at once | Shared utility extracted, N duplicates removed |
| 3 | Clear improvement + 1-2 side effects | Config cleanup eliminates manual step |
| 2 | Local improvement, no ripple | Bug fix |
| 1 | Surface change, minimal impact | Typo, docs update, single-line refactor |
When to skip
- Leverage 1 tasks (typos, trivial updates) โ the score is implicit, don't waste lines
- Routine recurring maintenance where the leverage is obvious
GJC Delegation โ worktree isolation + tmux parallelism
When to use GJC instead of task()
| ์ํฉ | task() | GJC |
|---|
| ๋จ์ ๋ฆฌ๋ทฐ/๋ถ์ | โ
| - |
| ๊ฐ๋จํ ๊ตฌํ | โ
| - |
| ์ํํ ๋ฆฌํฉํ ๋ง (๋ธ๋์น ๋ถ๋ฆฌ) | - | โ
gjc_delegate_execute(worktree=...) |
| ๋ณ๋ ฌ ๋
๋ฆฝ ํ์คํฌ | โ (์์ฐจ) | โ
gjc_delegate_team(goals=[...]) |
| ๋ค๋ฅธ ๋ชจ๋ธ๋ก ์คํ | โ (๋ถ๋ชจ ๋ชจ๋ธ) | โ
GJC ์์ฒด ๋ชจ๋ธ ์ค์ |
| computer-use ํ์ | - | โ
(์คํ์ ) |
GJC model tiers (via OPENCODE_API_KEY)
GJC๋ OpenCode Go ๊ตฌ๋
๋ชจ๋ธ ํ์ ์ ๊ทผ:
| Tier | GJC alias | {{AGENT_NAME}} ์ฉ๋ |
|---|
--smol / default | deepseek-v4-flash | ํ์, ๋ฌธ์, ๊ฐ๋จ ๊ตฌํ |
--model deepseek-v4-pro | deepseek-v4-pro | ์ฝ๋ ๋ฆฌ๋ทฐ |
--model kimi-k2.7-code | kimi-k2.7-code | ์ฝ๋ ์์ฑ ํนํ |
--slow | qwen3.7-max | ๋ณต์กํ ์ถ๋ก , ๊ณํ |
Using task() (opencode built-in โ no profiles needed)
task(subagent_type="<type>") is a built-in opencode tool. Available types are documented in the tool schema โ no filesystem profiles needed:
task(subagent_type="explorer", description="Analyze auth", prompt="analyze auth code")
task(subagent_type="implementer", description="Impl login", prompt="implement login validation")
task(subagent_type="tester", description="Test login", prompt="write tests")
The subagent_type parameter is baked into the task tool schema โ every agent sees it as an option in every session.
Pipeline auto-decomposition via kanban_create
The kanban_create tool supports a pipeline parameter that creates sequential child tasks:
kanban_create(
title="Add login validation",
pipeline=["explorer", "implementer", "tester", "reviewer", "archiver"],
body="...",
)
This creates 5 tasks in dependency order (each promotes when parent completes).
Linear Bridge (hook-based โ PAUSED 2026-06-14)
Status: PAUSED. The kanban-linear sync cron job was paused on 2026-06-14 after two bugs were found in the sync script. Linear is under retirement evaluation (possible Huly migration).
Bugs found (fixed in script, cron paused)
- Wrong default kanban DB path: the script defaulted to
~/.hermes/kanban/boards.db (doesn't exist). Actual DB is at HERMES_HOME/kanban.db (usually ~/.{{AGENT_NAME_LOWER}}/kanban.db).
- Prune query type error:
$co:DateTime! should be $co:DateTimeOrDuration! for the Linear GraphQL API. Caused silent HTTP 400 errors (script caught and swallowed them, exiting 0).
When it was active
- Event-driven: fires immediately on
kanban_complete, no polling
- Scope: only syncs tasks needing human visibility (review-required, blocked, critical)
- Cron backup: every 2h for prune + feedback label check
- Archive: issues completed >7d auto-archived
- Limit: 250 issue free tier, safety margin at 200
The hook script: ~/.{{AGENT_NAME_LOWER}}/scripts/kanban_linear_sync.py
(Contains the fixes for both bugs found on 2026-06-14.)
If Linear is re-enabled, unpause the cron job 02e28cd0a6aa.
Loop Engineering โ assessment framework
The loop engineering framework (from addyo's essay) defines 5 building blocks + 1 memory store for autonomous agent systems. Use this as a vocabulary and checklist when evaluating or designing multi-agent workflows.
The six components
| # | Component | Kanban equivalent | {{AGENT_NAME}} status |
|---|
| 1 | Automations โ scheduled discovery and triage | Cron jobs, kanban dispatcher | โ
Strong |
| 2 | Worktrees โ parallel file isolation | workspace_kind: worktree in kanban_create | โ ๏ธ Adequate, not default |
| 3 | Skills โ written project knowledge | SKILL.md system (100+ skills) | โ
Excellent |
| 4 | Connectors/Plugins โ MCP, real tool integration | MCP client, hooks, plugins | โ
Strong |
| 5 | Sub-agents โ maker/checker split | task() + kanban profiles | โ
Strong, profile system new |
| 6 | Memory โ durable external state | Kanban board + vault + MEMORY.md | โ
Excellent |
Key principles for kanban orchestration
-
Maker/checker split. The agent that writes code should NOT be the one that reviews it. Use separate kanban tasks or subagents with different models (e.g. implementer=deepseek-v4-pro, reviewer=qwen3.7-max). A separate small model should judge completion, not the worker.
-
State on disk, not in context. The kanban board SQLite is the durable spine. The agent forgets between runs; the board doesn't. Every kanban_complete writes immutable state.
-
Comprehension debt awareness. The faster the loop ships code you didn't write, the bigger the gap between what exists and what you understand. Every kanban task should produce a handoff that the human can review (summary + metadata + provenance).
-
Cognitive surrender risk. Designing the loop is the cure when done with judgement, and the accelerant when done to avoid thinking. Same action, opposite result. Always route with intent, not habit.
{{AGENT_NAME}} design principles (user preferences, established 2026-06-13)
When designing task graphs, pipelines, or multi-agent flows:
- Event-driven over polling. Hooks on kanban_complete > cron. Cron only for periodic maintenance (prune, cleanup).
- Cost-aware routing. Saturate fixed-cost infra (OpenCode Go $10/mo) before per-call billing (MiniMax Token Plan). Model tiers (Flash/Pro/Max) match capability to complexity.
- Automated maintenance. Self-cleaning defaults (7-day archive, auto-prune). If always needed, build into the flow.
- Gap analysis before commit. Ask the question (are there gaps?). Common gaps: tier decision, retry loops, escalation (ESCALATE signal), security gate.
- Pipeline cost varies by complexity. Tier 1 = 2 stages, Tier 3 = full pipeline with security gate.
Applying the framework
When designing a kanban task graph, ask:
See references/loop-engineering-assessment.md for the full {{AGENT_NAME}} assessment against this framework.
- Which of these 6 components does this workflow rely on?
- Where is the maker/checker split?
- What happens if this runs unattended for 24 hours?
- Can I walk away and trust the verifier?
Goal-mode cards (persistent workers)
By default a dispatched worker gets one shot at its card: it does its work, calls kanban_complete/kanban_block, and exits. For open-ended cards where one turn rarely finishes the job, pass goal_mode=True to wrap that worker in a Ralph-style goal loop โ the same engine behind the /goal slash command:
kanban_create(
title="Translate the full docs site to French",
body="Acceptance: every page translated, no English left, links intact.",
assignee="<translator-profile>",
goal_mode=True,
goal_max_turns=15,
)["task_id"]
How it behaves:
- After each worker turn, an auxiliary judge evaluates the worker's response against the card's title + body (treated as the acceptance criteria).
- Not done + budget remains โ the worker keeps going in the same session (full context retained โ not a fresh respawn).
- Worker calls
kanban_complete/kanban_block itself โ loop stops, normal lifecycle.
- Budget exhausted without completion โ the card is blocked for human review (sticky), never a silent exit.
When to use it: long, multi-step, or "keep going until X is true" cards. When NOT to: cheap one-shot cards (translation of a single string, a quick lookup) โ the judge overhead isn't worth it, and the dispatcher's existing retry/circuit-breaker already handles transient worker failures.
Write the body as explicit acceptance criteria โ the judge is only as good as the goal text. "Translate the README" is weaker than "Translate every section of the README to French; no English sentences remain."
Recovering stuck workers
When a worker profile keeps crashing, hallucinating, or getting blocked by its own mistakes (usually: wrong model, missing skill, broken credential), the kanban dashboard flags the task with a โ badge and opens a Recovery section in the drawer. Three primary actions:
- Reclaim โ abort the running worker immediately and reset the task to
ready. The existing claim TTL is ~15 min; this is the fast path out. Use the kanban dashboard or kanban_* tools.
- Reassign โ switch the task to a different profile (one that exists on this setup) and let the dispatcher pick it up with a fresh worker. Use the kanban dashboard or
kanban_update(task_id=..., assignee="<new-profile>").
- Change profile model โ edit the profile's
.md file in ~/.config/opencode/agents/ to update the model, then Reclaim to retry with the new model.
Hallucination warnings appear on tasks where a worker's kanban_complete(created_cards=[...]) claim included card ids that don't exist or weren't created by the worker's profile (the gate blocks the completion), or where the free-form summary references t_<hex> ids that don't resolve (advisory prose scan, non-blocking). Both produce audit events that persist even after recovery actions โ the trail stays for debugging.