anthropics / anthropics/claude-code
[Bug] Agent teams: separate-process teammates honour a plugin agent's restricted `tools:`, so they can never SendMessage a report back
- Dominant language
- Python
- Stars
- 145k
- Forks
- 23.1k
- PR merge metrics
- PR metrics pending
Description
### Summary
A teammate's only channel for returning a result is `SendMessage`. When a teammate's `--agent-type` resolves to a **plugin** agent whose frontmatter declares a restricted `tools:` list, that list is honoured — and because it contains neither `SendMessage` nor `ToolSearch`, the teammate completes its work and has **no way to deliver it**. It goes idle and the lead receives a contentless `idle_notification`. Nothing errors, so the failure is invisible from both sides.
### Evidence — controlled comparison, same session and launch path
| `--agent-type` | tools declared | report delivered? |
|---|---|---|
| `feature-dev:code-reviewer` (×5) | no `SendMessage` / no `ToolSearch` | ❌ 0 / 5 |
| `general-purpose` (×3) | `*` | ✅ 3 / 3 |
Only the agent type differed. Asked to enumerate its own tools, a `feature-dev:code-reviewer` teammate replied:
> I have access to these tools in this session: `Read`, `WebFetch`, `WebSearch`, `TaskStop`, `TaskOutput`, `Glob`, `Grep`. I don't have `SendMessage` or `ToolSearch` — I can't message teammates or search for additional tools.
Another wrote its finished report into its final assistant message with the note:
> Note: The `SendMessage` tool isn't available in this session, so I'm delivering the report directly here.
The work existed in every case; only delivery was impossible. Recovering it required reading each agent's `.jsonl` transcript out of band. A stale inbox at `~/.claude/teams//inboxes/.json` still holds 2 undelivered inbound messages for one such agent.
### Why `ToolSearch` matters too
Per the analysis in #68408, `SendMessage` is a **deferred** tool: its schema must be loaded via `ToolSearch("select:SendMessage")` before it can be invoked. An agent whose `tools:` list omits **both** therefore has no recovery path — it cannot even discover the tool.
### This appears to be backend-dependent
#78234 reports that for **in-process** teammates, plugin-scoped subagent definitions are silently *dropped* (the teammate spawns with `tools: ["*"]`). We observe the **opposite** for teammates spawned as **separate `claude` processes**: the plugin definition *is* applied, restricted tool list included. If both observations hold, teammate tool resolution differs by backend, and only the separate-process path is affected by this bug.
### Also observed: the tool list has drifted
The plugin declares `Glob, Grep, LS, Read, NotebookRead, WebFetch, TodoWrite, WebSearch, KillShell, BashOutput`, but the teammate actually reports `Read, WebFetch, WebSearch, TaskStop, TaskOutput, Glob, Grep` — `LS`, `NotebookRead` and `TodoWrite` resolve to nothing, and `KillShell`/`BashOutput` surface as `TaskStop`/`TaskOutput`. Unrelated to the delivery bug, but it suggests plugin agent definitions aren't validated against the current tool registry.
### Expected
Any one of:
1. **Always grant team-coordination tools** (`SendMessage`, and `ToolSearch` while `SendMessage` remains deferred) to teammates regardless of the definition's `tools:` list. The agent-teams docs already imply coordination tools are always available to a teammate.
2. **Make `SendMessage` non-deferred** so it needs no `ToolSearch` to invoke (also suggested in #68408).
3. **Fail loudly at spawn** if a teammate's resolved toolset cannot reach `SendMessage`, instead of silently producing an agent that can never report.
### Repro
1. `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`, teammates spawned as separate `claude` processes into tmux panes.
2. Spawn a teammate with `--agent-type feature-dev:code-reviewer` (any plugin agent with a restricted `tools:` list) and instruct it to `SendMessage` its result to the lead.
3. It performs the work, then goes idle. The lead receives only a bare `idle_notification` with no content. The report is present in the agent's transcript.
4. Repeat with `--agent-type general-purpose` → delivery succeeds.
### Note on setup
Our teammates are launched into panes managed by a local IDE that provides a **shim `tmux` on `PATH`** and intercepts tmux commands, rather than genuine tmux. The shim only handles pane creation/teardown — `--agent-type` resolution and tool assignment happen inside the real spawned `claude` process (launched with `--agent-id/--agent-name/--team-name/--agent-type/--settings`). Flagging it for reproducibility, since it may or may not be relevant.
### Environment
- Claude Code 2.1.219
- macOS
- `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`
- Plugin: `feature-dev@claude-plugins-official`, `gitCommitSha` `96276205880a60fd66bbae981f5ab568e70c4cbf`
### Related
- #68408 — `SendMessage` advertised but unavailable / deferred-schema problem
- #74113 — background agents go idle without delivering their final `SendMessage` report
- #78234 — plugin-scoped subagent definitions silently ignored in agent teams (in-process path)
- #80569 — teammates ignore `effort` frontmatter from subagent definitions
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by running the separate-process repro with --agent-type feature-dev:code-reviewer and general-purpose, comparing resolved tools and report delivery through SendMessage and ToolSearch. Trace tool assignment during the spawned claude process and verify that a restricted teammate can deliver its report or fails loudly at spawn instead of producing only an idle_notification.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- ai-infra-agents, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100