All Four AgentCore Protocols Are Just HTTP: What AG-UI, MCP, and A2A Actually Do
4th April 2026
A question that comes up once you understand how AG-UI works: isn’t this just HTTP streaming with a defined event format? Could you achieve the same thing with the HTTP protocol if you defined the same output structure?
The short answer: yes. And that’s the point.
The Proof
Here’s the same agent output using HTTP streaming with your own format vs AG-UI:
HTTP streaming (you define the format):
POST /invocations → yield {"type": "TEXT_MESSAGE_CONTENT", "delta": "Hi"}
↑ YOU define this format
AGUI:
POST /invocations → yield {"type": "TEXT_MESSAGE_CONTENT", "delta": "Hi"}
↑ ag-ui-strands defines this format for you
Same wire format. Same SSE. Same bytes on the wire. Both are POST → text/event-stream with JSON payloads. AG-UI doesn’t introduce a new transport, a new connection type, or any networking magic. It’s HTTP streaming all the way down.
What AG-UI Actually Is
AG-UI is three things:
- A naming convention — "let’s all call it
TEXT_MESSAGE_CONTENTinstead ofchunkordeltaortoken" - A library —
ag-ui-strandsauto-generates those events from Strands agent internals (intercepts tool calls, extracts state) so you don’t write the yield statements manually - An ecosystem agreement — if your agent emits these 12 event types, any AG-UI-compatible frontend works with it
It’s not a transport protocol. It’s a convention protocol — the same way REST, GraphQL, and JSON-RPC are convention protocols.
| “Protocol” | Is it a transport? | What is it really? |
|---|---|---|
| HTTP | Yes | Application-layer transport |
| REST | No | Conventions on top of HTTP |
| GraphQL | No | Query language on top of HTTP POST |
| JSON-RPC | No | Message format on top of HTTP |
| AG-UI | No | Event format on top of HTTP SSE or WebSocket |
AG-UI is to agent streaming what REST is to web APIs: “if you follow these conventions, my client will understand you.”
What You’d Build Yourself with HTTP
If you chose the HTTP protocol and wanted the same UI experience as AG-UI, you’d write approximately this:
@app.entrypoint
async def handler(payload):
# YOU manually emit lifecycle events:
yield {"type": "RUN_STARTED", ...}
# YOU intercept every agent event and categorize it:
for event in agent.stream(msg):
if event is text:
yield {"type": "TEXT_MESSAGE_CONTENT", ...}
elif event is tool_start:
yield {"type": "TOOL_CALL_START", ...}
elif event is tool_args:
yield {"type": "TOOL_CALL_ARGS", ...}
elif event is tool_end:
# YOU extract state from tool args:
if tool_name == "update_document":
state = extract_state(tool_args)
yield {"type": "STATE_SNAPSHOT", ...}
yield {"type": "RUN_FINISHED", ...}
With AG-UI (ag-ui-strands), this is automatic:
agui_agent = StrandsAgent(agent=agent, config=StrandsAgentConfig(
tool_behaviors={"update_document": ToolBehavior(state_from_args=...)}
))
# One line — all 12 event types emitted automatically
async for event in agui_agent.run(input):
yield event
~100 lines of manual event mapping vs ~5 lines of config. Both produce identical wire output.
The Real Value: Interoperability
Without AG-UI, every framework invents its own streaming format:
Your agent: {"chunk": "Hello"}
LangGraph: {"event": "on_chat_model_stream", "data": {"chunk": ...}}
OpenAI: {"choices": [{"delta": {"content": "Hello"}}]}
Bedrock: {"contentBlockDelta": {"delta": {"text": "Hello"}}}
Frontend: needs 4 different parsers
With AG-UI:
Your agent: {"type": "TEXT_MESSAGE_CONTENT", "delta": "Hello"}
LangGraph: {"type": "TEXT_MESSAGE_CONTENT", "delta": "Hello"}
Strands: {"type": "TEXT_MESSAGE_CONTENT", "delta": "Hello"}
CrewAI: {"type": "TEXT_MESSAGE_CONTENT", "delta": "Hello"}
Frontend: one parser works for all
Nine frameworks have adopted the same event format:
| Framework | AG-UI Adapter |
|---|---|
| LangGraph | ag-ui-langgraph |
| CrewAI | ag-ui-crewai |
| AWS Strands | ag-ui-strands |
| Google ADK | ag-ui-adk |
| Mastra | ag-ui-mastra |
| Pydantic AI | ag-ui-pydantic-ai |
| LlamaIndex | ag-ui-llamaindex |
| AG2 (AutoGen) | ag-ui-ag2 |
| Microsoft AF | ag-ui-microsoft-af |
Build a frontend that parses AG-UI events and it works with all nine. Invent your own HTTP streaming format and it works with only yours.
The Honest Verdict
| What AG-UI gives you | Can you build this with HTTP? |
|---|---|
| 12 typed events (TEXT_MESSAGE_*, TOOL_CALL_*, STATE_SNAPSHOT) | Yes — define the same JSON yourself |
| Auto-extraction of state from tool calls | Yes — write the extraction logic yourself |
| Tool call interception and streaming | Yes — intercept agent events manually |
| WebSocket transport option | Yes — add a /ws endpoint yourself |
| Frontend interop with other frameworks | No — your custom format won’t match LangGraph’s or CrewAI’s |
| ag-ui-strands doing it all in ~5 lines | No — you write ~100 lines of event mapping |
| CopilotKit React components out of the box | No — CopilotKit expects AG-UI events |
When You Should NOT Use AG-UI
- One agent, one frontend, one team — define your own JSON format. It’s simpler and you control everything.
- Backend-only agent (no UI) — use HTTP or A2A. AG-UI is designed for humans watching screens.
- Simple request/response, no streaming needed — HTTP returning JSON is fine.
- Internal tool with no framework migration plans — the interop benefit doesn’t apply.
When AG-UI Actually Helps
- You might switch frameworks — today Strands, tomorrow LangGraph. The frontend stays the same.
- Multiple agents, one UI — your UI talks to 3 different agent backends, all speaking AG-UI.
- You use CopilotKit — AG-UI was created by CopilotKit. Their React components (
@copilotkit/react-core) parse AG-UI events natively. You get a full agent UI for free. - You want the ecosystem — AG-UI Dojo has live demos for every framework. You can compare how Strands vs LangGraph vs CrewAI handle the same interactions.
- You don’t want to write event mapping code —
ag-ui-strandshandles tool interception, state extraction, message grouping, and lifecycle events automatically.
It’s Not Just AG-UI — All Four AgentCore Protocols Are HTTP
This observation extends beyond AG-UI. We inspected the actual AgentCore SDK source code for all four protocols. Here’s what each one produces:
ALL FOUR PROTOCOLS ON AGENTCORE:
HTTP MCP A2A AGUI
──── ─── ─── ────
App base: Starlette Starlette Starlette Starlette
Container: port 8080 port 8080 port 8080 port 8080
Network: TCP+TLS TCP+TLS TCP+TLS TCP+TLS
Transport: HTTP POST HTTP POST HTTP POST HTTP POST
Streaming: SSE SSE SSE SSE
Wire format: data:{}\n\n data:{}\n\n data:{}\n\n data:{}\n\n
Same Starlette app. Same port. Same TLS. Same SSE framing. The only difference is what JSON sits inside the data: line:
HTTP: {"anything": "you define"}
MCP: {"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {"name": "search", "arguments": {"q": "..."}}}
A2A: {"jsonrpc": "2.0", "id": 1, "result":
{"id": "task-1", "status": {"state": "working",
"message": {"parts": [{"text": "Searching..."}]}}}}
AGUI: {"type": "TEXT_MESSAGE_CONTENT", "messageId": "abc",
"delta": "Hello"}
MCP and A2A are even more similar to each other than to AGUI — both use the JSON-RPC envelope ({"jsonrpc": "2.0", "method": "...", "params": {...}}). The only difference between them is the method names: MCP uses tools/list and tools/call; A2A uses tasks/send and tasks/get.
What serverProtocol Actually Does
We checked what happens when you set the protocol in AgentCore’s starter toolkit:
ProtocolConfiguration(server_protocol="HTTP").to_aws_dict() → {"serverProtocol": "HTTP"}
ProtocolConfiguration(server_protocol="MCP").to_aws_dict() → {"serverProtocol": "MCP"}
ProtocolConfiguration(server_protocol="A2A").to_aws_dict() → {"serverProtocol": "A2A"}
ProtocolConfiguration(server_protocol="AGUI").to_aws_dict() → {"serverProtocol": "AGUI"}
It’s a label. AgentCore doesn’t parse your events, doesn’t validate the format, and doesn’t change routing based on the protocol value. It proxies POST /invocations to your container and streams back whatever bytes you return. The label shows up in the console and CloudWatch for observability — that’s it.
You could set serverProtocol: HTTP and manually emit JSON-RPC tasks/send responses — it would work as an A2A agent. You could set serverProtocol: HTTP and yield AG-UI events — it would work as an AGUI frontend. The label doesn’t enforce anything.
Four JSON Vocabularies, Not Four Transports
The four “protocols” are really four JSON vocabularies, each designed for a different conversation:
HTTP: "I define my own language."
→ No vocabulary constraints. You speak however you want.
MCP: "I speak JSON-RPC with tool/resource/prompt vocabulary."
→ Designed for: AI system asking "what tools do you have?"
→ The Strands Agent brain is NOT used — raw tools exposed.
A2A: "I speak JSON-RPC with task lifecycle vocabulary."
→ Designed for: Agent A asking Agent B "do this job."
→ The Strands Agent brain IS used — wrapped as a task worker.
AGUI: "I speak 12 typed events for human UI."
→ Designed for: browser rendering streaming text + tool cards + state.
→ The Strands Agent brain IS used — events auto-generated by library.
The infrastructure is identical. The JSON is different. The audience is different. Each “protocol” is really a library plus a convention that saves you from reinventing the JSON format and parsing logic yourself.
The Bottom Line
AG-UI is not magic. It’s HTTP streaming with a defined event format. MCP is HTTP with JSON-RPC and tool vocabulary. A2A is HTTP with JSON-RPC and task vocabulary. You could build any of them yourself with the HTTP protocol and the right JSON output.
The value proposition is the same as REST, GraphQL, or JSON itself: everyone agreed on the format, so everything interoperates. Whether that’s worth it depends on whether you care about framework interoperability. If you’re building one agent with one frontend, HTTP streaming with your own format is perfectly fine. If you’re building a platform that connects to multiple agent frameworks, the shared vocabulary saves you from writing separate parsers for each one.
The protocol label isn’t about technical complexity — it’s about ecosystem agreement. And right now, nine major frameworks have agreed on AG-UI, the MCP ecosystem is growing rapidly, and A2A has Google and AWS behind it. The conventions are winning not because they do something HTTP can’t, but because they do something HTTP alone doesn’t: make everyone speak the same language.
More recent articles
- HTTP vs MCP vs A2A vs AG-UI: The Four Protocols of AgentCore Runtime - 4th April 2026
- AG-UI Protocol: A Layer-by-Layer Deep Dive with Real Network Captures - 4th April 2026