PreToolUse hooks don't fire for subagents (Agent tool)

Status Closed — not planned
Maintainer reply None cached
Activity 6 comments · opened Jun 18, 2026 · closed Aug 22, 2026

Summary

PreToolUse hooks defined in ~/.claude/settings.json fire correctly for the main agent but are silently skipped for all subagents spawned via the Agent tool. This means any hook-based command rewriting, safety checks, or instrumentation only covers a fraction of actual tool calls in multi-agent workflows.

Impact

In a Conductor environment running parallel agents, 72% of sessions are subagents. With rtk installed as a PreToolUse hook to filter/compress Bash output (saving ~40% tokens on grep, find, git, gh commands), the main agent gets the optimization but every subagent runs raw commands — wasting tokens on unfiltered output.

Measured gap (30-day window):

  • Main sessions: ~11K commands went through the hook → tokens saved
  • Subagent sessions: ~7K commands bypassed the hook entirely → full token cost
  • Estimated waste: ~3M tokens/month from subagent commands that would have been filtered

Reproduction

  1. Add a PreToolUse hook to ~/.claude/settings.json:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/my-hook.sh"
          }
        ]
      }
    ]
  }
}
  1. In a session, run a Bash command directly — hook fires ✅
  2. Spawn a subagent via the Agent tool that runs Bash commands — hook does NOT fire ❌

Evidence from session transcripts:

Main session transcript shows hook invocations interleaved with Bash commands:

"command":"/Users/.../.claude/hooks/rtk-rewrite.sh"
"command":"grep -rn ..."
"command":"/Users/.../.claude/hooks/rtk-rewrite.sh"
"command":"find ..."

Subagent transcript shows raw Bash commands with zero hook invocations:

"command":"grep -r ..."
"command":"find ..."
"command":"grep -n ..."

Expected behavior

All hooks (PreToolUse, PostToolUse, etc.) should propagate to subagents spawned by the Agent tool, inheriting from the same settings hierarchy (user → project → local) as the main agent.

Environment

  • Claude Code version: latest (via Conductor)
  • rtk version: 0.30.0
  • OS: macOS (Darwin 25.5.0)
  • Hook location: ~/.claude/settings.json (user-level)

View original on GitHub ↗

4 Comments

kcarriedo · 2 months ago

The 72% subagent coverage gap you've documented here is a concrete argument for why hook propagation can't be optional. When subagents handle the majority of actual tool calls, any hook that only runs on the main session is effectively a partial safety net.

Two clarifying questions that might help Anthropic scope the fix:

  1. Do hooks fail to propagate because subagents launch with a clean settings context (no inheritance from the spawning session's resolved settings), or do they inherit settings but skip hook execution for some tool call types? The distinction matters for the fix: the first is a spawn-time config wiring issue, the second is a per-tool-call evaluation issue.
  1. When a subagent is spawned with an explicit subagent_type (e.g., "code-writer" vs "general-purpose"), does the hook behavior change? If typed subagents have a different settings resolution path, that could narrow the root cause.

The token waste number (3M tokens/month from unfiltered subagent commands) is useful framing. Safety-blocking hooks are the more critical argument though: a PreToolUse hook that prevents destructive Bash commands from running is meaningless if 72% of Bash calls in a multi-agent session bypass it entirely.

Worth noting: the companion issue #69283 (context inheritance for subagents) has a similar structure. Both issues share the pattern that multi-agent workflows silently drop properties the user configured at the top-level session -- hooks in this case, CLAUDE.md rules in #69283. They're separate fix surfaces but the same architectural gap: subagents don't inherit the parent session's configured environment.

ishita-0301 · 2 months ago

This seems like an important gap to close. If subagents don't inherit the same hook chain as the parent, then any guarantees around safety, logging, or command rewriting become inconsistent. In practice, the most autonomous workflows are often the ones that spawn the most subagents.

I ran into a similar idea while looking at https://github.com/FailproofAI/failproofai. Features like loop detection, execution policies, or preventing premature completion only work if every agent in the hierarchy is subject to the same runtime controls. Otherwise the weakest link ends up being the subagent that bypasses them.

Necmttn · 2 months ago

Coverage should be observable, not only fixed once.

Alongside propagating hooks, stamp each tool call or hook payload with a resolved settings hash or hook_chain_id, and record hook_evaluated: true|false plus a skip reason when false.

That lets users tell the difference between subagents inheriting no settings, hooks being skipped for a tool call, and settings loading correctly but no matcher firing. Without that receipt, this can regress silently back into partial coverage.

---

_Generated with ax._

B1tMaster · 1 month ago

This been raised again and again and never fixed. ! this is a no go for any real corporate use where audit trail and tokenomics are important. Please fix it.

Showing cached comments. Read the full discussion on GitHub ↗