Build generative UI for AI agents on Amazon Bedrock AgentCore with the AG-UI protocol Amazon Web Services announced support for the AG-UI protocol on Amazon Bedrock AgentCore, enabling AI agents to render interactive charts, update shared canvases, and pause for human approval. The integration, demonstrated through the Fullstack AgentCore Solution Template and CopilotKit, allows developers to build decoupled agent backends and frontends with generative UI and human-in-the-loop interactions. Artificial Intelligence https://aws.amazon.com/blogs/machine-learning/ Build generative UI for AI agents on Amazon Bedrock AgentCore with the AG-UI protocol AI agents can do more than chat. With the right protocol, an agent can render an interactive chart inline in your conversation, update a shared canvas in real time, or pause mid-execution to ask for your approval before proceeding. These interactions generative UI, shared state, and human-in-the-loop need a standard way for agent backends to communicate dynamic events to frontends. AG-UI https://docs.ag-ui.com/introduction Agent-User Interaction Protocol is an open protocol that defines this standard. It works with multiple agent frameworks Strands Agents, LangGraph, CrewAI and frontend libraries React, Angular, Vue . With AG-UI, your agent code and your frontend code stay decoupled. You pick the best framework for your backend and the best library for your frontend, and AG-UI connects them. Amazon Bedrock AgentCore https://aws.amazon.com/bedrock/agentcore/ is part of the Amazon Bedrock https://aws.amazon.com/bedrock/ family of services for generative AI. AgentCore is an agentic platform for building, deploying, and operating AI agents securely at scale, using any framework and any model. This post walks through how AG-UI integrates into the Fullstack AgentCore Solution Template FAST https://github.com/awslabs/fullstack-solution-template-for-agentcore to build interactive agent frontends on Amazon Bedrock AgentCore. We then show how CopilotKit https://copilotkit.ai/ extends this with generative UI, shared state, and human-in-the-loop interactions, all deployed on Amazon Bedrock AgentCore. Overview of solution Amazon Bedrock AgentCore Runtime provides a secure, serverless, and purpose-built hosting environment for deploying and running AI agents or tools. AgentCore Runtime supports several agent protocols. Model Context Protocol MCP connects agents to tools, Agent2Agent A2A connects agents to other agents, and AG-UI connects agents to users. When you deploy an agent container with the AG-UI protocol flag, AgentCore acts as a transparent proxy. It handles authentication Signature Version 4 SigV4 or OAuth 2.0 through Amazon Cognito , session isolation, scaling, and observability. Your container exposes POST /invocations for AG-UI requests and GET /ping for health checks on port 8080. AgentCore passes requests through unchanged. For more details, see Deploy AGUI servers in AgentCore Runtime https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-agui.html . FAST is a ready-to-deploy starter project. It connects AgentCore Runtime, Gateway, Identity, Memory, and Code Interpreter with a React frontend and Amazon Cognito authentication, all defined with AWS Cloud Development Kit AWS CDK . It ships with agent patterns for Strands Agents, LangGraph, and the Claude Agent SDK. FAST v0.4.1 added two AG-UI patterns agui-strands-agent and agui-langgraph-agent that share a single frontend parser. For a full walkthrough of FAST’s architecture and deployment, see Accelerate agentic application development with a full-stack starter template for Amazon Bedrock AgentCore https://aws.amazon.com/blogs/machine-learning/accelerate-agentic-application-development-with-a-full-stack-starter-template-for-amazon-bedrock-agentcore/ . The solution has two layers. AG-UI in FAST provides two new agent patterns and a single frontend parser that handles both, so the frontend doesn’t need to know which agent framework is running. CopilotKit + FAST is a standalone sample that replaces FAST’s built-in chat UI with CopilotKit. It adds generative UI inline charts and components , bidirectional shared state a todo canvas , and human-in-the-loop interactions a meeting scheduler that pauses the agent and waits for your input . Both layers deploy on AgentCore Runtime with Cognito authentication, AgentCore Gateway for MCP tool connectivity, and AgentCore Memory for persistent conversations. Walkthrough This walkthrough has two parts. First, we show how the AG-UI patterns work in FAST and how a single frontend parser handles both Strands and LangGraph backends. Second, we deploy the CopilotKit sample to demonstrate generative UI, shared state, and human-in-the-loop on AgentCore. Source code: Prerequisites For this walkthrough, you should have the following prerequisites: - An AWS account https://signin.aws.amazon.com/signin?redirect uri=https%3A%2F%2Fportal.aws.amazon.com%2Fbilling%2Fsignup%2Fresume&client id=signup with permissions for AWS CloudFormation, Amazon Elastic Container Registry Amazon ECR , Amazon Bedrock AgentCore, Amazon Cognito, and AWS Amplify. AWS Command Line Interface AWS CLI v2 https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html installed and configured. AWS CDK https://docs.aws.amazon.com/cdk/v2/guide/getting-started.html installed. Node.js 18 or later https://nodejs.org/ and Python 3.11 or later.- Docker running, for container builds. - Model access enabled in the Amazon Bedrock console for the model the agent uses. AG-UI in FAST: One parser, two frameworks The agui-strands-agent pattern wraps a Strands Agent in StrandsAgent from the ag-ui-strands library. The wrapper translates Strands streaming events into AG-UI Server-Sent Events automatically. Each request creates a fresh agent with Gateway MCP tools. AgentCore Memory is attached per thread through a session-manager provider, so conversation history persists across AgentCore Runtime scaling. Memory is opt-in: the provider returns None when MEMORY ID is unset: python patterns/agui-strands-agent/agent.py from ag ui strands import StrandsAgent, StrandsAgentConfig from bedrock agentcore.runtime import BedrockAgentCoreApp, RequestContext from strands import Agent app = BedrockAgentCoreApp Build the model and Code Interpreter once at module load MODEL = BedrockModel model id="us.anthropic.claude-sonnet-4-5-20250929-v1:0" CODE INTERPRETER = StrandsCodeInterpreterTools REGION .execute python securely @app.entrypoint async def invocations payload: dict, context: RequestContext : input data = RunAgentInput.model validate payload actor id = extract user id from context context Fresh agent per request --- picks up the caller's identity and tools agent = Agent model=MODEL, system prompt=SYSTEM PROMPT, tools= create gateway mcp client actor id , CODE INTERPRETER , session manager=get memory session manager actor id, session id , agui agent = StrandsAgent agent=agent, name="agui strands agent", config=StrandsAgentConfig session manager provider=make memory provider actor id , replay history into strands=False, , async for event in agui agent.run input data : yield event.model dump mode="json", by alias=True, exclude none=True BedrockAgentCoreApp reads the AgentCore Runtime headers WorkloadAccessToken , Authorization , Session-Id and populates context variables, so Gateway authentication and Memory work the same way as the HTTP patterns. The agui-langgraph-agent pattern uses LangGraphAGUIAgent from the copilotkit library. It builds the compiled graph fresh on every request, so each invocation gets MCP tools scoped to the caller. AgentCore Memory is opt-in here too: the helper returns None when MEMORY ID is unset, so you can run the pattern without provisioning Memory: python patterns/agui-langgraph-agent/agent.py from copilotkit import CopilotKitMiddleware, LangGraphAGUIAgent async def build graph actor id: str : """Build a fresh LangGraph compiled graph with Gateway tools.""" mcp client = await create gateway mcp client actor id tools = await mcp client.get tools tools.append CODE INTERPRETER return create agent model=MODEL, tools=tools, checkpointer=get memory saver , None when MEMORY ID is unset middleware= CopilotKitMiddleware , system prompt=SYSTEM PROMPT, @app.entrypoint async def invocations payload: dict, context: RequestContext : input data = RunAgentInput.model validate payload actor id = extract user id from context context graph = await build graph actor id agui agent = LangGraphAGUIAgent name="agui langgraph agent", graph=graph, config={"configurable": {"actor id": actor id}}, async for event in agui agent.run input data : yield event.model dump mode="json", by alias=True, exclude none=True Both patterns produce the same AG-UI events. The protocol defines a typed event stream over Server-Sent Events. For example, a single tool call produces this sequence: data: {"type": "RUN STARTED", "threadId": "t1", "runId": "r1"} data: {"type": "TEXT MESSAGE START", "messageId": "m1", "role": "assistant"} data: {"type": "TEXT MESSAGE CONTENT", "messageId": "m1", "delta": "Let me check "} data: {"type": "TEXT MESSAGE CONTENT", "messageId": "m1", "delta": "that for you."} data: {"type": "TEXT MESSAGE END", "messageId": "m1"} data: {"type": "TOOL CALL START", "toolCallId": "tc1", "toolCallName": "get weather"} data: {"type": "TOOL CALL ARGS", "toolCallId": "tc1", "delta": "{\"location\": \"Seattle\"}"} data: {"type": "TOOL CALL END", "toolCallId": "tc1"} data: {"type": "TOOL CALL RESULT", "toolCallId": "tc1", "content": "{\"temp\": 55}"} data: {"type": "RUN FINISHED", "threadId": "t1", "runId": "r1"} The frontend parser maps each event to a frontend action: js // frontend/src/lib/agentcore-client/parsers/agui.ts export const parseAguiChunk: ChunkParser = line, callback = { if line.startsWith "data: " return; const json = JSON.parse line.substring 6 .trim ; switch json.type { case "TEXT MESSAGE CONTENT": callback { type: "text", content: json.delta ?? "" } ; break; case "TOOL CALL START": callback { type: "tool use start", toolUseId: json.toolCallId, name: json.toolCallName } ; break; case "TOOL CALL RESULT": callback { type: "tool result", toolUseId: json.toolCallId, result: json.content ?? "" } ; break; case "RUN FINISHED": callback { type: "result", stopReason: "end turn" } ; } }; Compare this to the HTTP patterns, where Strands, LangGraph, and Claude-agent-sdk each need a separate parser to handle their different streaming formats. With AG-UI, the backend framework is abstracted away. You can swap agui-strands-agent for agui-langgraph-agent in your configuration and the frontend doesn’t change. To deploy, set the pattern in infra-cdk/config.yaml and run CDK: backend: pattern: agui-strands-agent or agui-langgraph-agent deployment type: docker cd infra-cdk cdk deploy --require-approval never python3 ../scripts/deploy-frontend.py CopilotKit + FAST: Generative UI, shared state, and human-in-the-loop The base FAST frontend provides a functional chat interface, but AG-UI supports much richer interactions: agents rendering custom UI components, syncing state with the frontend, and pausing for user input mid-execution. CopilotKit is a React library built specifically for these patterns. The CopilotKit team built a sample application https://github.com/aws-samples/sample-FAST-applications/tree/main/samples/copilotkit-generative-ui on top of FAST that demonstrates these capabilities on AgentCore. It includes both LangGraph and Strands agent patterns, and you pick one at deploy time. Generative UI spans a spectrum from high frontend control to high agent freedom. This sample sits at the controlled end: the frontend owns prebuilt React components, and the agent chooses which to render and supplies the data over AG-UI events. Further along the spectrum, agents return declarative UI descriptions that the frontend renders, or full UI surfaces that the frontend embeds. AG-UI carries all three, because it standardizes the event and state stream rather than the UI itself. The more freedom you hand the agent, the more you take on: open-ended surfaces need sandboxing and input validation. Generative UI: Agents render React components With CopilotKit, the agent renders custom React components inline in the chat, not only text. The frontend registers components that the agent can invoke through AG-UI tool call events: // Register a pie chart the agent can render useComponent { name: "pieChart", description: "Displays data as a pie chart.", parameters: PieChartPropsSchema, render: PieChart, } ; When the agent calls the pieChart tool, CopilotKit intercepts the TOOL CALL START and TOOL CALL ARGS events and renders the PieChart component directly in the conversation. The agent first calls a query data tool to fetch data from a sample comma-separated values CSV file, then passes the results to the chart component. Shared state: A todo canvas synced with the agent The sample includes a todo canvas that stays in sync between the agent and the UI bidirectionally. When you tell the agent “Add three tasks: design the API, write tests, and deploy to staging,” the agent calls manage todos and the canvas updates in real time through AG-UI STATE SNAPSHOT events. You can also edit todos directly in the UI. The agent sees the updated state on its next turn because the Strands pattern injects the current todos into the system prompt: php def state context builder state: dict - str: todos = state.get "todos", if todos: return f"\nCurrent todos:\n{json.dumps todos, indent=2 }" return "" Human-in-the-loop: The agent pauses and waits The sample demonstrates a meeting scheduler where the agent pauses mid-execution and renders a time picker. The user selects a time, and the agent continues with that selection: useHumanInTheLoop { name: "scheduleTime", description: "Schedule a meeting with the user.", parameters: z.object { reasonForScheduling: z.string , meetingDuration: z.number , } , render: { respond, status, args } =