Compatibility Notes
agentscope-extensions-agui converts AgentScope v2 AgentEvent streams into AG-UI Protocol events so front-end UIs can render an agent run in real time, including text, reasoning, tool calls, state, custom events, token usage, and HITL interrupts.
RUN_ERROR and RUN_FINISHED are mutually exclusive terminal events. Set emitRunFinishedAfterError=true only if you still need the legacy RUN_ERROR + RUN_FINISHED sequence.
AguiMessage.content is represented as typed message content. For text-only code paths, use getTextContent().
Multimodal input is supported, but document types are not supported yet.
AguiMessageConverter.toAguiMessage() currently preserves text and tool-call fields only; image, audio, video, and document content blocks are not serialized back into AG-UI message content.
When To Use
- You need to connect an AgentScope agent to an AG-UI-compatible front end or a custom chat UI.
- You need to stream
RUN_*,TEXT_MESSAGE_*,TOOL_CALL_*,CUSTOM, and related AG-UI events over SSE. - You need frontend tools, user-approval interrupts, runtime context propagation, or custom event-conversion extensions.
Add Dependencies
For manual adapter usage, add:Quickstart
RunAgentInput, including threadId, runId, messages, tools, state, and related fields. The adapter converts AG-UI messages to AgentScope Msg objects, invokes v2 streamEvents(...), and converts each AgentEvent to AG-UI events.
Event Mapping
The v2 path consumesAgentEvent. Built-in converters handle semantic mapping, and unmapped events fall back to the official RAW event.
Normal
RUN_STARTED and RUN_FINISHED events are driven by upstream AgentStartEvent and AgentEndEvent. If a normal stream completes without an upstream AgentEndEvent, the adapter does not synthesize RUN_FINISHED. On errors, the adapter emits a RUN_ERROR with a timestamp. RUN_ERROR and RUN_FINISHED are mutually exclusive terminal events. Set emitRunFinishedAfterError=true (or Spring Boot agentscope.agui.emit-run-finished-after-error=true) only for legacy clients that still expect a finish event after an error.
Subagent events
By default (emitSubagentEventsAsNative=false), AgentEvents with a non-null source (child / remote subagent events) are not mapped to native TEXT_MESSAGE_* / RUN_* / tool-call events. They become AG-UI CUSTOM events under the subagent.* namespace so they do not pollute the parent run lifecycle or text stream:
Each payload includes at least
source and type (plus type-specific fields such as delta or toolCallId).
To restore the previous behavior where child events used the same native converters as the parent:
AG-UI Base Event Properties
EveryAguiEvent supports the official base event properties: optional timestamp and rawEvent.
The default config does not enable BaseEventPropertiesEnricher, so the framework does not add timestamp to every event by default and does not expose internal AgentEvent objects as rawEvent by default. Enable the default enricher explicitly if you want timestamps filled:
BaseEventPropertiesEnricher only fills a missing timestamp; it preserves existing timestamps and does not write rawEvent. To expose rawEvent, register a custom AguiEventEnricher.
The Spring Boot starter does not implicitly enable the default base properties enricher. If you want that behavior, expose a BaseEventPropertiesEnricher bean or your own AguiEventEnricher bean.
Custom Converters And Enrichers
AgentEventConverter extends or overrides semantic mapping. For the same AgentEvent type, a user converter overrides the built-in converter.
AguiEventEnricher runs after conversion. It is intended for cross-cutting concerns such as timestamp, rawEvent, tracing fields, or other event decoration. It may modify, append, or filter converter output.
AgentEventConverter and AguiEventEnricher beans and uses orderedStream() so @Order / Ordered are honored.
Token Usage
Token usage is disabled by default. Manual config:ModelCallEndEvent with usage emits a CUSTOM event: delta is the current model-call usage. cumulative is the accumulated usage within the current AG-UI run.
RuntimeContext
AguiAgentAdapter.run(input, runtimeContext) accepts a caller-provided RuntimeContext. The adapter copies the caller context first, then applies AG-UI protocol metadata so the required defaults are not lost.
Because
sessionId always comes from threadId, the same agent instance remains isolated across AG-UI threads.
Spring Boot Integration
The starter registers MVC or WebFlux endpoints automatically. Common config:interrupt-on-disconnect controls whether an Agent run is interrupted when the MVC/WebFlux SSE
connection is closed, times out, or fails while sending an event. It defaults to true for
backward compatibility. Set it to false to let the Agent continue running after the client
disconnects; events produced while the connection is closed are not replayed by the starter.
You can extend the default chain with beans:
AgentEventConverter: custom event semantic mapping.AguiEventEnricher: cross-cutting event enrichment.AguiRuntimeContextResolver: request-scopedRuntimeContextinjection.AguiAgentAdapterFactory: replacement for defaultAguiAgentAdapterconstruction.
AguiRuntimeContextResolver can read the transport, path agent id, header agent id, headers, query params, and native Web request.
forwardedProps comes from the client request body and is suitable for UI options or frontend context. Do not treat it as a trusted identity source; server-side user identity should come from authentication or a server-side resolver.
Frontend Tools And Merge Mode
An AG-UI front end can pass tool schemas throughRunAgentInput.tools. The adapter injects those tools into the agent toolkit at the start of one run and cleans them up after the run completes or is cancelled.
The default is
MERGE_FRONTEND_PRIORITY. Injection is run scoped and does not permanently mutate the agent toolkit.
HITL Interrupts
When a run pauses for a tool decision, the AG-UI adapter emits the official interrupt outcome onRUN_FINISHED. AgentScope Java has two built-in tool-call interrupt paths:
- Tool suspension / external execution: a suspended
ToolResultBlockbecomes atool_callinterrupt and resumes as aToolResultBlock. - Permission confirmation:
RequireUserConfirmEventbecomes atool_callinterrupt with AgentScope metadata and resumes as aConfirmResult.
reason: "tool_call" because the interrupt is bound to a specific toolCallId. Do not use reason: "confirmation" for these tool-bound approvals.
resume[] field on the next runAgent request for the same threadId:
status supports the official resolved and cancelled values. For the common approval case where a user rejects a tool request, prefer resolved and express the business decision in payload, for example { "approved": false }; use cancelled when the interrupt itself is cancelled.
For permission confirmations, payload.approved must be the boolean true to approve the tool. Any missing, non-boolean, or false value is treated as denial. payload.editedArgs, when present, must be a JSON object and is a full replacement of the original tool arguments, not a partial merge. AgentScope Java rebuilds both the ToolUseBlock.input and raw JSON ToolUseBlock.content from editedArgs, so the approved tool executes the edited arguments.
The front end does not need to echo metadata in resume[]; it only sends interruptId, status, and payload. Through the Spring AguiRequestProcessor entry point, AgentScope Java records the latest RUN_FINISHED.outcome.interrupts[] server-side, validates that the next resume[] covers all open interrupts, and passes the originating interrupts into the adapter for conversion.