|
| 1 | +# Agent Teams Proposal |
| 2 | + |
| 3 | +## Status |
| 4 | + |
| 5 | +Proposal for design review and contribution planning. |
| 6 | + |
| 7 | +Agent teams are an experimental multi-agent orchestration feature. The goal of this document is to make the intended behavior reviewable before the feature is treated as stable user-facing functionality. |
| 8 | + |
| 9 | +Reference implementation: https://github.com/panwar-stack/opencode/commit/c9196991a16f2386f1d83d8deebf94097fb097f0 |
| 10 | + |
| 11 | +## Summary |
| 12 | + |
| 13 | +Agent teams let one OpenCode lead session create and coordinate multiple background teammate sessions. Each teammate is a normal child session with its own agent type, prompt, status, mailbox, optional dependencies, and optional plan approval. |
| 14 | + |
| 15 | +The feature is enabled explicitly: |
| 16 | + |
| 17 | +```json |
| 18 | +{ |
| 19 | + "experimental": { |
| 20 | + "agent_teams": true |
| 21 | + } |
| 22 | +} |
| 23 | +``` |
| 24 | + |
| 25 | +Once enabled, the lead agent can use team tools to create a team, spawn teammates, route messages, track shared tasks, approve plans, and shut down the team. |
| 26 | + |
| 27 | +## Problem |
| 28 | + |
| 29 | +The existing subagent model is useful for isolated delegated tasks, but it does not provide durable coordination primitives. Complex work often needs: |
| 30 | + |
| 31 | +- multiple agents running in parallel |
| 32 | +- explicit handoffs between agents |
| 33 | +- dependency ordering between pieces of work |
| 34 | +- a way for child sessions to communicate with the lead |
| 35 | +- progress visibility in the TUI |
| 36 | +- a controlled planning gate before a teammate can mutate files |
| 37 | + |
| 38 | +Without these primitives, orchestration is encoded in prompts and final answers, which makes coordination brittle and hard to review. |
| 39 | + |
| 40 | +## Goals |
| 41 | + |
| 42 | +- Allow one lead session to coordinate a bounded set of teammate sessions. |
| 43 | +- Keep teammates as normal child sessions so existing session storage, permissions, navigation, and cancellation still apply. |
| 44 | +- Support non-blocking teammate spawning. |
| 45 | +- Support dependency-based start ordering between teammates. |
| 46 | +- Provide a mailbox for lead-to-teammate and teammate-to-teammate communication. |
| 47 | +- Provide a shared task list for lightweight work tracking. |
| 48 | +- Support plan approval mode for review-before-write workflows. |
| 49 | +- Surface team status, pending permissions, tasks, and messages in the TUI. |
| 50 | +- Keep the feature behind `experimental.agent_teams` until the behavior is stable. |
| 51 | + |
| 52 | +## Non-goals |
| 53 | + |
| 54 | +- Replacing normal subagents or the Task tool. |
| 55 | +- Running arbitrary remote workers. |
| 56 | +- Guaranteeing deterministic multi-agent execution. |
| 57 | +- Solving merge conflicts between teammates automatically. |
| 58 | +- Adding organization/workspace membership semantics. |
| 59 | +- Making the shared task list a scheduler by itself. |
| 60 | + |
| 61 | +## User Experience |
| 62 | + |
| 63 | +### Create a team |
| 64 | + |
| 65 | +The lead session creates one active team: |
| 66 | + |
| 67 | +```txt |
| 68 | +Use agent teams. Create a team named api-refactor to split exploration, |
| 69 | +implementation, and review. |
| 70 | +``` |
| 71 | + |
| 72 | +Only one active team can exist per lead session. A closed team should allow a new team to be created for the same lead session. |
| 73 | + |
| 74 | +### Spawn teammates |
| 75 | + |
| 76 | +The lead spawns teammates with a name, agent type, and role prompt: |
| 77 | + |
| 78 | +```txt |
| 79 | +Spawn an explorer teammate to inspect auth routes. |
| 80 | +Spawn an implementer teammate that waits for the explorer. |
| 81 | +``` |
| 82 | + |
| 83 | +The spawn should return immediately with teammate metadata while the child session runs in the background. |
| 84 | + |
| 85 | +### Coordinate work |
| 86 | + |
| 87 | +Team members communicate through mailbox messages. Recipients can be: |
| 88 | + |
| 89 | +- `lead` |
| 90 | +- teammate name |
| 91 | +- teammate session ID |
| 92 | +- comma-separated recipients |
| 93 | + |
| 94 | +Teammates should send kickoff, progress, blocker, handoff, and completion updates through the mailbox. |
| 95 | + |
| 96 | +### Track tasks |
| 97 | + |
| 98 | +The shared task list records team-level work: |
| 99 | + |
| 100 | +- `pending` |
| 101 | +- `in_progress` |
| 102 | +- `completed` |
| 103 | +- `cancelled` |
| 104 | + |
| 105 | +Task dependencies gate claiming, but creating a task does not spawn or wake an agent. |
| 106 | + |
| 107 | +### Approve plans |
| 108 | + |
| 109 | +A teammate can start in plan mode. In plan mode, mutating tools are denied until the lead approves the submitted plan. |
| 110 | + |
| 111 | +Plan mode blocks: |
| 112 | + |
| 113 | +- `bash` |
| 114 | +- `write` |
| 115 | +- `edit` |
| 116 | +- `apply_patch` |
| 117 | + |
| 118 | +Approving a plan removes the deny rules and wakes the teammate. Rejecting a plan sends feedback and keeps the teammate in plan mode. |
| 119 | + |
| 120 | +### Shut down |
| 121 | + |
| 122 | +Shutting down a team closes the team and cancels active teammate sessions. It does not cancel the lead session. |
| 123 | + |
| 124 | +## Tools |
| 125 | + |
| 126 | +| Tool | Purpose | |
| 127 | +| ---- | ------- | |
| 128 | +| `team_create` | Create the active team for the current lead session. | |
| 129 | +| `team_spawn` | Spawn a non-blocking teammate child session. | |
| 130 | +| `team_send_message` | Send mailbox messages to one or more recipients. | |
| 131 | +| `team_broadcast` | Send one message to all active teammates, and to the lead when called by a teammate. | |
| 132 | +| `team_get_messages` | Read pending mailbox messages for the current team session. | |
| 133 | +| `team_task_create` | Create a shared task record. | |
| 134 | +| `team_task_list` | List team tasks. | |
| 135 | +| `team_task_claim` | Claim a pending task after dependencies are complete. | |
| 136 | +| `team_task_update` | Update task status or assignee. | |
| 137 | +| `team_plan_submit` | Submit a teammate plan to the lead. | |
| 138 | +| `team_plan_decide` | Approve or reject a teammate plan. | |
| 139 | +| `team_shutdown` | Close the active team and cancel active teammates. | |
| 140 | + |
| 141 | +## Data Model |
| 142 | + |
| 143 | +The feature needs four persisted concepts: |
| 144 | + |
| 145 | +### Team |
| 146 | + |
| 147 | +- `id` |
| 148 | +- `name` |
| 149 | +- `goal` |
| 150 | +- `lead_session_id` |
| 151 | +- `status`: `active`, `closed`, `cancelled` |
| 152 | +- timestamps |
| 153 | + |
| 154 | +Constraint: one active team per `lead_session_id`. |
| 155 | + |
| 156 | +### Team member |
| 157 | + |
| 158 | +- `id` |
| 159 | +- `team_id` |
| 160 | +- `session_id` |
| 161 | +- `name` |
| 162 | +- `agent_type` |
| 163 | +- `model` |
| 164 | +- `role_prompt` |
| 165 | +- `status`: `starting`, `blocked`, `active`, `idle`, `completed`, `cancelled` |
| 166 | +- `plan_mode` |
| 167 | +- `work_mode`: `plan`, `implement` |
| 168 | +- `dependency_ids` |
| 169 | +- `result` |
| 170 | +- timestamps |
| 171 | + |
| 172 | +Constraint: one team member per child `session_id`. |
| 173 | + |
| 174 | +### Team task |
| 175 | + |
| 176 | +- `id` |
| 177 | +- `team_id` |
| 178 | +- `description` |
| 179 | +- `status`: `pending`, `in_progress`, `completed`, `cancelled` |
| 180 | +- `assignee` |
| 181 | +- `dependency_ids` |
| 182 | +- `metadata` |
| 183 | +- timestamps |
| 184 | + |
| 185 | +### Team message |
| 186 | + |
| 187 | +- `id` |
| 188 | +- `team_id` |
| 189 | +- `sender` |
| 190 | +- `recipients` |
| 191 | +- `body` |
| 192 | +- `delivery_status`: `pending`, `delivered`, `read` |
| 193 | +- timestamps |
| 194 | + |
| 195 | +Message recipients should be tracked separately so each recipient can have its own delivery state. |
| 196 | + |
| 197 | +## HTTP API |
| 198 | + |
| 199 | +The server should expose enough team state for clients to display and manage teams: |
| 200 | + |
| 201 | +```txt |
| 202 | +GET /team?sessionID=<sessionID> -> TeamInfo |
| 203 | +GET /team/:teamID -> TeamInfo |
| 204 | +GET /team/:teamID/tasks -> TeamTask[] |
| 205 | +GET /team/:teamID/messages -> TeamMessage[] |
| 206 | +POST /team/:teamID/shutdown -> boolean |
| 207 | +``` |
| 208 | + |
| 209 | +If these endpoints change, regenerate the SDK after updating the OpenAPI surface. |
| 210 | + |
| 211 | +## TUI |
| 212 | + |
| 213 | +The TUI should expose team state without forcing users to inspect child sessions manually. |
| 214 | + |
| 215 | +Required surfaces: |
| 216 | + |
| 217 | +- sidebar team section with teammate count, status, and pending permission/question count |
| 218 | +- team panel with overview, tasks, and messages tabs |
| 219 | +- shutdown action |
| 220 | +- child-session navigation for teammate sessions |
| 221 | + |
| 222 | +Default team keybinds: |
| 223 | + |
| 224 | +| Keybind | Default | Purpose | |
| 225 | +| ------- | ------- | ------- | |
| 226 | +| `team_panel_toggle` | `<leader>v` | Open the team panel. | |
| 227 | +| `team_task_list` | `<leader>k` | Open the team panel on tasks. | |
| 228 | +| `team_cycle_lead` | `<leader>up` | Navigate from a teammate to the lead session. | |
| 229 | + |
| 230 | +## Permissions and Safety |
| 231 | + |
| 232 | +- The feature must remain behind `experimental.agent_teams`. |
| 233 | +- Teammates should inherit parent deny rules and external-directory protection. |
| 234 | +- Plan mode must deny mutating tools until explicit lead approval. |
| 235 | +- Team shutdown must cancel active teammate runs. |
| 236 | +- Mailbox delivery should wake idle sessions when prompt operations are available. |
| 237 | +- The lead should receive automatic start, blocked, completed, idle, and cancelled updates. |
| 238 | + |
| 239 | +## Contribution Plan |
| 240 | + |
| 241 | +Review and contribution can be split into small PRs: |
| 242 | + |
| 243 | +1. Core team service |
| 244 | + - schema tables |
| 245 | + - team create/get/shutdown |
| 246 | + - member lifecycle |
| 247 | + - messages and recipients |
| 248 | + - tasks and dependencies |
| 249 | + |
| 250 | +2. Team tools |
| 251 | + - create, spawn, messaging, tasks, plan approval, shutdown |
| 252 | + - clear disabled-state output when `experimental.agent_teams` is false |
| 253 | + - dependency resolution by teammate name or session ID |
| 254 | + |
| 255 | +3. Prompt integration |
| 256 | + - deliver pending mailbox messages as synthetic user context |
| 257 | + - mark delivered messages after insertion |
| 258 | + - preserve normal session loop behavior |
| 259 | + |
| 260 | +4. TUI integration |
| 261 | + - sidebar teammate status |
| 262 | + - team panel |
| 263 | + - team keybinds |
| 264 | + - pending permission/question visibility |
| 265 | + |
| 266 | +5. HTTP API and SDK |
| 267 | + - team read endpoints |
| 268 | + - shutdown endpoint |
| 269 | + - OpenAPI annotations |
| 270 | + - SDK regeneration |
| 271 | + |
| 272 | +6. Documentation |
| 273 | + - user guide |
| 274 | + - server API docs |
| 275 | + - keybind docs |
| 276 | + - config docs |
| 277 | + |
| 278 | +## Testing Plan |
| 279 | + |
| 280 | +Run tests from package directories, not the repo root. |
| 281 | + |
| 282 | +Core tests in `packages/opencode` should cover: |
| 283 | + |
| 284 | +- creating a team |
| 285 | +- rejecting duplicate active teams for the same lead |
| 286 | +- creating a new team after shutdown |
| 287 | +- adding and listing members |
| 288 | +- updating member status |
| 289 | +- creating, claiming, and updating tasks |
| 290 | +- blocking task claims until dependencies complete |
| 291 | +- sending and delivering messages per recipient |
| 292 | +- shutdown cancellation behavior |
| 293 | + |
| 294 | +Tool tests should cover: |
| 295 | + |
| 296 | +- disabled config behavior |
| 297 | +- missing active team behavior |
| 298 | +- unknown agent type |
| 299 | +- missing dependencies |
| 300 | +- blocked teammates starting after dependency completion |
| 301 | +- plan submit and decide flow |
| 302 | +- mailbox wake behavior when prompt operations exist |
| 303 | + |
| 304 | +TUI tests should cover: |
| 305 | + |
| 306 | +- team sidebar plugin registration |
| 307 | +- team sidebar active state when `experimental.agent_teams` is true |
| 308 | +- plugin disabled state when the internal team plugin is disabled |
| 309 | + |
| 310 | +Suggested verification commands: |
| 311 | + |
| 312 | +```bash |
| 313 | +cd packages/opencode |
| 314 | +bun test test/team test/tool/team_spawn.test.ts test/cli/tui/plugin-team.test.ts |
| 315 | +bun typecheck |
| 316 | +``` |
| 317 | + |
| 318 | +If the SDK changes: |
| 319 | + |
| 320 | +```bash |
| 321 | +./packages/sdk/js/script/build.ts |
| 322 | +``` |
| 323 | + |
| 324 | +## Review Checklist |
| 325 | + |
| 326 | +- Does the feature add enough value over existing subagents to justify new primitives? |
| 327 | +- Are lead and teammate responsibilities clear? |
| 328 | +- Are tool names and arguments understandable to models and users? |
| 329 | +- Is plan mode restrictive enough before approval? |
| 330 | +- Is shutdown behavior predictable? |
| 331 | +- Is mailbox delivery state sufficient for multiple recipients? |
| 332 | +- Are task dependencies intentionally lightweight, or do they need scheduler semantics? |
| 333 | +- Are HTTP endpoints read-only except shutdown? |
| 334 | +- Is the experimental gate strict enough? |
| 335 | +- Are docs clear that this is agent orchestration, not workspace/team membership? |
| 336 | + |
| 337 | +## Open Questions |
| 338 | + |
| 339 | +- Should `team_spawn` expose model override arguments, or only use the selected agent's configured model? |
| 340 | +- Should completed teammate results be summarized before sending to the lead for very long outputs? |
| 341 | +- Should task updates enforce lead-or-assignee authorization, or is model-level guidance enough? |
| 342 | +- Should messages support `read` separately from `delivered`, or is one delivered state sufficient? |
| 343 | +- Should teams survive process restarts and resume blocked/running teammate state, or should active runs be treated as ephemeral? |
| 344 | +- Should team APIs expose members directly, or should clients continue deriving members from child sessions? |
| 345 | +- Should team tools be hidden from non-team sessions until a team exists? |
| 346 | + |
| 347 | +## Stability Criteria |
| 348 | + |
| 349 | +Agent teams can graduate from experimental when: |
| 350 | + |
| 351 | +- the team data model has no known migration blockers |
| 352 | +- the TUI can show all important team state |
| 353 | +- teammate cancellation and plan approval are reliable |
| 354 | +- mailbox delivery behaves consistently across lead and teammate sessions |
| 355 | +- API and SDK shapes are stable |
| 356 | +- docs include user-facing examples and limitations |
0 commit comments