PermissionRequest hooks not triggered for subagent permission requests in Agent Teams
Bug Description
When using Claude Code's Agent Teams (multi-agent system with Task tool and TeamCreate), permission requests from subagents do not trigger PermissionRequest hooks. Instead, they fall back to standard terminal prompts in the parent session.
This means any custom hook configured for PermissionRequest (e.g., sending notifications to Telegram, Slack, or any external service) is completely bypassed when subagents need permission.
Steps to Reproduce
- Configure a
PermissionRequesthook in~/.claude/settings.json:
``json``
{
"hooks": {
"PermissionRequest": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "bash ~/.claude/hooks/my_custom_hook.sh",
"timeout": 600
}
]
}
]
}
}
- Start a Claude Code session and spawn a multi-agent team using
TeamCreateandTasktool with subagents.
- When a subagent needs permission to run a command (e.g.,
curl,export ... && curl ...), the permission request appears as a standard terminal dialog ("Do you want to proceed? [y/n]") in the parent session.
- The
PermissionRequesthook is never called for the subagent's request.
Expected Behavior
PermissionRequest hooks should fire for all permission requests, including those delegated from subagents to the parent session. The hook should intercept the request before it reaches the terminal UI, regardless of whether it originates from the main session or a subagent.
Actual Behavior
- Main session permission requests → Hook fires correctly ✅
- Subagent permission requests → Hook is bypassed, terminal prompt shown ❌
Impact
This limitation breaks the use case of remote permission management. Users who set up hooks to approve/deny permissions from external services (phone notifications, Slack, Telegram, etc.) are forced back to the terminal when using Agent Teams — defeating the purpose of the hook.
With Agent Teams being a new and powerful feature, many users will want to use it alongside custom permission hooks. The current behavior makes these two features incompatible.
Workaround
Pre-approve common subagent commands in settings.json permissions so they don't need to ask:
{
"permissions": {
"allow": [
"Bash(export:*)",
"Bash(source:*)",
"Bash(curl:*)"
]
}
}
This lets subagents work autonomously but removes the ability to review their actions, which is not ideal for security-conscious users.
Environment
- Claude Code version: Latest (2026-02-07)
- OS: Linux (WSL2 on Windows)
- Hook event:
PermissionRequest
Related
We documented this limitation in our open-source project claude-telegram-hook, which sends permission requests to Telegram with inline buttons. The hook works perfectly for the main session but is completely bypassed by subagents.
Showing cached comments. Read the full discussion on GitHub ↗
10 Comments
Same issue ; I have a permissionRequest hook whick works with agents and is never fired in teams :
Same issue here. Whenever I or Claude Code spawn a multi-agent team in a Claude Code session, I constantly get prompted by the agents for actions that the main Claude Code session does have permission to do which is annoying and defeats the purpose of using agents since I have to babysit them.
Same here, agent-teams running in tmux with
--dangerously-skip-permissionsdo not have this issue. Outside of tmux — problem exists even with--dangerously-skip-permissions.I also encountered the same problem, I have the same requirement, please resolve it with priority
Additional evidence: macOS + tmux teammate mode (v2.1.77)
Confirming this also affects tmux teammate mode on macOS. Here's what we found through systematic testing:
Setup
teammateMode: "tmux"in settings.jsonPermissionRequesthook configured with debug logging (writes to/tmp/hook-auto-approve-debug.logon every invocation)bash ~/.claude/scripts/team-auto-approve.shFindings
sudo,rm -rf,Write(~/.ssh/**), etc.)Impact
This means
PermissionRequesthooks cannot be used for:Workaround
Rely entirely on static
permissions.allowandpermissions.denyrules in settings.json for tmux agent permission control. The hook is only useful as defense-in-depth for the lead's own session.This is a prerequisite for background subagent permission escalation (see #47339). Without hooks firing for subagent permission requests, there's no way to intercept and route unapproved tool calls. This blocks any orchestration pattern that dispatches parallel background agents.
+1
Still broken in v2.1.116. Part of the compound failure on 2026-04-21 where an overnight multi-agent run burned 20% monthly API utilization producing nothing — permission hooks not firing means the programmatic workaround path doesn't exist either.
Still broken in 2.1.142
Root cause + a working workaround, from disassembling the 2.1.207 bundle.
Why it happens
An in-process teammate resolves its own permission dialog only when its
ToolUseContext.requestDialogis present. The gate is literally:When
requestDialogis absent, the request is forwarded to the lead through the team mailbox and the lead renders it as a plain dialog (queueBehind: true). NoPermissionRequesthooks run in either process on that path — the teammate's hooks are process-local and never reached, and the lead builds no hook input at all. That's why the dialog falls back to the terminal prompt and your hook never fires.requestDialogis a live TTY-bound callback, so it's absent for headless/-pleads and for resumed/rehydrated teammate contexts. That matches what several people here saw — e.g. it working under tmux but not outside it, even with--dangerously-skip-permissions: the TTY-attached case hasrequestDialog, the detached/resumed case doesn't.This is also distinct from a payload problem:
agent_idis populated when a context id exists; on the forward path there's simply no hook dispatch to carry it. (tool_use_idalso isn't part of thePermissionRequesthook schema, so a hook can't recover attribution there even when it does run.)Workaround that actually works
Answer at
PreToolUseinstead of (or in addition to)PermissionRequest. APreToolUsehook returning anallowpermission decision resolves upstream of the dialog-forward fork, so it takes effect on every path — fresh, headless, and resumed — and it also clears prompts the dialog stage would otherwise force (e.g. the "Multiple directory changes in one command require approval for clarity" ask). APermissionRequest-only hook can't help, because on the forwarded path Claude never emits the event.Minimal shape:
…where
your-approveremits{"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "allow"}}for the calls you want to auto-approve. Scope it tightly (tool, command shape, subagent-origin, and whatever consent signal you rely on) — aPreToolUseallow pre-authorizes the tool, so an unconditioned one is equivalent to skipping permissions entirely.Suggested upstream fix
Run the same
PermissionRequesthook pipeline in the teammate mailbox branch — using the teammate's ownToolUseContext— before forwarding to the lead. Dispatching from the lead's inbox poller instead would mean reconstructing that context and risks losing the realagent_id.---
(Disclosure: I maintain capt-hook, a declarative Claude-Code hook framework — it ships exactly this
PreToolUseapprover as a builtinfixespack, so you can get the workaround without hand-rolling the approver. The mechanism above is the point, though; it works fine with a plain shell hook.)