Anthropic announced nested subagent support (depth=5) on 2026-06-09; the runtime currently strips Task at parent->child spawn (upstream denylist, empirically confirmed by our committed probe: level=1 status=NO_AGENT_TOOL, matching ruflo ADR-147). This lands the readiness infrastructure that is independently useful today and activates with zero changes when the gate lifts: - aqe hooks post-task gains --parent-agent-id / --depth (validated: identifier charset, integer 0 <= d <= 32; depth=0 survives as 0); provenance persisted to qe_trajectories.metadata_json (stage 1 — no schema migration) and forwarded into ReasoningBank feedback so learning can segment patterns per hierarchy level - TaskExecution gains optional parentAgentId/depth (additive types) - scripts/probe-nested-spawn-depth.mjs: single-shot empirical probe, committed transcript under docs/probes/ — re-run after every `claude update`; TASK_TOOL_LIVE is the signal for follow-up phases - fresh-project fix found by the E2E: persistTaskOutcome assumed captured_experiences/experience_applications exist, but they are middleware-created — Stream B silently no-oped on fresh installs; canonical DDL now ensured in the hook path Deliberately deferred (documented in ADR-101 P1): tools: frontmatter retrofit on shipped qe-*.md agents — Claude Code frontmatter is a restrictive allowlist and would sever inherited MCP tool access; needs maintainer sign-off + wildcard verification first. 8 unit tests green; E2E on a fresh temp project verified persistence, rejections, and depth=0 boundary. tsc + eslint clean. Part of #520 (improvement 4/7, Tier 2). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
7.1 KiB
ADR-101: Nested Subagent Hierarchy — Depth Limits, Privilege Model, Trajectory Provenance
| Field | Value |
|---|---|
| Decision ID | ADR-101 |
| Status | Implemented (P2 stage 1) / Proposed (P1 frontmatter — pending maintainer confirmation) |
| Date | 2026-06-10 |
| Author | AQE Core (Fable 5 improvement initiative, issue #520) |
| Review Cadence | After every claude update (re-run the probe) |
WH(Y) Decision Statement
In the context of the AQE fleet's agent hierarchy (queen → fleet-commander → domain specialists), which today flattens all delegation into depth-1 Task-tool fan-out,
facing Anthropic's 2026-06-09 announcement of nested subagent support (depth=5), where empirical probing shows the runtime plumbing exists but the Task tool is stripped at parent→child spawn time by an upstream denylist,
we decided for building the readiness infrastructure now — nesting provenance (parentAgentId, depth) through trajectory recording and the post-task hook, a committed empirical probe script as the regression test for the gate lifting, and validation bounds (identifier check, 0 ≤ depth ≤ 32),
and neglected waiting for the upstream rollout (loses the independently-useful provenance for today's flat spawns) and immediately retrofitting tools: frontmatter onto all shipped qe-*.md agents (a restrictive allowlist that would cut agents off from inherited MCP tools — deferred pending maintainer confirmation, see P1 below),
to achieve zero-code-change activation when Anthropic flips the gate, plus per-hierarchy-level pattern segmentation in ReasoningBank starting today,
accepting that provenance lands in the JSON metadata blob rather than dedicated columns (stage 1 — no schema migration) and that the privilege split between coordinator and leaf agents is documented but not yet enforced in frontmatter.
Context
ruflo's ADR-147 (PR #2336) probed Claude CLI 2.1.169 and found: parentAgentId/isSubagent plumbing exists in the binary; YAML tools: declarations propagate to children; the runtime strips Task at parent→child spawn regardless of flags — a hardcoded or server-side denylist. Our own probe (committed at docs/probes/probe-nested-spawn-2026-06-10.txt) reproduces this against this project's runtime: level=0 task_tool=yes, level=1 task_tool=no → NO_AGENT_TOOL.
The provenance fields are useful before the gate lifts: Claude Code's flat spawns still have a parent (the main loop or the queen), and segmenting learned patterns by hierarchy level improves routing priors (ADR-095/096 read the same outcome rows).
Phases
| Phase | Content | Status |
|---|---|---|
| P1 | tools: frontmatter with coordinator/leaf privilege split across qe-*.md (+ assets/agents/v3/ mirror) |
Proposed — blocked on maintainer confirmation. Claude Code's tools: frontmatter is a restrictive allowlist: declaring it cuts the agent off from inherited tools, including all mcp__agentic-qe__* tools unless each is enumerated (wildcard support in agent frontmatter is unverified). Retrofitting ~50 shipped agents risks breaking the fleet for users — production-safety rule requires explicit sign-off and an MCP-wildcard test first. |
| P2 stage 1 | --parent-agent-id / --depth on post-task; validation; persisted to qe_trajectories.metadata_json; forwarded into ReasoningBank feedback; TaskExecution.parentAgentId/depth types |
Implemented (this ADR) |
| P2 stage 2 | Dedicated columns + indexes for provenance | Deferred until query patterns demand it |
| P3 | Depth-aware pre-task guardrail (NESTING_DEPTH_EXCEEDED) |
Blocked on P2 stage 2 |
| P4 | Queen-coordinator delegation rewrite for real nesting | Blocked on the upstream gate lifting (probe flips to TASK_TOOL_LIVE) |
Options Considered
Option 1: Provenance-first readiness, frontmatter deferred (Selected)
Pros: all shipped behavior unchanged; provenance independently useful today; probe tells us exactly when to do more Cons: least-privilege boundary not yet enforced
Option 2: Full ruflo-style P1 now (restrictive tools: lists on all agents) (Rejected for now)
Why rejected: ruflo declared tools: on 8 new agents; retrofitting AQE's ~50 shipped agents changes their effective toolset (MCP access loss risk) without a way to test nested behavior until the denylist lifts. Revisit with maintainer sign-off + an MCP-wildcard frontmatter test.
Option 3: Wait for upstream rollout (Rejected)
Why rejected: loses today's provenance value and the regression signal; ruflo's "independently useful" argument applies verbatim.
Dependencies
| Relationship | ADR ID | Title | Notes |
|---|---|---|---|
| Relates To | ADR-095/096 | Routing exploration / Route-Q loop | Consume the same outcome rows provenance now annotates |
| Relates To | ADR-064 | Agentic Teams | Queen hierarchy whose delegation P4 will rewrite |
| Relates To | ADR-099 | Reasoning-tag scrub | Same trajectory pipeline |
| Part Of | — | Fable 5 / ruflo-parity initiative | Tracking issue #520, improvement 4 |
References
| Ref ID | Title | Type | Location |
|---|---|---|---|
| — | Provenance validation | Source | src/cli/commands/hooks-handlers/nesting-provenance.ts |
| — | Hook + persistence wiring | Source | task-hooks.ts, hooks-dream-learning.ts (metadata_json) |
| — | Type extension | Source | src/coordination/queen-types.ts (TaskExecution) |
| — | Probe script | Source | scripts/probe-nested-spawn-depth.mjs |
| — | Probe result (2026-06-10) | Evidence | docs/probes/probe-nested-spawn-2026-06-10.txt — level=1 status=NO_AGENT_TOOL |
| — | Tests (8) | Tests | tests/unit/cli/hooks/nesting-provenance.test.ts |
| — | ruflo prior art | External | ruvnet/ruflo PR #2336 (ADR-147) |
Governance
| Review Board | Date | Outcome | Next Review |
|---|---|---|---|
| AQE Core | 2026-06-10 | P2 stage 1 Implemented; P1 awaiting maintainer call | Re-run probe after every claude update |
Status History
| Status | Date | Notes |
|---|---|---|
| Proposed | 2026-06-10 | From Fable 5 improvement plan (issue #520) |
| Implemented (P2 stage 1) | 2026-06-10 | Provenance flags + validation + metadata_json persistence + probe + 8 tests. Drive-by fix: fresh-project captured_experiences/experience_applications DDL in persistTaskOutcome (Stream B silently no-oped on fresh installs). |
Definition of Done Checklist
- Evidence: probe committed (
NO_AGENT_TOOL— denylist active, matching ruflo); E2E persistence of{"parentAgentId":"qe-fleet-commander","depth":2}and{"depth":0}on a fresh temp project; rejection of invalid id / negative / non-integer / >32 depth - Criteria: 3 options compared; validation bounds match ruflo's suite (0 ≤ d ≤ 32)
- Agreement: P1 frontmatter awaits maintainer confirmation (MCP allowlist risk)
- Documentation: this ADR; fail-open exit semantics documented (hooks never break the tool pipeline — rejection = printed error + no persistence, exit 0)
- Review: verification record on issue #520