Skip to content

feat(harness): human-in-the-loop and pause actor on input-required - #2714

Open
supreme-gg-gg wants to merge 14 commits into
mainfrom
jetc/feat/harness-hitl
Open

feat(harness): human-in-the-loop and pause actor on input-required#2714
supreme-gg-gg wants to merge 14 commits into
mainfrom
jetc/feat/harness-hitl

Conversation

@supreme-gg-gg

@supreme-gg-gg supreme-gg-gg commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

This PR adds end-to-end HITL support for the ADK, Codex, and Claude Code harnesses running on Substrate. When a task enters input-required, Kagent pauses the Actor so the worker can be released while preserving the live runtime state needed to continue the same turn.

Key changes

  • Adds binding-scoped MCP tool approval through AgentTemplate.spec.tools[].mcp.requireApproval.
  • Defines shared, typed A2A HITL payloads and validates approval and ask-user responses before resuming a task.
  • Adds a runtime-neutral pending-turn contract for parking, resuming, and canceling live harness processes.
  • Pauses Substrate Actors at input-required and continues to suspend them at terminal task boundaries.
  • Adds Codex MCP approval and native ask-user handling through the App Server protocol.
  • Adds Claude MCP approval through an authenticated, Actor-local permission-prompt-tool.
  • Updates the Go and Python ADK runtimes to apply approval policy to the originating MCP binding rather than matching tool names globally.
  • Adds UI controls and durable transcript records for tool approvals, rejection reasons, and ask-user answers.
  • E2E test coverage for approval for ADK, Codex, and Claude harness

Pausing

Input waits use Substrate Pause rather than Suspend. Pause preserves a FULL snapshot, including process memory, which is required for harnesses such as Codex and Claude that retain a live process while awaiting input. The paused snapshot is kept on node-local storage instead of object storage, reducing network overhead while the worker is released.

Terminal task boundaries still use Suspend with DATA snapshots.

AgentTemplate API for tool approval

Approval is configured on an MCP binding:

spec:
  tools:
    - mcp:
        server:
          kind: RemoteMCPServer
          name: kagent-tool-server
        tools:
          - tool_name
        requireApproval: true

requireApproval applies to every tool selected by that binding, or every tool on the server when tools is omitted. The API represents mixed protected and unprotected tool sets from one server as separate bindings, keeping selection and approval policy together. Partially completes #2688

ADK supports that split today. Codex and Claude currently reject duplicate bindings to the same RemoteMCPServer; Claude also exposes the whole server when partial tool selection cannot be enforced and reports a warning.

HITL coverage

The following flows are supported and tested:

  • MCP tool approval and rejection, including optional rejection reasons where supported by the harness.
  • Sequential and parallel MCP tool approval requests.
  • Ask-user questions for ADK and Codex, including multiple questions and choices.
  • Cancellation while a task is waiting for input.
  • Persisted HITL requests and responses in task history and the chat transcript.

Claude ask-user is not supported because the upstream Claude Code tool was removed. I will probably add this as a follow-up.

Permission mode

Configurable native permission modes for Codex and Claude are out of scope. Both harnesses continue to run with unrestricted native sandbox permissions because Substrate is the sandbox boundary. Built-in tools such as file access, shell, web search, and other MCP tool calls not marked with requireApproval will generally be auto-approved.

Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
…required

Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Sep 4, 2026
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
@supreme-gg-gg

Copy link
Copy Markdown
Contributor Author

Some demo with Claude (first) and Codex (second), ADK behaviour is similar:

claude.mp4
codex.mp4

Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
@supreme-gg-gg
supreme-gg-gg marked this pull request as ready for review September 4, 2026 22:49
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant