How do you orchestrate Claude Code across a team?
AgentCliAdapter interface drives Claude Code and Codex, so your team can mix them on one board.What orchestration means here
Orchestration is the rules of who starts agents, who answers them, and where the work goes when they finish. For solo developers it’s trivial — you and your terminal. For a team, the unanswered questions stack up: when Sasha’s agent asks a question while she’s in a meeting, does it die? When Maya the lead wants to know what her team spent on Claude this sprint, where does she look? When a new contractor joins on Monday, how do they get the same setup?
kanbots’s answer is to put the rules on the board. Permissions, routing, cost rollup, and the agent CLI choice are all properties of the project, not the individual developer.
Who can start an agent
Anyone with project access can drag a card to In progress. The dispatch happens on the card’s assignee’s machine — the developer whose claude /logincredentials and local code checkout will be used. If no assignee is set, kanbots dispatches on the dragger’s machine and silently sets them as the assignee.
Two consequences:
- You can’t dispatch on someone else’s behalf.The agent always runs on the assignee’s local daemon (cloud) or local desktop (OSS), against their checkout. Maya the lead can drag Sasha’s card and start a run only if Sasha’s daemon is online and her auto-claim policy allows it. The credential boundary is per-developer.
- Permissions are project-level, not card-level. Pillar 1 (auth) defines org and project roles; orchestration checks the role on dispatch. No per-card ACLs.
Where decisions go
When the agent pauses on a decision, the cloud writes a row in decisionsand publishes to the per-org realtime channel. Who sees a yellow “Awaiting decision” badge and can click an answer depends on the project’s decisions.answerers setting:
assignee_only(default) — the card’s assignee and any org admin can answer.project_members— anyone withproject:memberrole on the run’s project, plus the assignee and admins.organisation_members— any org member. Loosest; useful for small co-located teams.
Use project_members on shared on-call rotations where any teammate should be able to unblock a run; keep assignee_onlyon solo cards where you don’t want a teammate accidentally choosing a path on your behalf. Races between two simultaneous clickers are serialized by a conditional Postgres UPDATE; the second clicker gets a 409 with the winning answer, no merge weirdness.
Decisions also have a deadline (default 30 minutes, configurable 60s–24h). If nobody answers in time, the cloud either injects a per-decision default_value or sends a decision_timeoutmessage and the run fails. Pillar 10 notifications nudge the assignee + admins on timeout so the next standup isn’t the first time anyone hears about it.
How cost rolls up
Every result event from Claude or Codex carries total_cost_usd. The dispatcher writes it to agent_runs. From there the cloud aggregates upward:
- Per card. Sum of all runs on the card. Visible on the card header next to elapsed time and token counts.
- Per autopilot session. Sum of all child runs in an autopilot session. Shown on the session header alongside the session cost budget.
- Per project. Visible on the project settings page; the period rolls weekly and monthly. Filterable by assignee, model, persona.
- Per org. The CFO view. One number per month; drill into the project breakdown.
Importantly, the customer pays Anthropic (or OpenAI for Codex) directly via their own account. kanbots doesn’t resell inference; the cost numbers in the UI are what your provider invoiced for those tokens. Per-developer, per-card, per-anything rollup means a procurement conversation has actual data attached, not vibes.
One board, two CLIs (and more later)
The dispatcher talks to one of two agent CLIs today through a single interface:
// packages/dispatcher/src/agent-cli-adapter.ts
export interface AgentCliAdapter {
buildArgs(spec: RunSpec): string[]; // assemble the CLI args
parseStreamLine(line: string): StreamEvent; // claude vs codex JSON
writeDecisionAnswer(stdin, value: string): void;
}Switching CLIs is a per-dispatch choice. The AI providers modal (Settings → AI providers) shows your signed-in CLIs; Dispatchon a card picks a default but lets you override. The board, the worktrees, the decision UI, and the cost rollup are identical — only the process behind the slot changes.
Practical use of this: a team that prefers Claude for refactor work but uses Codex for tight algorithmic loops doesn’t have to pick. Each dispatch can target the better fit. The thread on the card records which CLI ran, so retros and cost attribution work normally.
Orchestration as an API: the MCP server
kanbots-mcp-serverexposes the board over Model Context Protocol. Any MCP-aware client — Cursor, Claude Desktop, the Claude Code CLI itself, custom scripts — can drive the board with natural language. The tools exposed:
- Issue CRUD:
listIssues,getIssue,createIssue,updateIssue,moveIssueStatus,archiveIssue,splitIssue. - Runs:
dispatchAgent,stopAgentRun,listAgentRuns,listPendingDecisions,resolvePendingDecision.
The desktop runs a local HTTP tool bridge on 127.0.0.1; the MCP server is a thin stdio process that forwards tool calls to the bridge with a per-session bearer token. Wire it into Cursor or Claude Desktop with the snippet under Settings → MCP server:
{
"mcpServers": {
"kanbots": {
"command": "kanbots-mcp-server",
"env": {
"KANBOTS_TOOL_BRIDGE_URL": "http://127.0.0.1:34567",
"KANBOTS_TOOL_BRIDGE_TOKEN": "<copy from Settings>"
}
}
}
}With the server wired in, you can sit in Claude Desktop and say “dispatch agents on every open issue labelled refactor” and Claude calls listIssues → dispatchAgent on each match. Orchestration becomes an API you write to in English.
A team day, walked through
- 9:00. Maya the lead opens the board on her laptop, sees 3 cards in Awaiting decision from overnight autopilot, answers all three (she has admin role, so the policy lets her). The runs resume; her decisions are recorded with timestamp + user id on the decision rows.
- 10:15. Sasha drags issue #102 to In progress. Her local daemon claims the run; the worktree opens; Claude starts. Maya sees the thread fill live on the same board.
- 11:00.Pat starts a feature-dev autopilot session on epic #88 with 3 personas (product, engineer, tester) and parallelism 4. The session burns through the parent and the four child issues the engineer persona split off, all in parallel slots on Pat’s machine.
- 14:30. Pat hits the session cost budget of $15. The session stops launching new children; the 2 in-flight children finish. Pat reviews the 5 produced draft PRs.
- 17:00. Maya opens the project cost panel for the week. Anthropic spend: $47.10 across 4 developers, 31 runs. She files it for the next exec readout. No Slack thread required.
Failure modes and fixes
“Auto-claim picked up a card we didn’t want it on.”
The daemon’s auto-claim policy in ~/.kanbots-agent/config.toml controls which projects it claims for. Default is to whitelist projects explicitly. Setting projects = ["*"]is convenient until it isn’t. Fix: whitelist the projects you actually want the daemon to act on, or set prompt_for_first = true so the daemon asks once per project on first claim.
“The decision policy is too tight.”
If your team is small enough that anyone can unblock anyone, assignee_only creates needless waiting. Set the project to project_members in Settings → Decisions. Watch the audit log for who’s answering what; if a teammate is repeatedly making the wrong call for someone else’s card, tighten back to assignee_only.
“Cost rollup is missing one developer.”
Almost always means that developer is using a different CLI version that doesn’t report cost on result, or they’ve set OPENAI_API_KEY pointing at a self-hosted gateway that strips cost. Check the run rows: a missing total_cost_usd is the signal. Upgrade the CLI or fix the gateway.
When this is the wrong fit
For a single developer working solo on a single repo, this is all overhead. You don’t need permission policies, cost rollup, or shared decision routing — you need the agent to do the work. Run claude in your terminal, or use the kanbots OSS desktop in single-user mode.
For organizations that haven’t standardized on a CLI agent yet, orchestration solves a problem you don’t have. Get two developers running Claude Code reliably first; come back when you have the “Pat’s agent broke something again, what was it doing” problem.
Related reading
For the team-shaped pattern at the conceptual level, see the right AI coding agent setup for a team. For multi-persona dynamics in autopilot, see how multi-persona AI agent orchestration works. For driving the board from natural language, see MCP server for Claude Code orchestration.
Try it on your own folder
Drop a folder, get a board, dispatch parallel agents. The desktop runs locally on macOS, Linux, and Windows.
Related questions
- What is the right AI coding agent setup for a team?A shared board, threaded runs, and bring-your-own-keys: why solo IDE agents do not generalize to teams and what the team-first pattern looks like.
- How do you assign GitHub issues to AI agents?Turn a GitHub issue into an agent run with one click. The label conventions, worktree-per-issue model, and how the agent reports back via decisions and PRs.
- What is an AI agent kanban board?A kanban whose cards are running AI agents. How status columns map to agent lifecycle, what live updates look like, and why this beats issue trackers + a separate agent IDE.
- How do you build an AI agent task queue?Queue → in-progress → review → done, with cost caps, decision prompts, and per-slot parallelism. The plumbing of a real task queue for agents instead of a request/response chatbot.