Agent frontmatter hooks silently fail for team-spawned subagents (session ID mismatch)
Description
Hooks defined in .claude/agents/*.md YAML frontmatter never fire for agents spawned via the team/agent system (TeamCreate + Task with subagent_type). The hooks are registered but never matched at dispatch time due to a session ID mismatch.
Reproduction
- Create
.claude/agents/worker.md:
---
name: worker
description: Test agent
hooks:
PreToolUse:
- matcher: "Read"
hooks:
- type: command
command: "touch /tmp/hook-fired.txt"
---
Worker agent instructions here.
- Create a team and spawn the agent:
TeamCreate → Task with subagent_type: "worker"
- The agent uses
Read(and other tools) — but/tmp/hook-fired.txtis never created.
- Meanwhile, hooks in
.claude/settings.jsonwith the same matchers DO fire for all agents.
Root cause (from source analysis)
Binary analyzed: Claude Code 2.1.50 (ELF/Bun SEA)
Registration (when agent spawns):
// In agent spawn code:
if (H.hooks) UaD(A.setAppState, C, H.hooks, `agent '${H.agentType}'`, true);
Hooks are stored in appState.sessionHooks[C] where C is the session ID at spawn time.
Dispatch (when agent calls a tool):
// In VR (hook dispatch):
let U = D?.agentId ?? v$();
let J = hmA(G, U, E, H);
Lookup:
// In pS$ (session hook resolver):
function pS$(appState, sessionId) {
let sessionData = appState.sessionHooks[sessionId];
if (!sessionData) return new Map; // ← returns empty, hooks not found
...
}
The registration session ID (C) and the dispatch session ID (D?.agentId ?? v$()) don't match for team-spawned agents. The hooks are stored under one key but looked up under another, so pS$ returns an empty Map and hooks silently never fire.
Settings.json hooks are unaffected because they're resolved via a different path (TwH()) that doesn't use session IDs.
Environment
- Claude Code: 2.1.50
- Platform: Linux (Fedora 43, x86_64)
- Agent spawn method:
TeamCreate+Taskwith customsubagent_type
Impact
Agent-scoped hooks are completely non-functional for team workflows. This affects:
- Rule injection / compliance enforcement
- Agent-specific logging
- Any hook-based agent customization
The documentation states frontmatter hooks should work for project agents (and the registration code runs — Registered N frontmatter hook(s) is logged), but they are silently dropped at dispatch time.
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗