feat: add team tools, HTTP routes, and tool registry integration#12731
feat: add team tools, HTTP routes, and tool registry integration#12731ugoenyioha wants to merge 6 commits intoanomalyco:devfrom
Conversation
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
|
The following comment was made by an LLM, it may be inaccurate: Based on my search, I found two related PRs that are part of the same feature stack:
These are not duplicates but rather sequential dependencies in a 3-part feature implementation for agent teams. PR #12731 is the middle piece that adds the tool layer and API routes between the core primitives (#12730) and the UI integration (#12732). |
a2b08b8 to
13e20a3
Compare
72a476a to
9046ac9
Compare
…tative - Set shutdown_requested BEFORE sending message (fixes autoWake race) - Remove force:true from shutdown transition (prevent resurrection) - Fallback to direct shutdown if message delivery fails - Make shutdown authoritative: updated description and message text
d6aa931 to
f6f9159
Compare
… test - Update tool/team.ts with shutdown race condition fix - Update server routes, tool registry to latest dev - Add task-team-isolation test - Sync team core deps (events, index, messaging)
Summary
Adds the tool and API layer for agent teams (Fixes #12711). Depends on #12730 — merge that first.
This is PR 2/3. It exposes the Team namespace from PR 1 as 9 MCP tools the LLM can call, plus HTTP routes for TUI consumption. All tools are conditionally registered behind the
OPENCODE_EXPERIMENTAL_AGENT_TEAMSfeature flag.What's included
Business logic in Team namespace (
team/index.ts— +333 lines over PR 1)Core team operations live in the Team namespace, not the tool layer. Tools are thin wrappers that handle authorization checks and format output.
New Team functions:
Team.resolveModel()— Model resolution with priority chain: explicitprovider/modelparam → agent config → lead's last model → global default. Validates against configured providers with fuzzy suggestions on miss.Team.spawnMember()— Creates child session, registers member (with orphaned session cleanup onaddMemberfailure), constructs teammate context message, launches fire-and-forget prompt loop. Sync-throw guard onSessionPrompt.loop().Team.approvePlan()— Removes plan-approval deny rules from teammate session, updates plan state, notifies teammate via team message.Team.autoCleanup()— Subscribes toTeamEvent.MemberStatusChanged. When all members reach"shutdown", auto-cleans the team. Safety net that doesn't depend on the LLM remembering to callteam_cleanup.Team.onCleanedRestorePermissions()— Subscribes toTeamEvent.Cleaned. Restores lead session permissions when a delegate-mode team is cleaned up. Decouples cleanup from direct Session imports.notifyLead()— Sends idle/error notification to lead when a teammate's prompt loop finishes. UsessetMemberStatuswith{ guard: true }to prevent overwriting"shutdown"(TOCTOU prevention).Team tools (
tool/team.ts— 557 lines)9 MCP tools, each a thin wrapper over Team namespace methods with authorization checks and formatted output:
team_createdelegatemode restricts lead to coordination-only. Optional initial task list. Prevents nested teams.team_spawnTeam.spawnMember(). Configurable agent type, model, initial prompt, auto-claim task, and optionalrequire_plan_approval. Wraps spawnMember in try/catch for proper error reporting.team_message"lead".team_broadcastteam_tasksteam_claimteam_approve_planTeam.approvePlan().team_shutdownteam_cleanupSecurity & authorization:
team_create,team_spawn,team_shutdown,team_cleanup,team_approve_planvia session permission rules"lead"rejected on spawn*:plan-approval) distinct from delegate deny patterns (*) so they can be independently managedbash,write,edit,multiedit,apply_patch) to the lead sessionTeammate system prompt design
Teammates always receive the full provider-specific system prompt for their model (e.g.
PROMPT_ANTHROPICfor Claude,PROMPT_BEASTfor GPT-4/o1/o3,PROMPT_GEMINIfor Gemini,PROMPT_CODEXfor GPT-5/Codex). This matches Claude Code's behavior where sub-agents get the same system prompt as standalone sessions.How it works: Teammate sessions are marked with
session.teammate = true. Inllm.ts, system prompt construction becomes additive for teammates:Empty-provider fallback: if
SystemPrompt.provider(model)returns empty for a teammate, falls back toSystemPrompt.instructions().For Codex teammates,
options.instructionsis always set (API requirement).The team-specific context (role identity, available tools, communication rules) is injected as a user message, not a system prompt — keeping it separate from the provider behavioral guidance.
Event-based decoupling
Team.cleanup()no longer imports Session directly. Instead it publishesTeamEvent.CleanedwithleadSessionIDanddelegatefields. TheonCleanedRestorePermissions()listener (wired in bootstrap) subscribes to this event and handles the Session.update to remove delegate deny rules. This keeps the team module decoupled from session internals.HTTP routes (
server/routes/team.ts— 130 lines)Routes use
hono-openapiwithdescribeRoute,validator, andresolvermiddleware for OpenAPI metadata, request validation, and consistent error responses:GET /team— List all teamsGET /team/:name— Get team by nameGET /team/:name/tasks— Get team's task listGET /team/by-session/:sessionID— Find team context for a session (team info + tasks + role)POST /team/:name/delegate— Toggle delegate mode (validates body with Zod schema)Bootstrap wiring (
project/bootstrap.ts)Team.onCleanedRestorePermissions()— wired before recoveryTeam.recover()— marks stale teammates as interruptedTeam.autoCleanup()— wired after recovery completesRegistry integration (
tool/registry.ts)Flag.OPENCODE_EXPERIMENTAL_AGENT_TEAMSis enabledServer integration (
server/server.ts)TeamRoutes()at/teampath — single 2-line changeTests
11 test files, 134 tests covering:
team.test.tsteam-spawn.test.tssession.teammateflagteam-e2e.test.tsteam-edge-cases.test.tsteam-scenarios.test.tsteam-plan-approval.test.tsteam-delegate-cleanup.test.tsteam-integration.tsteam-multi-model.tsteam-scenarios-integration.tsFiles changed
src/tool/team.tssrc/team/index.tssrc/server/routes/team.tssrc/project/bootstrap.tssrc/session/llm.tssrc/session/index.tsteammateflag to Session.Infosrc/session/prompt.tsteammate+sessionPermissionto LLMsrc/tool/registry.tssrc/server/server.tstest/team/*.test.tsStack
PR 2/3 — merge in order: