PreToolUse hook payload carries no caller identity, so per-actor guardrails cannot be written

Status Open
Reported on v2.1.222
Maintainer reply None cached
Activity 1 comment · opened Aug 7, 2026

Environment

  • Claude Code 2.1.222
  • macOS 26.5.2, Node v26.5.0
  • Project with .claude/agents/*.md subagents and .claude/settings.json hooks

What I was trying to do

Enforce a project rule mechanically instead of by prose: the main agent must not edit source files; it delegates that to a subagent role. The natural implementation is a PreToolUse hook on Edit|Write|NotebookEdit that denies when the caller is the main agent and allows when the caller is a subagent.

What happens

The hook input JSON has no field identifying which agent issued the tool call. Logging the payload keys of every Edit/Write gives exactly:

{"tool":"Write","session":"2e28371b-5034-4ea1-9aec-9d0ad169afef","path":"/…/.claude/settings.json","keys":["session_id","tool_input","tool_name"]}

session_id, tool_input, tool_name — nothing about the actor. A path-based deny therefore blocks the subagents too, which are exactly the actors that are supposed to be allowed to edit those paths. The guardrail cannot be written at all.

Reproduce

  1. Add to .claude/settings.json:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write|NotebookEdit",
        "hooks": [
          {
            "type": "command",
            "command": "jq -c '{tool: .tool_name, session: .session_id, keys: keys}' >> /tmp/payload.jsonl"
          }
        ]
      }
    ]
  }
}
  1. Have the main agent edit a file, then have a subagent edit a file.
  2. cat /tmp/payload.jsonl — no field distinguishes the two.

Expected

Something in the payload that identifies the caller — e.g. agent_type ("main" / the subagent's name), or a documented guarantee that a subagent's session_id differs from the main session's so the hook can compare against a known value.

Impact

This is the central use case for hooks in a multi-agent setup: different actors have different privileges, and prose in a charter is not enforcement. Without caller identity, every hook must treat all actors as one, so a project can only write rules that apply to everyone or to no one.

Honest limitation of my evidence

I only captured payloads from main-agent edits. I did not confirm whether subagent tool calls fire PreToolUse hooks at all, or what session_id they carry if they do. If subagent calls simply do not fire hooks, that is itself worth documenting, because it changes what a hook can be relied on to cover.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗