Skip to content

feat: add AG-UI (AGUI) as fourth first-class protocol mode#858

Merged
aidandaly24 merged 18 commits intoaws:mainfrom
aidandaly24:feat/agui-protocol
Apr 22, 2026
Merged

feat: add AG-UI (AGUI) as fourth first-class protocol mode#858
aidandaly24 merged 18 commits intoaws:mainfrom
aidandaly24:feat/agui-protocol

Conversation

@aidandaly24
Copy link
Copy Markdown
Contributor

@aidandaly24 aidandaly24 commented Apr 15, 2026

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:

  • AGUI added to ProtocolModeSchema, PROTOCOL_FRAMEWORK_MATRIX, RESERVED_PROJECT_NAMES in both CLI and CDK
  • AGUI added to agentcore.schema.v1.json protocol enum
  • Complete AguiEvent typed union (27 event types) in src/cli/aws/agui-types.ts
  • AguiRunInput request type with buildAguiRunInput helper

Python agent templates (3 frameworks):

  • Strandsag-ui-strands >= 0.1.7 with session_manager_provider for per-thread memory isolation
  • LangChain+LangGraph — StateGraph with ToolNode + ReAct loop, MemorySaver checkpointer, LangchainInstrumentor
  • GoogleADKag-ui-adk with ADKAgent, AGUIToolset, create_adk_app. Uses plain opentelemetry-distro (not aws-opentelemetry-distro) due to google-adk version conflict

Unified SSE parser (src/cli/aws/agui-parser.ts):

  • Single parser shared between dev (invoke-agui.ts) and deployed (agentcore.ts) paths
  • Bounded cursor-based pruning with singleConsumer mode for dev path
  • CRLF-safe line splitting (/\r?\n/)
  • Malformed JSON skipped (never yielded as content)

Dev mode:

  • Persistent threadId per dev session for multi-turn conversations (reset on clearConversation)
  • Tool call tracking with toolCallId-based matching
  • Retry logic with exponential backoff (no retry after streaming starts)

Container support:

  • Dockerfile {{#if enableOtel}} conditional respects instrumentation.enableOtel schema field
  • enableOtel threaded through AgentRenderConfigBaseRenderer → Handlebars template
  • MCP+Container latent bug fixed (enableOtel: false was ignored by Dockerfile)

Import path hardening:

  • ProtocolModeSchema.safeParse replaces unsafe as cast in yaml-parser.ts
  • MCP enableOtel clamped to false regardless of YAML value in import actions

DX improvements:

  • formatZodIssue falls back to issue.code instead of printing literal "undefined"
  • New dockerfile-render.test.ts snapshot test covering both enableOtel branches
  • Dynamic imports converted to static where non-intentional (AGENTS.md compliance)

Deployed & tested

Config Create Template Deploy Invoke
Strands+Bedrock CodeZip
Strands+Bedrock Container ✅ "2+3=5"
LangGraph+Bedrock CodeZip ✅ "325435+435634563456456=435634563781891"
ADK+Gemini CodeZip
ADK+Gemini Container ✅ container builds
Dev mode multi-turn ✅ "favorite color is blue"
Dev mode tool call ✅ TOOL_CALL_START→ARGS→END→RESULT

Related Issue

Closes #796

Type of Change

  • New feature
  • Bug fix

Testing

  • I ran npm run test:unit and npm run test:integ
  • I ran npm run typecheck
  • I ran npm run lint
  • If I modified src/assets/, I ran npm run test:update-snapshots and committed the updated snapshots
  • End-to-end deployment testing across all 3 frameworks × 2 build types
  • Dev mode testing with curl against local uvicorn server
  • 4-lane parallel code review (Planner/Architect/Critic consensus + OMC code-reviewer)

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings

@aidandaly24 aidandaly24 requested a review from a team April 15, 2026 15:46
@github-actions github-actions Bot added the size/xl PR size: XL label Apr 15, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 15, 2026

Package Tarball

aws-agentcore-0.9.1.tgz

How to install

npm install https://github.com/aws/agentcore-cli/releases/download/pr-858-tarball/aws-agentcore-0.9.1.tgz

@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Apr 15, 2026
Comment thread src/assets/python/agui/langchain_langgraph/base/main.py
Comment thread src/assets/python/agui/langchain_langgraph/base/main.py Outdated
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Apr 16, 2026
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Apr 20, 2026
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Apr 20, 2026
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Apr 20, 2026
Comment thread src/assets/python/a2a/googleadk/base/main.py
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.
@github-actions github-actions Bot removed the size/xl PR size: XL label Apr 21, 2026
@github-actions github-actions Bot added the size/xl PR size: XL label Apr 21, 2026
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."
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Apr 21, 2026
@jesseturner21
Copy link
Copy Markdown
Contributor

Missing JSON Schema Update

The PR description states that AGUI was added to agentcore.schema.v1.json protocol enum, but this file is not included in the diff. The current schema at schemas/agentcore.schema.v1.json still has:

"protocol": {
  "type": "string",
  "enum": ["HTTP", "MCP", "A2A"]
}

This needs to be updated to include "AGUI" so that users who validate their config against the JSON schema can use the new protocol.

Fix: Add "AGUI" to the protocol enum in schemas/agentcore.schema.v1.json.

@jesseturner21
Copy link
Copy Markdown
Contributor

jesseturner21 commented Apr 21, 2026

This pr has a corresponding change in the l3 constructs package here https://github.com/aws/agentcore-l3-cdk-constructs/pull/151

Comment thread src/cli/operations/dev/invoke.ts Outdated
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.
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Apr 22, 2026
@aidandaly24 aidandaly24 merged commit 52144dc into aws:main Apr 22, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xl PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New cli does not support agui

3 participants