Skip to content

feat: Support resumable HITL for subagent tool hooks #188

@danny-avila

Description

@danny-avila

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions