feat: add AG-UI (AGUI) as fourth first-class protocol mode#858
Merged
aidandaly24 merged 18 commits intoaws:mainfrom Apr 22, 2026
Merged
feat: add AG-UI (AGUI) as fourth first-class protocol mode#858aidandaly24 merged 18 commits intoaws:mainfrom
aidandaly24 merged 18 commits intoaws:mainfrom
Conversation
Contributor
Package TarballHow to installnpm install https://github.com/aws/agentcore-cli/releases/download/pr-858-tarball/aws-agentcore-0.9.1.tgz |
3d2587b to
aa64583
Compare
avi-alpert
reviewed
Apr 15, 2026
avi-alpert
reviewed
Apr 16, 2026
46de280 to
bde5a74
Compare
avi-alpert
reviewed
Apr 20, 2026
Bugs found by deploying all 3 AGUI frameworks to AWS and invoking: - Bump ag-ui-strands to >= 0.1.4 (0.1.3 crashes on strands >= 1.19.0 due to accessing removed private attr agent.state._state) - Remove parallel_tool_calls=False from LangGraph template (Bedrock rejects this OpenAI-specific parameter with ValidationException) - Remove aws-opentelemetry-distro from GoogleADK template (conflicts with google-adk >= 1.16.0 OpenTelemetry dependencies — agents using this template should set instrumentation.enableOtel: false)
The AGUI LangGraph template had a single-node graph (chat → END) with
no tool execution loop. When the model called add_numbers, the graph
exited without executing the tool or generating a text response,
producing "(no content in AGUI response)" in agentcore dev.
Template fix:
- Add ToolNode(tools=backend_tools) as a "tools" node
- Replace set_finish_point("chat") with tools_condition conditional edge
- Add edge from "tools" back to "chat" for the ReAct loop
- Separate backend_tools list from frontend tools (state["tools"])
This matches the standard LangGraph ReAct pattern (agent → tools →
agent → ... → END) and how the HTTP/A2A templates use create_react_agent.
Dev invoke fix:
- invoke-agui.ts now tracks TOOL_CALL_START/ARGS/END/RESULT events
- When no text is produced but tool calls were seen, surfaces them
as [Tool: name(args)] instead of generic "(no content)" message
16 issues from 4-lane parallel code review, all addressed: Critical fixes: - Strands template: use session_manager_provider from ag-ui-strands 0.1.7 instead of hardcoded "default-session"/"default-user" - Dev client: persist threadId per session for multi-turn conversations - CRLF handling: use /\r?\n/ in SSE parsers (invoke-agui + invoke.ts) - Malformed JSON no longer yielded as content (shared parser skips) - Unbounded aguiEvents array replaced with bounded cursor-based pruning Structural improvements: - Unified SSE parser (agui-parser.ts) replaces two divergent parsers in invoke-agui.ts (dev) and agentcore.ts (deployed). Net -39 LOC. - Dual-consumer support with singleConsumer mode for dev path - AguiEvent type union completed (4 missing members added) - Dynamic imports converted to static where non-intentional (AGENTS.md) Python template fixes: - LangGraph: add LangchainInstrumentor + dep, remove unused END import, MemorySaver already removed in prior commit - GoogleADK: remove dead load_model() + bedrock-agentcore dep, remove hardcoded user_id (ADK defaults to per-thread identity) - Strands: bump ag-ui-strands pin to >= 0.1.7 enableOtel plumbing: - Dockerfile CMD conditional on enableOtel (Handlebars) - enableOtel threaded through AgentRenderConfig + BaseRenderer - Import path: ProtocolModeSchema.safeParse replaces unsafe as-cast - Import path: MCP enableOtel clamped regardless of YAML value - GoogleADK uses plain opentelemetry-distro (aws-distro conflicts) DX + testing: - formatZodIssue falls back to issue.code instead of literal "undefined" - New dockerfile-render.test.ts covers both enableOtel branches - All snapshots updated
The static JSON schema file used for CDK validation was not updated when AGUI was added to the Zod schema. This caused CDK synth to reject protocol: "AGUI" with a misleading validation error.
ag_ui_langgraph calls aget_state(config) with thread_id which requires a checkpointer. Without it, every invocation throws ValueError: No checkpointer set. The original msgpack crash only triggers with numbers exceeding 2^63 (ormsgpack limitation), not with normal large numbers. Bug bash confirmed: 325435 + 435634563456456 works correctly with MemorySaver present.
- Wrap reader.releaseLock() in try/catch to prevent error masking if lock is already released (HIGH from code review) - Replace textStream! non-null assertion with runtime guard (MEDIUM from code review)
Previously matched by activeToolName which was already reset to '' by TOOL_CALL_END. The find() never matched, falling through to the last tool call — wrong for parallel tool calls. Now matches by toolCallId which is the unique identifier AG-UI provides per tool invocation.
The schemas/ directory is auto-regenerated from Zod schemas during the release workflow. AGUI is already in ProtocolModeSchema (constants.ts) and will appear in the JSON schema on next release.
All 3 AGUI templates now read PORT from env with default 8080:
uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("PORT", "8080")))
Addresses PR review comment requesting configurable port for local testing.
Schema enum stays 'AGUI' (internal), but TUI display text uses 'AG-UI' which is the protocol's official name.
74dc895 to
c8c275f
Compare
The template was missing load_model() call and bedrock-agentcore dep, so GOOGLE_API_KEY was never set from the AgentCore credential. Both dev mode and deployed agents failed with "No API key provided."
Contributor
Missing JSON Schema UpdateThe PR description states that "protocol": {
"type": "string",
"enum": ["HTTP", "MCP", "A2A"]
}This needs to be updated to include Fix: Add |
Contributor
|
This pr has a corresponding change in the l3 constructs package here https://github.com/aws/agentcore-l3-cdk-constructs/pull/151 |
avi-alpert
reviewed
Apr 22, 2026
AGENTS.md requires all imports at top of file. The dynamic import had no meaningful performance benefit — AGUI parser is ~4KB in a 2.1MB CLI.
avi-alpert
approved these changes
Apr 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds AG-UI (AGUI) as a fourth first-class protocol mode alongside HTTP, MCP, and A2A. AG-UI is an SSE-based agent-to-UI protocol that enables rich streaming interactions (text, tool calls, reasoning, state management) between agents and frontends.
What's included
Schema & types:
AGUIadded toProtocolModeSchema,PROTOCOL_FRAMEWORK_MATRIX,RESERVED_PROJECT_NAMESin both CLI and CDKAGUIadded toagentcore.schema.v1.jsonprotocol enumAguiEventtyped union (27 event types) insrc/cli/aws/agui-types.tsAguiRunInputrequest type withbuildAguiRunInputhelperPython agent templates (3 frameworks):
ag-ui-strands >= 0.1.7withsession_manager_providerfor per-thread memory isolationag-ui-adkwithADKAgent,AGUIToolset,create_adk_app. Uses plainopentelemetry-distro(notaws-opentelemetry-distro) due to google-adk version conflictUnified SSE parser (
src/cli/aws/agui-parser.ts):invoke-agui.ts) and deployed (agentcore.ts) pathssingleConsumermode for dev path/\r?\n/)Dev mode:
threadIdper dev session for multi-turn conversations (reset on clearConversation)toolCallId-based matchingContainer support:
{{#if enableOtel}}conditional respectsinstrumentation.enableOtelschema fieldenableOtelthreaded throughAgentRenderConfig→BaseRenderer→ Handlebars templateImport path hardening:
ProtocolModeSchema.safeParsereplaces unsafeascast inyaml-parser.tsenableOtelclamped tofalseregardless of YAML value in import actionsDX improvements:
formatZodIssuefalls back toissue.codeinstead of printing literal"undefined"dockerfile-render.test.tssnapshot test covering both enableOtel branchesDeployed & tested
Related Issue
Closes #796
Type of Change
Testing
npm run test:unitandnpm run test:integnpm run typechecknpm run lintsrc/assets/, I rannpm run test:update-snapshotsand committed the updated snapshotsChecklist