PermissionRequest hooks not triggered for subagent permission requests in Agent Teams

Status Open
Maintainer reply None cached
Activity 11 comments · opened Feb 7, 2026

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

  1. Configure a PermissionRequest hook in ~/.claude/settings.json:

``json
{
"hooks": {
"PermissionRequest": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "bash ~/.claude/hooks/my_custom_hook.sh",
"timeout": 600
}
]
}
]
}
}
``

  1. Start a Claude Code session and spawn a multi-agent team using TeamCreate and Task tool with subagents.
  1. 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.
  1. The PermissionRequest hook 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.

View original on GitHub ↗

10 Comments

ThomasHoussin · 6 months ago

Same issue ; I have a permissionRequest hook whick works with agents and is never fired in teams :

		"PermissionRequest": [
			{
				"matcher": "^(?!ExitPlanMode$|AskUserQuestion$).*",
				"hooks": [
					{
						"type": "command",
						"command": "node .claude/hooks/permission-check.mjs"
					}
				]
			}
		]
recoworks · 6 months ago

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.

isnifer · 5 months ago

Same here, agent-teams running in tmux with --dangerously-skip-permissions do not have this issue. Outside of tmux — problem exists even with --dangerously-skip-permissions.

welkinbai · 5 months ago

I also encountered the same problem, I have the same requirement, please resolve it with priority

cballou · 5 months ago

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.json
  • PermissionRequest hook configured with debug logging (writes to /tmp/hook-auto-approve-debug.log on every invocation)
  • Hook script: bash ~/.claude/scripts/team-auto-approve.sh

Findings

  1. Hook fires for the lead's process — debug log entries appear for the lead's own tool calls
  2. Hook NEVER fires for tmux agent processes — zero debug log entries from any spawned teammate, even after multiple tool calls (Write, Read, Bash, Glob, Grep, Edit)
  3. Settings.json deny rules DO work for tmux agents (blocking sudo, rm -rf, Write(~/.ssh/**), etc.)
  4. Settings.json allow rules DO work for tmux agents (auto-approving matched patterns)
  5. The hook only comes into play for tool calls that don't match any allow/deny rule — but for tmux agents, unmatched calls just prompt the user directly, bypassing the hook entirely

Impact

This means PermissionRequest hooks cannot be used for:

  • Auto-approving team agent tool calls programmatically
  • Enforcing dynamic deny rules beyond static glob patterns (e.g., "deny writes to settings.json" required adding static deny entries as a workaround)
  • Logging/auditing team agent permission decisions
  • Sending notifications for team agent permission requests

Workaround

Rely entirely on static permissions.allow and permissions.deny rules in settings.json for tmux agent permission control. The hook is only useful as defense-in-depth for the lead's own session.

himanshuseth · 4 months ago

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.

weiesky · 4 months ago

+1

ThatDragonOverThere · 4 months ago

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.

dyresen · 3 months ago

Still broken in 2.1.142

yasyf · 1 month ago

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.requestDialog is present. The gate is literally:

if (s.requestDialog !== void 0) {
  // …runs the PermissionRequest hook pipeline, then shows/queues the dialog…
}
// else: forward to the lead via the team mailbox — no hook pipeline runs here

When requestDialog is absent, the request is forwarded to the lead through the team mailbox and the lead renders it as a plain dialog (queueBehind: true). No PermissionRequest hooks 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.

requestDialog is a live TTY-bound callback, so it's absent for headless/-p leads 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 has requestDialog, the detached/resumed case doesn't.

This is also distinct from a payload problem: agent_id is populated when a context id exists; on the forward path there's simply no hook dispatch to carry it. (tool_use_id also isn't part of the PermissionRequest hook schema, so a hook can't recover attribution there even when it does run.)

Workaround that actually works

Answer at PreToolUse instead of (or in addition to) PermissionRequest. A PreToolUse hook returning an allow permission 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). A PermissionRequest-only hook can't help, because on the forwarded path Claude never emits the event.

Minimal shape:

{
  "hooks": {
    "PreToolUse": [
      { "matcher": "Bash", "hooks": [ { "type": "command", "command": "your-approver" } ] }
    ]
  }
}

…where your-approver emits {"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) — a PreToolUse allow pre-authorizes the tool, so an unconditioned one is equivalent to skipping permissions entirely.

Suggested upstream fix

Run the same PermissionRequest hook pipeline in the teammate mailbox branch — using the teammate's own ToolUseContext — before forwarding to the lead. Dispatching from the lead's inbox poller instead would mean reconstructing that context and risks losing the real agent_id.

---

(Disclosure: I maintain capt-hook, a declarative Claude-Code hook framework — it ships exactly this PreToolUse approver as a builtin fixes pack, 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.)

Showing cached comments. Read the full discussion on GitHub ↗