TL;DR In the background a subagent keeps every MCP tool but only 19 built-in ones. Check your
toolsfield against that list and ask for the foreground when it declares something outside it, because the filter applies anyway and says nothing. That is how you stop debugging a subagent that looks like it ignores its own config.
You put ListAgents in your subagent's tools. You dispatch it. It doesn't have the tool. No error, no warning, and the file is written correctly.
The cause isn't your config. It's where the subagent runs. As of v2.1.198 subagents start in the background by default, and the background comes with its own tool cut.
Two filters, not one
A subagent inherits the built-in and MCP tools of the main conversation, then passes through two filters in sequence.
The first one hits every subagent, wherever it runs, and removes these even when you list them:
AskUserQuestion EndConversation EnterPlanMode ExitPlanMode
ScheduleWakeup TaskOutput WaitForMcpServers Workflow
ExitPlanMode survives when the subagent has permissionMode: plan. And Agent only goes when the subagent is already at the depth limit, so an ordinary subagent can still spawn its own.
That is the first surprise: a subagent can never ask you anything. Not a background thing, a subagent thing. It does what it can with what it understood.
The second filter applies only in the background. It keeps every MCP tool, and of the built-ins it leaves exactly these 19:
Read Grep Glob Bash PowerShell
Edit Write NotebookEdit WebFetch WebSearch
TodoWrite Skill ToolSearch EnterWorktree ExitWorktree
Monitor TaskStop SendMessage Artifact
Everything else goes. Including whatever you wrote in tools. And silently: the removal only complains when it leaves your list empty, in which case the subagent never launches.
Which means one definition resolves to different tools depending on where it ends up running.
The one you feel first
SendMessage is on the list. ListAgents is not. So a background subagent can send a message to another session but can't discover who to send it to. Give it work that depends on talking to your other sessions and it works in the foreground, then quietly half-works in the background.
Agent team teammates are the exception: on top of the 19 they keep TaskCreate, TaskGet, TaskList, TaskUpdate, CronCreate, CronDelete, and CronList.
The other exception is conversation forks, which skip both filters and get the main conversation's exact tool pool.
And where it runs decides one more thing that stings just as much: what a background subagent edits does not come back with a rewind. Only a skill with context: fork in the foreground is covered by checkpoints; for everything else your undo button is git.
How you steer it
1. Diff your tools against the 19
If your subagent declares anything outside that list, and it isn't a fork or a teammate, the background version won't have it.
2. Ask for the foreground when you delegate
There is no background: false. The documented way is to say it in the request itself:
Investigate the auth failure with a subagent, in the foreground
A foreground subagent blocks the conversation until it's done, and in exchange it keeps every tool the first filter left it.
3. Or pin it the other way
In the subagent's frontmatter:
---
name: researcher
description: Investigates and summarizes, never writes
background: true
---
With background: true that subagent goes to the background even when Claude needs its result right away. Leave the field out and Claude decides, defaulting to the background. It's the field missing from the field table in how to create an agent, which covers the neighbouring piece: --agent turns your main session into the agent, and no background filter applies there.
What you get for the trade
The cut buys you something real: the background is why your session no longer freezes behind a delegate. As of v2.1.186, when a background subagent hits a call that needs permission, the prompt surfaces in your main session naming the subagent that's asking. Approve it, or press Esc to deny that one call without killing the subagent. Before that version, a background subagent auto-denied anything requiring permission, in silence, which is a good deal worse than losing ListAgents.
While it runs you'll find it in the /tasks panel, where finished ones stay listed below the work still going. To push something already running into the background, that's Ctrl+B and it lives in bash mode. And if the level you care about is whole sessions rather than subagents inside one, the map is background agents.
Reference
| You want… | Use |
|---|---|
| A subagent that keeps all its tools | Ask for the foreground when you delegate |
| It to always run in the background | background: true in its frontmatter |
| To see what's running | /tasks |
| To raise or lower the 20 concurrent cap | CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS |
| To turn background tasks off entirely | CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 |
With 20 subagents running, the next one fails with Concurrent subagent limit reached, and Claude is told not to retry. Spawning works again as soon as one finishes.
Official docs: Create custom subagents