PermissionRequest hooks: subagent prompts don't invoke the hook; when it did fire, a returned allow was ignored
Environment
- claude-code 2.1.191 (Linux x86_64, Arch package;
DISABLE_AUTOUPDATER=1) - Hook registered via a plugin's hooks.json under
PermissionRequest(matcher covers Read); the same plugin registers a PreToolUse hook, which is how we can prove plumbing liveness below. - Settings context: no allow/deny/ask permission rules for Read configured, so the documented tighten-only caveats have nothing to bite on.
Documented behavior (docs.claude.com/claude-code hooks reference, fetched 2026-07-17)
- PermissionRequest: "Returning
allowskips the interactive prompt but doesn't override permission rules." - "Permission requests generated by subagent tool calls fire
PermissionRequesthooks…" (payload documented to carryagent_id/agent_type).
We observed two distinct failure modes, both contradicting the above.
Mode A — hook fires, returned allow is ignored (observed 2026-07-17 ~05:24Z)
A subagent's Read of a world-readable file outside the workspace triggered the built-in out-of-directory permission flow. Our PermissionRequest hook was invoked (payload carried tool_name: Read, the file path, and the subagent identity) and answered within ~1 ms:
{"decision": {"behavior": "allow", "updatedInput": {"file_path": "…"}}}
The interactive prompt was shown to the human anyway. We initially suspected our output shape (top-level decision vs the documented hookSpecificOutput envelope) and fixed it to emit the documented envelope — which brings us to mode B, because we could never verify the envelope fix:
Mode B — the hook is not invoked at all for a subagent's prompt (observed 2026-07-17 ~13:42Z)
A subagent Read of a never-before-approved world-readable path (/etc/os-release) produced the interactive prompt, and our PermissionRequest hook was never invoked — while our PreToolUse hook for the same tool call fired 5 ms earlier (both hooks in the same plugin, same daemon socket — plumbing demonstrably alive). Our hook-side event log records the PreToolUse dispatch and zero PermissionRequest dispatches for that session.
This directly contradicts documented subagent coverage (quote 2). Whether A-vs-B selection is version drift or depends on subagent type / permission mode (we saw A with a ticket-worker-type agent under acceptEdits, B with an Explore-type under default) we cannot determine from outside.
Workaround that works (for triagers' reference)
A PreToolUse hook returning hookSpecificOutput.permissionDecision: "allow" suppresses the out-of-directory prompt for both main-agent and subagent Reads on this build (live-verified at the keyboard, zero prompts). We have moved our read policy to that seat.
Questions
- Is PermissionRequest expected to fire for subagent tool-call prompts on current builds?
- When it does fire and the hook returns a documented allow (enveloped), is that expected to suppress the built-in out-of-directory ask when no permission rules are configured?
Happy to provide the full timestamped hook-event log for both modes.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗