Preflight Checklist
Problem Statement
The Core Issue
When hook scripts execute for events like PreToolUse, PostToolUse, Notification, SubagentStop, or PreCompact, there is no way to determine which agent (main or subagent) triggered the event. All events share the same session_id regardless of their origin, making it impossible to build reliable observability, debugging, or orchestration tooling for multi-agent workflows.
Why Existing Workarounds Fail
| Approach |
Why It Fails |
| Process/Environment differentiation |
Main agent and subagents run asynchronously in the same process. No PID, PPID, or environment variable distinguishes them. |
Parsing transcript_path JSONL |
Unreliable: (1) requires complex async file parsing, (2) transcript structure is undocumented and subject to change, (3) race conditions with concurrent subagents, (4) significant performance overhead. |
| Session-to-agent mapping |
Breaks immediately with parallel subagents—mapping gets overwritten and produces incorrect attribution (detailed in #7881). |
Using tool_use_id correlation |
Only works for PreToolUse↔PostToolUse pairs; doesn't help identify the originating agent for other events. |
Affected Events
The following hook events can be triggered by subagents but provide no agent identification:
| Event |
Can Fire from Subagent |
Agent Info Available |
PreToolUse |
✅ Yes |
❌ No |
PostToolUse |
✅ Yes |
❌ No |
PostToolUseFailure |
✅ Yes |
❌ No |
Notification |
✅ Yes |
❌ No |
SubagentStart |
N/A (announces subagent) |
⚠️ Partial* |
SubagentStop |
N/A (announces subagent) |
⚠️ Partial* |
PreCompact |
✅ Yes |
❌ No |
*SubagentStart and SubagentStop events exist but currently lack consistent agent identification fields in their payloads.
Proposed Solution
Design Principles
- Minimal Surface Area: Add only the essential fields needed for agent identification
- Consistency: Use the same field names across all affected events
- Backward Compatibility: New fields are additive; existing integrations continue to work
- Leverage Existing Data: Fields should mirror what's already available in
SubagentStart/SubagentStop internal handling
Specification
Add the following three fields to the stdin JSON payload only for events triggered by subagents:
interface SubagentContext {
/** Unique identifier for this subagent instance (e.g., "a1b2c3d4") */
agent_id: string;
/**
* Subagent type identifier from agent definition
* (e.g., "code-reviewer", "frontend-developer", "ui-designer")
*/
agent_type: string;
/**
* Path to this subagent's transcript file
* (e.g., "/home/user/.claude/projects/.../agent-{agent_id}.jsonl")
*/
agent_transcript_path: string;
}
For main agent events: These fields are omitted (not present in the payload). Only subagents require explicit identification—the main agent is implicitly identified by the absence of these fields.
Example Payloads
Main Agent Event (Unchanged)
For main agent events, no new fields are added. The absence of agent fields implicitly indicates the main agent:
{
"session_id": "abc-123",
"hook_event_name": "PostToolUse",
"tool_name": "Write",
"tool_input": { "file_path": "/app/component.tsx", "content": "..." },
"tool_response": { "success": true },
"transcript_path": "/home/user/.claude/projects/.../abc-123.jsonl"
}
Subagent Event (New Fields Added)
For subagent events, the three identification fields are included:
{
"session_id": "abc-123",
"hook_event_name": "PostToolUse",
"tool_name": "Write",
"tool_input": { "file_path": "/app/styles.css", "content": "..." },
"tool_response": { "success": true },
"transcript_path": "/home/user/.claude/projects/.../abc-123.jsonl",
"agent_id": "f7e8d9c0",
"agent_type": "ui-designer",
"agent_transcript_path": "/home/user/.claude/projects/.../agent-f7e8d9c0.jsonl"
}
Detection Logic in Hook Scripts
# Simple check: presence of agent_id indicates subagent
is_subagent = "agent_id" in event
This design avoids redundant fields for main agent events—only subagents require explicit identification.
Why NOT Include Parent References
Some related proposals suggest adding parent_agent_id or hierarchical fields. I recommend against this for the initial implementation:
- Flat Architecture: Claude Code's subagents operate in parallel within the same process, not in a true parent-child hierarchy. All subagents share the same session.
- Unnecessary Complexity: For observability and routing purposes, knowing the
agent_id and agent_type is sufficient. Parent relationships can be inferred from session scope if needed.
- Scope Creep Risk: Hierarchical fields imply nested subagents, which isn't the current execution model and could create confusion.
The session_id already serves as the "parent" concept—all agents within a session share it.
Priority
High — This limitation blocks fundamental observability requirements for multi-agent workflows, which are increasingly common as users adopt custom subagents for specialized tasks.
Feature Category
Other
Use Cases Enabled
1. Agent-Specific Logging & Metrics
#!/usr/bin/env python3
import json, sys
event = json.load(sys.stdin)
tool_name = event.get("tool_name", "unknown")
# Determine agent type
if "agent_id" in event:
agent_type = event["agent_type"]
else:
agent_type = "main"
# Route metrics to agent-specific dashboards
send_metric(f"agent.{agent_type}.tool.{tool_name}.count", 1)
send_metric(f"agent.{agent_type}.tool.{tool_name}.latency", event.get("duration_ms", 0))
2. Agent-Specific Tool Policies
#!/usr/bin/env python3
import json, sys
event = json.load(sys.stdin)
# Only allow Write tool for specific agents
if event.get("tool_name") == "Write":
# Main agent is always allowed
if "agent_id" in event:
allowed_subagents = ["frontend-developer", "backend-developer"]
if event["agent_type"] not in allowed_subagents:
print(f"Subagent '{event['agent_type']}' is not authorized to write files", file=sys.stderr)
sys.exit(2) # Block the tool call
3. Real-Time Multi-Agent Dashboards
#!/usr/bin/env python3
import json, sys
from datetime import datetime
event = json.load(sys.stdin)
is_subagent = "agent_id" in event
# Emit structured event for real-time visualization
dashboard_event = {
"timestamp": datetime.now().isoformat(),
"session_id": event["session_id"],
"agent_id": event.get("agent_id"), # None for main agent
"agent_type": event["agent_type"] if is_subagent else None,
"event_type": event["hook_event_name"],
"tool": event.get("tool_name"),
"is_subagent": is_subagent,
}
websocket_broadcast(dashboard_event)
4. Differential Compaction Handling
#!/usr/bin/env python3
import json, sys
event = json.load(sys.stdin)
if event["hook_event_name"] == "PreCompact":
# Check if this is a subagent compaction
if "agent_id" in event:
# Backup subagent transcript separately
backup_transcript(
event["agent_transcript_path"],
f"subagent-{event['agent_type']}-backup.jsonl"
)
else:
# Main agent compaction - use standard backup
backup_transcript(event["transcript_path"], "main-backup.jsonl")
Relationship to Existing Issues
| Issue |
Focus |
How This Proposal Differs |
| #7881 |
SubagentStop identification |
This proposal provides a unified solution across all hook events, not just SubagentStop |
| #14859 |
Agent hierarchy + new hooks |
This proposal is minimal and focused—no new hook types, no hierarchical fields, just essential identification |
This proposal can be seen as a foundational step that enables the broader observability features discussed in those issues without requiring architectural changes.
Implementation Considerations
Minimal Code Changes Expected
The agent_id, agent_type, and transcript path are already tracked internally for SubagentStart/SubagentStop processing. This proposal simply requests exposing these existing values in other hook event payloads.
Backward Compatibility
- New fields are additive only
- Existing hook scripts that don't use these fields continue to work unchanged
- No changes to exit code semantics or JSON output schemas
Documentation Updates Needed
- Update Hooks Reference with new fields in the "Hook Input" section
- Add examples showing agent-aware hook implementations
Summary
| What |
Details |
| Request |
Add agent_id, agent_type, and agent_transcript_path to hook event payloads for subagent-triggered events only |
| Scope |
PreToolUse, PostToolUse, PostToolUseFailure, Notification, SubagentStop, PreCompact |
| Main Agent Events |
Unchanged (no new fields) — absence of fields indicates main agent |
| Benefit |
Enables reliable agent identification for observability, policy enforcement, and debugging |
| Complexity |
Low — leverages existing internal agent tracking |
| Breaking Changes |
None — purely additive |
Thank you for considering this proposal. I'm happy to provide additional technical details, test scenarios, or implementation suggestions if helpful.
Preflight Checklist
Problem Statement
The Core Issue
When hook scripts execute for events like
PreToolUse,PostToolUse,Notification,SubagentStop, orPreCompact, there is no way to determine which agent (main or subagent) triggered the event. All events share the samesession_idregardless of their origin, making it impossible to build reliable observability, debugging, or orchestration tooling for multi-agent workflows.Why Existing Workarounds Fail
transcript_pathJSONLtool_use_idcorrelationPreToolUse↔PostToolUsepairs; doesn't help identify the originating agent for other events.Affected Events
The following hook events can be triggered by subagents but provide no agent identification:
PreToolUsePostToolUsePostToolUseFailureNotificationSubagentStartSubagentStopPreCompact*
SubagentStartandSubagentStopevents exist but currently lack consistent agent identification fields in their payloads.Proposed Solution
Design Principles
SubagentStart/SubagentStopinternal handlingSpecification
Add the following three fields to the stdin JSON payload only for events triggered by subagents:
For main agent events: These fields are omitted (not present in the payload). Only subagents require explicit identification—the main agent is implicitly identified by the absence of these fields.
Example Payloads
Main Agent Event (Unchanged)
For main agent events, no new fields are added. The absence of agent fields implicitly indicates the main agent:
{ "session_id": "abc-123", "hook_event_name": "PostToolUse", "tool_name": "Write", "tool_input": { "file_path": "/app/component.tsx", "content": "..." }, "tool_response": { "success": true }, "transcript_path": "/home/user/.claude/projects/.../abc-123.jsonl" }Subagent Event (New Fields Added)
For subagent events, the three identification fields are included:
{ "session_id": "abc-123", "hook_event_name": "PostToolUse", "tool_name": "Write", "tool_input": { "file_path": "/app/styles.css", "content": "..." }, "tool_response": { "success": true }, "transcript_path": "/home/user/.claude/projects/.../abc-123.jsonl", "agent_id": "f7e8d9c0", "agent_type": "ui-designer", "agent_transcript_path": "/home/user/.claude/projects/.../agent-f7e8d9c0.jsonl" }Detection Logic in Hook Scripts
This design avoids redundant fields for main agent events—only subagents require explicit identification.
Why NOT Include Parent References
Some related proposals suggest adding
parent_agent_idor hierarchical fields. I recommend against this for the initial implementation:agent_idandagent_typeis sufficient. Parent relationships can be inferred from session scope if needed.The
session_idalready serves as the "parent" concept—all agents within a session share it.Priority
High — This limitation blocks fundamental observability requirements for multi-agent workflows, which are increasingly common as users adopt custom subagents for specialized tasks.
Feature Category
Other
Use Cases Enabled
1. Agent-Specific Logging & Metrics
2. Agent-Specific Tool Policies
3. Real-Time Multi-Agent Dashboards
4. Differential Compaction Handling
Relationship to Existing Issues
This proposal can be seen as a foundational step that enables the broader observability features discussed in those issues without requiring architectural changes.
Implementation Considerations
Minimal Code Changes Expected
The
agent_id,agent_type, and transcript path are already tracked internally forSubagentStart/SubagentStopprocessing. This proposal simply requests exposing these existing values in other hook event payloads.Backward Compatibility
Documentation Updates Needed
Summary
agent_id,agent_type, andagent_transcript_pathto hook event payloads for subagent-triggered events onlyPreToolUse,PostToolUse,PostToolUseFailure,Notification,SubagentStop,PreCompactThank you for considering this proposal. I'm happy to provide additional technical details, test scenarios, or implementation suggestions if helpful.