Context
PR #185 (danny-avila/sanitize-subagent-events) made subagent update events safe to publish and propagated the parent HookRegistry into child subagent graphs so child tool hooks fire. During review, nested HITL was deliberately left out of that PR because it needs a larger design than event sanitization.
Today, child subagent PreToolUse / PostToolUse hooks can run, but child PreToolUse hooks that return ask do not produce a resumable parent interrupt. The current behavior is intentionally fail-closed for safety: child graphs do not inherit humanInTheLoop, so subagent tool approvals do not enter a partially-supported checkpoint/resume flow.
Problem
A host should be able to register a parent-scoped tool policy hook and have it apply inside subagents, including approval flows. For example, a child subagent calculator/MCP/local-tool call should be able to trigger a human approval request, pause the parent run, resume cleanly after approval/denial, and preserve subagent event ordering without leaking sensitive runtime config.
This is more involved than the PR #185 patch because it touches hook scoping, child graph checkpointing, interrupt propagation, and resume semantics.
Desired behavior
- Preserve current hook propagation: parent-registered
PreToolUse, PostToolUse, PostToolBatch, and PermissionDenied hooks still fire for child subagent tools.
- Support child
PreToolUse decisions of ask with a real resumable interrupt visible to the parent Run / host.
- Resume should bridge back into the child graph and complete the original subagent tool call after approval.
- Deny/reject should fail closed and produce the expected denied tool result without executing the child tool.
SubagentStart, SubagentStop, ON_TOOL_EXECUTE, ON_RUN_STEP_COMPLETED, and ON_SUBAGENT_UPDATE ordering should remain deterministic enough for UI/SSE consumers.
- No raw
configurable, metadata, user credentials, tokens, checkpoint internals, scratchpad/currentTaskInput, resolve, or reject should become observable in publishable ON_SUBAGENT_UPDATE payloads.
Design questions
- How should parent and child run IDs/session IDs map for hook lookup, halt signals, and
PermissionDenied?
- Should child graphs inherit the parent checkpointer, use a child checkpoint namespace, or create an explicit subagent checkpoint bridge?
- How should
SubagentExecutor.execute() surface child interrupt() instead of catching it as a terminal Subagent error?
- How should the parent resume payload identify the subagent run, parent subagent tool call, child tool call, and approval decision?
- What should happen with multiple concurrent subagents, or a child graph that raises multiple approval requests?
Acceptance criteria
- Unit/integration tests cover a child subagent tool hook returning
ask and resuming with approve/deny/reject decisions.
- Tests cover multiple subagents and at least one child tool that uses event-driven
ON_TOOL_EXECUTE.
- Tests prove parent-scoped hooks still fire inside subagents after resume.
- Tests prove publishable
ON_SUBAGENT_UPDATE payloads remain sanitized and do not expose host config/metadata/tokens/checkpoint internals.
- Live integration confirms subagents with tools, no tools, and hooks still work with the nested approval flow.
Related
Context
PR #185 (
danny-avila/sanitize-subagent-events) made subagent update events safe to publish and propagated the parentHookRegistryinto child subagent graphs so child tool hooks fire. During review, nested HITL was deliberately left out of that PR because it needs a larger design than event sanitization.Today, child subagent
PreToolUse/PostToolUsehooks can run, but childPreToolUsehooks that returnaskdo not produce a resumable parent interrupt. The current behavior is intentionally fail-closed for safety: child graphs do not inherithumanInTheLoop, so subagent tool approvals do not enter a partially-supported checkpoint/resume flow.Problem
A host should be able to register a parent-scoped tool policy hook and have it apply inside subagents, including approval flows. For example, a child subagent calculator/MCP/local-tool call should be able to trigger a human approval request, pause the parent run, resume cleanly after approval/denial, and preserve subagent event ordering without leaking sensitive runtime config.
This is more involved than the PR #185 patch because it touches hook scoping, child graph checkpointing, interrupt propagation, and resume semantics.
Desired behavior
PreToolUse,PostToolUse,PostToolBatch, andPermissionDeniedhooks still fire for child subagent tools.PreToolUsedecisions ofaskwith a real resumable interrupt visible to the parentRun/ host.SubagentStart,SubagentStop,ON_TOOL_EXECUTE,ON_RUN_STEP_COMPLETED, andON_SUBAGENT_UPDATEordering should remain deterministic enough for UI/SSE consumers.configurable,metadata, user credentials, tokens, checkpoint internals, scratchpad/currentTaskInput,resolve, orrejectshould become observable in publishableON_SUBAGENT_UPDATEpayloads.Design questions
PermissionDenied?SubagentExecutor.execute()surface childinterrupt()instead of catching it as a terminalSubagent error?Acceptance criteria
askand resuming with approve/deny/reject decisions.ON_TOOL_EXECUTE.ON_SUBAGENT_UPDATEpayloads remain sanitized and do not expose host config/metadata/tokens/checkpoint internals.Related
askdecisions fail-closed until this larger checkpoint/resume bridge exists.