Skip to content

fix(agui): emit AG-UI interrupt for permission-type HITL tool confirmation (#2437) - #2495

Open
wzq-xzwj wants to merge 1 commit into
agentscope-ai:mainfrom
wzq-xzwj:fix/2437-permission-hitl-interrupt
Open

fix(agui): emit AG-UI interrupt for permission-type HITL tool confirmation (#2437)#2495
wzq-xzwj wants to merge 1 commit into
agentscope-ai:mainfrom
wzq-xzwj:fix/2437-permission-hitl-interrupt

Conversation

@wzq-xzwj

Copy link
Copy Markdown
Contributor

What & Why

Fixes #2437.

The AG-UI adapter only surfaced suspend-type HITL (tools that throw ToolSuspendException / frontend tools, i.e. GenerateReason.TOOL_SUSPENDED). The permission-type HITL path was dropped:

  • Under DEFAULT permission mode, a non-readonly tool makes ReActAgent emit RequireUserConfirmEvent + RequestStopEvent(PERMISSION_ASKING).
  • RequireUserConfirmEvent had no converter, so it fell through to the RAW fallback and no Interrupt reached RUN_FINISHED.
  • The frontend therefore had nothing to confirm/deny, and resume was impossible.

This builds directly on the converter-registry architecture introduced in #2306, extending it to the confirmation path rather than changing its design.

Changes

  • PermissionConfirmEventConverter (new) — maps RequireUserConfirmEvent to one AG-UI Interrupt per pending ToolUseBlock, with reason tool_confirmation and toolName / toolInput / toolContent / replyId metadata. Registered in AgentEventConverterRegistry. The interrupt id keeps the replyId:toolCallId format so resume can recover the tool call id (consistent with AgentLifecycleEventConverter).
  • AguiResumeCoordinator — tracks tool_confirmation interrupts alongside tool_call, exposing them through a new resume-interrupts runtime-context key.
  • AguiAgentAdapter — forwards the resume interrupts to the message converter.
  • AguiMessageConverter — for confirmation interrupts, builds a ConfirmResult (approved/denied) from the resume payload and reconstructs the ToolUseBlock with non-null JSON content (via JsonUtils.resolveToolCallArgsJson) to avoid the tool-input validation failure (argument "content" is null) on resume. Non-confirmation resumes keep the existing ToolResultBlock path.

Tests

  • Added unit tests for resolved / cancelled / explicit-approved:false confirmations and the non-confirmation fallback.
  • Full agentscope-extensions-agui module suite: 435 tests, 0 failures, 0 errors.

Notes

  • No behavior change for suspend-type HITL; confirmation is a new, separate path selected by interrupt reason.

@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@codecov

codecov Bot commented Jul 30, 2026

Copy link
Copy Markdown

…ation (agentscope-ai#2437)

The AG-UI adapter only handled suspend-type HITL (ToolSuspendException /
frontend tools, GenerateReason.TOOL_SUSPENDED). Permission-type HITL --
where a non-readonly tool under DEFAULT permission mode makes ReActAgent
emit RequireUserConfirmEvent + RequestStopEvent(PERMISSION_ASKING) -- was
dropped: RequireUserConfirmEvent fell through to the RAW fallback and no
Interrupt reached RUN_FINISHED, so the frontend could never confirm/deny.

Building on the converter-registry architecture introduced by agentscope-ai#2306:

- Add PermissionConfirmEventConverter that maps RequireUserConfirmEvent to
  one AG-UI Interrupt per pending ToolUseBlock (reason "tool_confirmation"),
  carrying toolName/toolInput/toolContent/replyId metadata, and register it
  in AgentEventConverterRegistry. Interrupt id keeps the "replyId:toolCallId"
  format so resume can recover the tool call id.
- AguiResumeCoordinator now tracks "tool_confirmation" interrupts alongside
  "tool_call" ones and exposes them via a new resume-interrupts runtime key.
- AguiAgentAdapter forwards the resume interrupts to the message converter.
- AguiMessageConverter builds a ConfirmResult (approved/denied) from the
  resume payload for confirmation interrupts, reconstructing the ToolUseBlock
  with non-null JSON content to avoid the tool-input validation NPE on resume;
  non-confirmation resumes keep the existing ToolResultBlock path.
- Add unit tests covering resolved/cancelled/explicit-false confirmations and
  the non-confirmation fallback.
@wzq-xzwj
wzq-xzwj force-pushed the fix/2437-permission-hitl-interrupt branch from abd07d3 to f3ece2c Compare July 30, 2026 10:50
@wzq-xzwj

Copy link
Copy Markdown
Contributor Author

@jujn 麻烦帮忙审核一下哈,多谢

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AG-UI adapter drops human-in-the-loop tool confirmation (consumes deprecated v1 Event stream; RequireUserConfirmEvent never bridged)

1 participant