-
Notifications
You must be signed in to change notification settings - Fork 10.8k
Description
Problem
OpenCode's task tool spawns subagents that run sequentially, return a result, and terminate. There's no way for multiple agents to work in parallel, communicate with each other, or coordinate on shared tasks. Users working on complex problems (multi-file refactors, research + implementation, code review across concerns) are limited to one agent at a time.
Claude Code shipped agent teams (Feb 5, 2026). Several community requests exist: #12661, #9649, #6478. PR #7756 proposes subagent-to-subagent delegation with a tree hierarchy. This proposal takes a different approach: flat teams with named messaging, built as an adjunct to the existing session/task system rather than a redesign of it.
Design Goals
- Non-invasive — builds on existing sessions, agents, and tools. No changes to the core session or task architecture.
- Flat, not hierarchical — one lead, N teammates. No nested teams, no tree traversal.
- Name-addressed messaging — teammates communicate by name, not by session ID or parent-child relationship. The lead doesn't route messages.
- Multi-model — each teammate can use a different provider/model (e.g., Gemini for research, Claude for implementation).
- Opt-in — behind
OPENCODE_EXPERIMENTAL_AGENT_TEAMSflag. Default behavior unchanged.
Architecture
Data Model
A team is a named group of sessions:
Team {
name: string // e.g. "auth-review"
leadSessionID: string // the session that created the team
delegate?: boolean // lead restricted to coordination-only tools
members: [{
name: string // unique within team, e.g. "security-reviewer"
sessionID: string // child session
agent: string // agent type (e.g. "general", "explore")
status: "active" | "idle" | "shutdown" | "interrupted"
model?: string // "providerID/modelID"
planApproval?: "none" | "pending" | "approved" | "rejected"
}]
}
Team state is persisted to disk as JSON files under .opencode/teams/{teamName}/ (config.json and tasks.json). All reads go directly to disk — no in-memory cache. Task state (shared task list) uses file-based storage with file locking for concurrency. No database schema changes.
Tools
Nine tools, split by role:
Lead-only:
| Tool | Purpose |
|---|---|
team_create |
Create a team, become the lead |
team_spawn |
Spawn a teammate (creates child session, starts prompt loop) |
team_approve_plan |
Approve/reject a teammate's plan (unlocks write tools) |
team_shutdown |
Request a teammate to shut down |
team_cleanup |
Remove team resources |
Available to all team members (lead + teammates):
| Tool | Purpose |
|---|---|
team_message |
Send a message to a specific teammate or "lead" by name |
team_broadcast |
Send a message to all teammates |
team_tasks |
View/add/complete tasks on a shared task list |
team_claim |
Claim a pending task (file-locked to prevent races) |
Tool isolation: Task subagents spawned by teammates get NO team tools. Subagents are private utilities — the teammate relays relevant findings. This prevents uncoordinated noise in team communication.
Communication
Messages are injected as synthetic user messages into the recipient's session, which triggers auto-wake if the recipient is idle. No file-based mailboxes, no polling.
TeamMessaging.send({ teamName, from: "security-reviewer", to: "lead", text: "Found 3 SQL injection vulnerabilities" })
// → injects a user message into the lead's session
// → if lead is idle, auto-wake kicks off the prompt loop
Messages between teammates are persisted through OpenCode's existing session storage (messages and parts written as JSON files to ~/.local/share/opencode/storage/).
Teammate Lifecycle
- Lead calls
team_spawnwith agent type, name, model, and initial prompt - A child session is created with permission rules denying lead-only tools
- The teammate's prompt loop starts in the background (non-blocking)
- When the teammate's loop completes or errors, an idle notification is sent to the lead via
team_message - Lead can send follow-up work via
team_message, which auto-wakes the teammate
Recovery
On server restart, Team.recover() scans all teams for members with status: "active" (stale from a crash), marks them as interrupted, and injects a synthetic notification into the lead session. The lead's LLM sees the notification on next prompt and can re-spawn or message them. Team structure, member state, and conversation history all survive a restart — the remaining gap is that teammate prompt loops are not auto-restarted.
Optional Features
Delegate mode: Lead is restricted to coordination-only tools (no write/edit/bash). Forces clean separation between orchestration and execution.
Plan approval: Teammates start in read-only mode. They research, formulate a plan, send it to the lead. Lead approves (unlocks write tools) or rejects (teammate revises). Prevents wasted work on wrong approaches.
Shared task list: Teams can maintain a task list with priorities, dependencies, and assignees. Tasks auto-unblock when dependencies complete. Any member can view, add, claim, or complete tasks.
TUI Integration
- Header: Team badge showing team name and member count/status summary
- Sidebar: Team section with per-member status, per-member todo progress, current tool activity (live spinner), and shared task list
- Prompt: Aggregated busy indicator ("3 teammates working") when lead is idle but teammates are active
- Session list: Spinner on busy teammate sessions
- Team dialog: Keyboard-driven team creation interface
What This Does NOT Change
- The existing
tasktool and subagent system are untouched - Session creation, storage, and lifecycle are unchanged
- The prompt loop, processor, and message system are unchanged
- No database schema changes
- No new dependencies
Example Usage
User: Review this codebase for security issues across frontend, backend, and infrastructure
Lead (Claude Opus):
→ team_create("security-audit")
→ team_spawn("frontend", agent="general", model="anthropic/claude-sonnet-4-20250514", prompt="Review React components for XSS...")
→ team_spawn("backend", agent="general", model="google/gemini-2.5-pro", prompt="Review API endpoints for injection...")
→ team_spawn("infra", agent="explore", prompt="Check Docker, CI, and dependency configs...")
[3 teammates work in parallel, each searching and analyzing independently]
frontend → team_message(to="lead", "Found 3 XSS vulnerabilities in...")
backend → team_message(to="frontend", "The sanitization you flagged is also missing in the API layer")
infra → team_tasks(action="complete", task_id="deps")
Lead synthesizes findings into a final report
Screenshots
Super Bowl prediction — 3 teammates researching in parallel with live sidebar activity:
Precious metals forecast — 3 teammates with task dependencies and claim operations:
Implementation Status
Working implementation submitted as a 3-PR stack:
- PR feat: add agent team core — Team namespace, messaging, recovery, and events #12730 — Core team primitives (Team namespace, messaging, events, recovery)
- PR feat: add team tools, HTTP routes, and tool registry integration #12731 — 9 MCP tools, HTTP routes, tool registry integration
- PR feat: add team TUI integration — sidebar, header, sync, and team dialog #12732 — TUI integration (sidebar, header, sync, team dialog, prompt)
By the numbers:
- ~1,500 lines of core implementation (team state, messaging, events, 9 tools)
- ~1,100 lines of TUI integration (sidebar panels, header badges, sync store, team dialog, prompt bar)
- ~8,500 lines of tests across 14 test files (unit, integration, e2e, edge cases, persistence, recovery, plan approval, spawn permissions, auto-wake, delegate cleanup, scaling scenarios)
- Multi-model tested (Claude + Gemini + OpenAI teammates in one team)
Open Questions
- Should there be a max team size limit?
- Should teammate prompt loops auto-restart on server recovery, or is lead-driven re-spawn sufficient?
Related
- [FEATURE]: Add Agent Teams Equivalent or Better #12661 — "Add Agent Teams Equivalent or Better"
- [FEATURE]: Multi-Agent Coding #9649 — Multi-Agent Coding request
- feat: parallel subtask #6478 — Parallel subtask execution
- PR feat(task): Add subagent-to-subagent delegation with budgets, persistent sessions, and hierarchical session navigation #7756 — Subagent-to-subagent delegation (tree-based approach)

