Forem

Cover image for Deploying AG-UI Agents to Production with Amazon Bedrock AgentCore
Anmol Baranwal Subscriber for CopilotKit

Posted on

Deploying AG-UI Agents to Production with Amazon Bedrock AgentCore

The Agent-User Interaction Protocol (AG-UI) standardizes how AI agents communicate with user applications.

But deploying those agents means the same manual work: configuring SSE endpoints, writing auth middleware, managing session isolation, and setting up auto-scaling. None of that is your agent logic. All of it had to be built before you could ship.

Amazon recently announced native AG-UI support in Amazon Bedrock AgentCore Runtime across 14 AWS regions. You bring your agent code in a container, set one protocol flag, and AgentCore handles the rest.

So I deployed Strands Agents to learn how it actually works end-to-end. This post covers everything I picked up, including what AgentCore is and the full deployment flow from a local server to a live UI.


Amazon Bedrock AgentCore Runtime

Amazon Bedrock AgentCore is an agentic platform for building, deploying, and operating agents securely at scale. AgentCore Runtime is a fully managed hosting environment.

You bring your agent code in a container, and AgentCore checks who's allowed in (auth), keeps each user's session separate (Session isolation), adds capacity when traffic spikes (auto-scaling) and logs everything to CloudWatch (observability). You don't write any of this code.

It's also framework-agnostic: agents built with Strands, LangGraph, CrewAI, or any other framework can deploy to AgentCore. Think of it as the production layer between your agent and your users.

It supports four protocols:

  • HTTP: default agent invocation
  • MCP: agent ↔ tools
  • A2A: agent ↔ agent
  • AG-UI: agent ↔ user (new)

You can read more about the differences in message format, discovery and authentication in their docs.

protocols

You configure with --protocol AGUI and the protocol layer is taken care of. Your job is just the agent logic.


AG-UI: the interaction protocol

AG-UI (Agent-User Interaction Protocol) is an open, event-based protocol that standardises how AI agents communicate with user-facing applications.

Instead of a custom WebSocket or polling layer, AG-UI defines a shared event stream between your agent backend and your frontend UI. It covers:

  • Streaming text responses as they generate
  • Tool call lifecycle (start to result)
  • State updates and progress
  • User interactions sent back into the agent mid-execution

ag-ui in the protocol stack

In practice, when your agent responds, the frontend receives a sequence of typed events:

data: {"type": "RUN_STARTED", "threadId": "test-123", "runId": "run-456"}
data: {"type": "TEXT_MESSAGE_START", "messageId": "msg-abc", "role": "assistant"}
data: {"type": "TEXT_MESSAGE_CONTENT", "messageId": "msg-abc", "delta": "Hello!"}
data: {"type": "TEXT_MESSAGE_END", "messageId": "msg-abc"}
data: {"type": "RUN_FINISHED", "threadId": "test-123", "runId": "run-456"}
Enter fullscreen mode Exit fullscreen mode

Any AG-UI-compatible frontend, including CopilotKit, can consume that stream directly. In the next section, we will see how it all connects through an architecture diagram.


How It All Connects

CopilotKit is an AG-UI-compatible React client. It connects to an AG-UI endpoint, subscribes to the event stream and renders streaming responses, tool progress, and state updates inside your app.

Once your agent is deployed to AgentCore, HttpAgent points to the AgentCore invocation URL with a Cognito Bearer token in the headers, and user messages flow back over AG-UI into the running agent.

Here is what the full stack looks like when deployed:

Your agent framework  [Strands · LangGraph · CrewAI]
│
│  deployed to
▼
Amazon Bedrock AgentCore Runtime  [Bearer token via Cognito OAuth 2.0]
│  auth · session isolation · auto-scaling · observability
│
│  invokes container
▼
Agent container  [ARM64 · port 8080]
│  FastAPI · /invocations · /ping
│
│  calls model
▼
Amazon Bedrock model
│
│  streams back via
▼
AG-UI protocol  [SSE event stream]
│
│  consumed by
▼
CopilotKit  [HttpAgent · @ag-ui/client]
│
├─  renders streaming responses + tool progress
├─  syncs state updates in real time
└─  forwards user messages → agent via AG-UI
▼
Your application UI
Enter fullscreen mode Exit fullscreen mode

complete architecture diagram

If you want a complete full-stack starting point, AWS also released the Fullstack AgentCore Solution Template - a ready-made stack with AgentCore, LangGraph, CopilotKit and AG-UI all wired together, deployed via CDK. It's the fastest way to go from zero to a production-ready agentic app on AWS.


Deploying your AG-UI agent with Strands

This example uses AWS Strands as the agent framework but the same pattern works with LangGraph, CrewAI and any other AG-UI-compatible framework.

Before deploying, make sure you have:

  • Python 3.12+
  • AWS account with credentials configured (aws configure)
  • IAM permissions for AgentCore Runtime
  • Docker, Finch, or Podman for building container images
  • Amazon Cognito user pool configured (Setup guide here)

Start by installing the required packages:

pip install fastapi uvicorn ag_ui_strands strands-agents boto3
Enter fullscreen mode Exit fullscreen mode
  • ag_ui_strands wraps your Strands agent with AG-UI protocol support, handling event encoding automatically.
  • strands-agents is the AWS agent framework used in this example.
  • boto3 is the AWS SDK, used internally by Strands to call Bedrock models.

Step 1: Build your AG-UI server

Create my_agui_server.py. This defines the model, wraps the agent with AG-UI support, and exposes the endpoints AgentCore needs.

import uvicorn
from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse, JSONResponse
from ag_ui_strands import StrandsAgent
from ag_ui.core import RunAgentInput
from ag_ui.encoder import EventEncoder
from strands import Agent
from strands.models.bedrock import BedrockModel

model = BedrockModel(
    model_id="us.anthropic.claude-3-5-sonnet-20241022-v2:0",
    region_name="us-west-2",
)

strands_agent = Agent(
    model=model,
    system_prompt="You are a helpful assistant.",
)

agui_agent = StrandsAgent(
    agent=strands_agent,
    name="my_agent",
    description="A helpful assistant",
)

app = FastAPI()

@app.post("/invocations")
async def invocations(input_data: dict, request: Request):
    accept_header = request.headers.get("accept")
    encoder = EventEncoder(accept=accept_header)

    async def event_generator():
        run_input = RunAgentInput(**input_data)
        async for event in agui_agent.run(run_input):
            yield encoder.encode(event)

    return StreamingResponse(
        event_generator(),
        media_type=encoder.get_content_type()
    )

@app.get("/ping")
async def ping():
    return JSONResponse({"status": "Healthy"})

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8080)
Enter fullscreen mode Exit fullscreen mode

Here, StrandsAgent wraps your Strands agent and handles all AG-UI event encoding so you don't write any protocol logic yourself.

AgentCore requires three things from your container:

  • POST /invocations - handles AG-UI requests, returns the SSE event stream.
  • GET /ping - health check, must return HTTP 200.
  • Port 8080 - required, do not change.

For LangGraph, CrewAI, and other frameworks, see the AG-UI framework integrations.

Step 2: Test locally

Start your server.

python my_agui_server.py
Enter fullscreen mode Exit fullscreen mode

The server starts on http://localhost:8080. Send a test request to confirm the SSE stream is working before deploying.

curl -N -X POST http://localhost:8080/invocations \
  -H "Content-Type: application/json" \
  -d '{
    "thread_id": "test-123",
    "run_id": "run-456",
    "state": {},
    "messages": [{"role": "user", "content": "Hello!", "id": "msg-1"}],
    "tools": [], "context": [], "forwardedProps": {}
  }'
Enter fullscreen mode Exit fullscreen mode

You should see the SSE events stream back:

data: {"type": "RUN_STARTED", "threadId": "test-123", "runId": "run-456"}
data: {"type": "TEXT_MESSAGE_START", "messageId": "msg-abc", "role": "assistant"}
data: {"type": "TEXT_MESSAGE_CONTENT", "messageId": "msg-abc", "delta": "Hello!"}
data: {"type": "TEXT_MESSAGE_END", "messageId": "msg-abc"}
data: {"type": "RUN_FINISHED", "threadId": "test-123", "runId": "run-456"}
Enter fullscreen mode Exit fullscreen mode

Step 3: Deploy to AgentCore

The AgentCore starter toolkit handles the entire deployment process for you.

It builds an ARM64 container image, pushes it to Amazon ECR, and creates the AgentCore runtime with protocol flag serverProtocol: "AGUI". You don't write a Dockerfile or configure any infrastructure manually.

Install it first:

pip install bedrock-agentcore-starter-toolkit
Enter fullscreen mode Exit fullscreen mode

Create a requirements.txt so the toolkit knows what to install in the container:

fastapi 
uvicorn 
ag_ui_strands
Enter fullscreen mode Exit fullscreen mode

Now configure and deploy. The configure command sets the protocol to AG-UI and links your Cognito auth setup. The deploy command does the rest:

# Configure with AG-UI protocol + OAuth authentication
agentcore configure -e my_agui_server.py --protocol AGUI

# Deploy to AWS
agentcore deploy
Enter fullscreen mode Exit fullscreen mode

agentcore deploy

After a successful deploy, you receive an agent runtime ARN. You will need this to invoke the agent and connect your frontend.

arn:aws:bedrock-agentcore:us-west-2:ACCOUNT_ID:runtime/my_agui_server-xyz123
Enter fullscreen mode Exit fullscreen mode

AWS AgentCore Console

Step 4: Invoke your deployed agent

With the agent running on AgentCore, you can now invoke it and stream AG-UI events over the wire. Set your environment variables first:

export BEARER_TOKEN="<your-cognito-bearer-token>"
export AGENT_ARN="arn:aws:bedrock-agentcore:us-west-2:ACCOUNT_ID:runtime/my_agui_server-xyz123"
Enter fullscreen mode Exit fullscreen mode

Install the HTTP client libraries for making SSE requests:

pip install httpx httpx-sse
Enter fullscreen mode Exit fullscreen mode

Then invoke the agent:

import asyncio
import json
import os
from urllib.parse import quote
from uuid import uuid4

import httpx
from httpx_sse import aconnect_sse

async def invoke_agui_agent(message: str):
    agent_arn = os.environ.get('AGENT_ARN')
    bearer_token = os.environ.get('BEARER_TOKEN')
    escaped_arn = quote(agent_arn, safe='')

    url = f"https://bedrock-agentcore.us-west-2.amazonaws.com/runtimes/{escaped_arn}/invocations?qualifier=DEFAULT"
    headers = {
        "Authorization": f"Bearer {bearer_token}",
        "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id": str(uuid4()),
    }
    payload = {
        "threadId": str(uuid4()),
        "runId": str(uuid4()),
        "messages": [{"id": str(uuid4()), "role": "user", "content": message}],
        "state": {},
        "tools": [],
        "context": [],
        "forwardedProps": {},
    }

    async with httpx.AsyncClient(timeout=300) as client:
        async with aconnect_sse(client, "POST", url, headers=headers, json=payload) as sse:
            async for event in sse.aiter_sse():
                data = json.loads(event.data)
                event_type = data.get("type")
                if event_type == "TEXT_MESSAGE_CONTENT":
                    print(data.get("delta", ""), end="", flush=True)
                elif event_type == "RUN_ERROR":
                    print(f"Error: {data.get('code')} - {data.get('message')}")

asyncio.run(invoke_agui_agent("Hello from production!"))
Enter fullscreen mode Exit fullscreen mode

You should see the agent's response stream token by token.

agent response stream

The same AG-UI events as local testing, now served from AgentCore with managed authentication, session isolation, and auto-scaling.

Step 5: Connect your frontend

With the agent deployed, point HttpAgent from @ag-ui/client at the AgentCore invocation URL instead of localhost. The rest of the client code stays the same.

This is the same AG-UI client used locally - you are just pointing it at the AgentCore URL instead of localhost.

import { HttpAgent } from "@ag-ui/client";

const agent = new HttpAgent({
  url: `https://bedrock-agentcore.us-west-2.amazonaws.com/runtimes/${encodedArn}/invocations?qualifier=DEFAULT`,
  headers: {
    "Authorization": `Bearer ${token}`,
    "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id": sessionId,
  }
});
Enter fullscreen mode Exit fullscreen mode

For SigV4 authentication, sign requests using the AWS SDK. For OAuth 2.0, obtain a token from your configured Cognito user pool. Authentication configuration is the same across all AgentCore protocols. See the AgentCore auth docs for setup.

AG-UI support in AgentCore is available today across 14 AWS regions.


Resources

You can start building right away.

If you want a complete full-stack starting point, AWS also released the Fullstack AgentCore Solution Template - AgentCore, LangGraph, CopilotKit, and AG-UI all wired together and deployed via CDK.


What This Means

AG-UI works with LangGraph, CrewAI, AWS Strands, Google ADK, Mastra, Microsoft Agent Framework, LlamaIndex, Agno, and more. The protocol itself isn't tied to any of them - you pick the framework, AG-UI handles the interaction layer.

What was missing was a managed way to run these agents in production. That's what this support adds.

Beyond AG-UI hosting, AgentCore also covers persistent memory across sessions, tool connectivity via MCP Gateway, and production observability (though I didn't explore all of these in-depth).

thanks for reading!

You can connect me on GitHub, Twitter and LinkedIn.

Follow CopilotKit on Twitter and say hi, and if you'd like to build something cool, join the Discord community.

Top comments (0)