Preflight Checklist
What's Wrong?
Sub-agents spawned via the Agent tool cannot themselves spawn nested sub-agents. The Task / Agent ephemeral spawn primitive is available to the top-level Claude Code session, but it is silently filtered out of the tool surface inside spawned sub-agent contexts, even when the agent definition's frontmatter declares tools: All tools (or leaves tools: unset, inheriting defaults).
This is a contract mismatch. The frontmatter promises full tool access; the runtime delivers a restricted set. Only the persistent-teammate primitive (TeamCreate / SendMessage / TeamDelete) is reachable from within a sub-agent, which breaks the ephemeral fresh-context spawn pattern that hierarchical orchestrators are designed around.
Affected agent surface from inside a sub-agent context (Claude Code, Opus 4.7):
- Present:
TeamCreate, TeamDelete, SendMessage, TaskOutput, TaskStop, plus standard file/shell tools.
- Absent:
Task, Agent.
The sub-agent has no way to detect this silently-filtered state at startup. The failure surfaces only at the first attempted nested spawn, which makes it look like a manifest or task problem when it is actually a harness configuration gap.
What Should Happen?
Sub-agents declared with tools: All tools (or tools: unset) should have Task / Agent accessible from within their own context. The frontmatter contract should match the runtime tool surface.
If filtering nested-spawn primitives at depth > 1 is intentional (for example security or cost containment), then ONE of the following should be true:
- The restriction is documented in the agent-definition spec, so authors do not design hierarchical orchestrators that silently halt at runtime.
- The restriction is opt-in-able via an explicit frontmatter field, for example
nested_spawn: enabled, defaulting to current restricted behavior but allowing authors to declare hierarchical-orchestrator intent.
- The restriction emits a structured error or warning when the sub-agent attempts a nested spawn, instead of behaving as if the tool simply was not requested.
Of these, option 1 (just expose the primitive) is preferred because the existing agent-definition frontmatter already declares the contract. Option 2 is acceptable if there is a real reason to default-deny. Option 3 alone is insufficient because it leaves the orchestrator pattern unimplementable.
Error Messages/Logs
There is no error message at the harness layer. The failure mode is silent at spawn time. The sub-agent observes its own tool surface and halts based on what it sees.
Below is the run log emitted by my batch-executor sub-agent (a real CLO batch invocation, 4 tasks) when it discovered the gap at the cohort spawn step:
---
# Run Log: BATCH_2026_05_24_canon_clo_cohesion_partition
## Halt Rate
- halted_items: 0
- dispatched_items: 0
- skipped_items: 0
- halt_rate: undefined
## Halt Causes
## Items
(No items reached the per-item dispatch gate. The batch halted at the cohort-spawn stage; see Run Outcome below.)
## Run Outcome
Status: failed (contract-floor halt at wave_1 cohort spawn)
Halt point: batch-executor Process Step 3 (Execute Path), immediately before the wave_1 cohort spawn.
Cause: The harness exposes no per-item ephemeral subagent-spawn primitive (Task / Agent). Only TeamCreate (persistent teammate model) and SendMessage are available. The batch-executor spec requires spawning one fresh worker per checklist item with stateless single-iteration context. This contract is non-negotiable per the CLO pattern.
TeamCreate would create persistent teammates that accumulate cross-item context across turns, violating the worker's stateless-per-invocation guarantee. Adopting it is a substantive contract change requiring sandbox validation, not a like-for-like swap.
What was NOT executed:
- No worker spawn attempted (primitive absent).
- No work-items dispatched.
- No commits made.
- No files modified.
---
The sub-agent's final-message verdict to its parent orchestrator was:
"Halt point: pre-spawn for wave_1 cohort. No worker received a prompt. Zero commits, zero checklist mutations. Harness exposes no per-item ephemeral subagent-spawn primitive. TeamCreate would violate clo-executor persistence: stateless frontmatter and the fresh-context-per-item contract."
No stack trace. No exception. No console error from the Claude Code CLI itself. The gap is observable only by the sub-agent introspecting its own available tools.
Steps to Reproduce
Minimal reproduction in any Claude Code workspace.
Step 1. Create a parent orchestrator agent definition at .claude/agents/repro-parent.md:
name: repro-parent
description: Reproduction harness for nested-spawn gap. Attempts to spawn a child sub-agent from within itself.
model: opus
tools: All tools
Repro Parent
When invoked, attempt to spawn a child sub-agent named repro-child via the Agent tool. Report whether the spawn primitive was available in your tool surface, and what tools you observed (specifically: was Task or Agent present, or only TeamCreate / SendMessage?). Do not actually do any real work.
Step 2. Create a child agent definition at .claude/agents/repro-child.md:
name: repro-child
description: Trivial leaf worker for the nested-spawn reproduction.
model: haiku
tools: All tools
Repro Child
Return the string "child reached" and exit. No file operations needed.
Step 3. From a top-level Claude Code session, invoke the parent orchestrator:
Agent(subagent_type="repro-parent", prompt="Attempt to spawn repro-child via Agent. Report tool surface inventory.")
Step 4. Observe the parent agent's response.
Expected: the parent successfully spawns the child, the child returns "child reached", and the parent reports Task / Agent was available in its tool surface.
Actual: the parent reports that Task and Agent are absent from its tool surface; only TeamCreate, SendMessage, TeamDelete, TaskOutput, TaskStop (plus standard non-orchestration tools) are present. The child is never spawned.
Step 5. To confirm this is a nested-context restriction and not a global one, run from the same top-level session:
Agent(subagent_type="repro-child", prompt="say hello")
Expected and actual: this works fine. The child returns "child reached". The Agent primitive is available at the top level. Only the nested context filters it.
Notes:
- Both agent definitions declare
tools: All tools in frontmatter, which should grant access to every available tool including the orchestration primitive.
- No
.claude/settings.json permission rules or hook configurations affect this; the filtering is at the harness layer.
- Reproduction was observed on Windows 10 with Claude Code CLI, model Opus 4.7, date 2026-05-24.
Claude Model
Opus
Is this a regression?
No, this never worked
Last Working Version
No response
Claude Code Version
2.1.146
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Cursor
Additional Information
No response
Preflight Checklist
What's Wrong?
Sub-agents spawned via the
Agenttool cannot themselves spawn nested sub-agents. TheTask/Agentephemeral spawn primitive is available to the top-level Claude Code session, but it is silently filtered out of the tool surface inside spawned sub-agent contexts, even when the agent definition's frontmatter declarestools: All tools(or leavestools:unset, inheriting defaults).This is a contract mismatch. The frontmatter promises full tool access; the runtime delivers a restricted set. Only the persistent-teammate primitive (
TeamCreate/SendMessage/TeamDelete) is reachable from within a sub-agent, which breaks the ephemeral fresh-context spawn pattern that hierarchical orchestrators are designed around.Affected agent surface from inside a sub-agent context (Claude Code, Opus 4.7):
TeamCreate,TeamDelete,SendMessage,TaskOutput,TaskStop, plus standard file/shell tools.Task,Agent.The sub-agent has no way to detect this silently-filtered state at startup. The failure surfaces only at the first attempted nested spawn, which makes it look like a manifest or task problem when it is actually a harness configuration gap.
What Should Happen?
Sub-agents declared with
tools: All tools(ortools:unset) should haveTask/Agentaccessible from within their own context. The frontmatter contract should match the runtime tool surface.If filtering nested-spawn primitives at depth > 1 is intentional (for example security or cost containment), then ONE of the following should be true:
nested_spawn: enabled, defaulting to current restricted behavior but allowing authors to declare hierarchical-orchestrator intent.Of these, option 1 (just expose the primitive) is preferred because the existing agent-definition frontmatter already declares the contract. Option 2 is acceptable if there is a real reason to default-deny. Option 3 alone is insufficient because it leaves the orchestrator pattern unimplementable.
Error Messages/Logs
Steps to Reproduce
Minimal reproduction in any Claude Code workspace.
Step 1. Create a parent orchestrator agent definition at
.claude/agents/repro-parent.md:Repro Parent
When invoked, attempt to spawn a child sub-agent named
repro-childvia theAgenttool. Report whether the spawn primitive was available in your tool surface, and what tools you observed (specifically: wasTaskorAgentpresent, or onlyTeamCreate/SendMessage?). Do not actually do any real work.Step 2. Create a child agent definition at
.claude/agents/repro-child.md:Repro Child
Return the string "child reached" and exit. No file operations needed.
Step 3. From a top-level Claude Code session, invoke the parent orchestrator:
Agent(subagent_type="repro-parent", prompt="Attempt to spawn repro-child via Agent. Report tool surface inventory.")
Step 4. Observe the parent agent's response.
Expected: the parent successfully spawns the child, the child returns "child reached", and the parent reports
Task/Agentwas available in its tool surface.Actual: the parent reports that
TaskandAgentare absent from its tool surface; onlyTeamCreate,SendMessage,TeamDelete,TaskOutput,TaskStop(plus standard non-orchestration tools) are present. The child is never spawned.Step 5. To confirm this is a nested-context restriction and not a global one, run from the same top-level session:
Agent(subagent_type="repro-child", prompt="say hello")
Expected and actual: this works fine. The child returns "child reached". The
Agentprimitive is available at the top level. Only the nested context filters it.Notes:
tools: All toolsin frontmatter, which should grant access to every available tool including the orchestration primitive..claude/settings.jsonpermission rules or hook configurations affect this; the filtering is at the harness layer.Claude Model
Opus
Is this a regression?
No, this never worked
Last Working Version
No response
Claude Code Version
2.1.146
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Cursor
Additional Information
No response