# Ag2 Ag UI

> Expose an AG2 `Agent` over the AG-UI protocol so a frontend (CopilotKit, custom React/Next.js, or any AG-UI client) can stream responses (text and reasoning), render tool calls, sync shared state, and track sub-task steps. Wraps the agent with `AGUIStream(agent)` and mounts it in FastAPI via `stream.dispatch(...)` or `stream.build_asgi()`. Use when the user wants a web frontend in front of an AG2 agent rather than a CLI / script.

- Skill: `ag2ai/ag2-ag-ui` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ag2ai/ag2-ag-ui`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ag2ai/ag2-ag-ui/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- License: Apache-2.0
- Author: ag2ai (https://skillmd.com/u/ag2ai)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/ag2ai/ag2-ag-ui

---


# AG-UI integration

## When to use

- The user is building a web UI (React / Next.js / anything HTTP+SSE) that should talk to an AG2 agent.
- They want streaming text, reasoning, tool-call rendering, shared state sync, or sub-task step tracking surfaced to the frontend with a standard protocol — not a custom REST/WebSocket contract.
- They're using or considering CopilotKit (the recommended React client).

For a custom narrow-purpose API where you own the contract end-to-end, skip AG-UI and write a plain endpoint instead.

## Supported AG-UI features

| Feature | Status |
|---|---|
| Run lifecycle (`RUN_STARTED` / `RUN_FINISHED` / `RUN_ERROR`) | ✓ |
| Streaming text events (`TEXT_MESSAGE_START` / `_CONTENT` / `_END` / `_CHUNK`) | ✓ |
| Reasoning events (`REASONING_START` / `_END`, `REASONING_MESSAGE_START` / `_CONTENT` / `_END`) | ✓ |
| Backend tool lifecycle (`TOOL_CALL_START` / `_ARGS` / `_RESULT` / `_END`) | ✓ |
| Frontend-tool dispatch (`TOOL_CALL_CHUNK` for client tools in `RunAgentInput.tools`) | ✓ |
| Shared-state snapshots (`STATE_SNAPSHOT`) | ✓ |
| Sub-task steps (`STEP_STARTED` / `STEP_FINISHED`, emitted on `TaskStarted` / `TaskCompleted`) | ✓ |
| Human input checkpoints surfaced as AG-UI events | ✗ — no human-input event family; `hitl_hook` passes through to `agent.ask` |

## Installation

```bash
pip install "ag2[ag-ui]"
```

> Required. Run this install before delivering the code. If you cannot run commands, state the exact `pip install` command.

## 60-second recipe — FastAPI server

```python title="run_ag_ui.py"
from fastapi import FastAPI, Header
from fastapi.responses import StreamingResponse

from ag2 import Agent
from ag2.ag_ui import AGUIStream, RunAgentInput
from ag2.config import OpenAIConfig

agent = Agent(
    name="support_bot",
    prompt="You help users with billing questions.",
    config=OpenAIConfig(model="gpt-4o-mini"),
)

stream = AGUIStream(agent)
app = FastAPI()

@app.post("/chat")
async def run_agent(message: RunAgentInput, accept: str | None = Header(None)) -> StreamingResponse:
    return StreamingResponse(
        stream.dispatch(message, accept=accept),
        media_type=accept or "text/event-stream",
    )
```

```bash
uvicorn run_ag_ui:app --reload --port 8000
```

Test:

```bash
curl -N -X POST http://127.0.0.1:8000/chat \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{"thread_id":"t1","run_id":"r1","messages":[{"id":"m1","role":"user","content":"Hello"}],"state":{},"context":[],"tools":[]}'
```

## Lower-friction alternative — `build_asgi()`

If you don't need custom auth / middleware, mount the ASGI endpoint directly:

```python
from ag2.ag_ui import AGUIStream
from fastapi import FastAPI

app = FastAPI()
stream = AGUIStream(agent)
app.mount("/chat", stream.build_asgi())
```

## CopilotKit frontend (recommended for React / Next.js)

Two ways to start:

```bash
# Option A — CopilotKit bootstrap
npx copilotkit@latest create -f ag2

# Option B — clone the reference starter
# https://github.com/ag2ai/ag2-copilotkit-starter
```

The starter layout:

```
ag2-copilotkit-starter/
├── agent-py/     # Python backend (AG2 + AG-UI)
└── ui-react/     # React + CopilotKit frontend
```

Backend serves `/chat` on port 8008 by default. The Next.js route at `ui-react/app/api/copilotkit/route.ts` bridges the UI to the backend:

```tsx
import { HttpAgent } from "@ag-ui/client";
import { CopilotRuntime, ExperimentalEmptyAdapter, copilotRuntimeNextJSAppRouterEndpoint } from "@copilotkit/runtime";
import { NextRequest } from "next/server";

const agent = new HttpAgent({ url: "http://localhost:8008/chat" });
const runtime = new CopilotRuntime({ agents: { weather_agent: agent } });

export async function POST(req: NextRequest) {
  const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({
    runtime,
    serviceAdapter: new ExperimentalEmptyAdapter(),
    endpoint: "/api/copilotkit",
  });
  return handleRequest(req);
}
```

Wrap your app:

```tsx
import { CopilotKit } from "@copilotkit/react-core";
import "@copilotkit/react-ui/styles.css";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <CopilotKit agent="weather_agent" runtimeUrl="/api/copilotkit">
          {children}
        </CopilotKit>
      </body>
    </html>
  );
}
```

Render chat (`<CopilotChat />`), and use `useCopilotAction({...})` in client components to render generative UI tied to backend tool calls.

## Production checklist

- **CORS** — allow your frontend origin on the AG-UI backend (`POST`, `OPTIONS`, auth headers).
- **Auth** — protect both `/api/copilotkit` (Next.js route) and backend `/chat`. Don't rely on client-only secrets.
- **SSE buffering** — verify backend response is `Content-Type: text/event-stream` and that proxy layers (Nginx, CloudFront, etc.) don't buffer SSE.
- **Timeouts / retries** — conservative values for long-running tool workflows; only retry idempotent requests.
- **Tool inputs are untrusted** — validate and authorize server-side before invoking privileged tools. Log tool execution with request IDs.
- **Tool name parity** — frontend `useCopilotAction` `name` must match backend `@tool` name exactly.

## Going deeper

- `website/docs/user-guide/ag-ui/index.mdx` — `AGUIStream`, supported events, basic server.
- `website/docs/user-guide/ag-ui/copilotkit-quickstart.mdx` — full React + CopilotKit walkthrough (file layout, route, layout, chat component, weather-card example).
- AG-UI protocol: https://docs.ag-ui.com/introduction
- Reference starter: https://github.com/ag2ai/ag2-copilotkit-starter
- For protocol-level testing: AG2 Dojo profile https://dojo.ag-ui.com/ag2/feature/agentic_chat

## Common pitfalls

- **Missing `ag-ui` extra** — `pip install "ag2[ag-ui]"` is required; without it `from ag2.ag_ui import AGUIStream` will fail.
- **CORS blocked** — frontend can't hit the backend in dev. Add `CORSMiddleware` to the FastAPI app for the dev origin.
- **No streaming output** — proxy or `Content-Type` issue. Test with raw `curl -N` first to isolate.
- **Tool UI not rendering** — tool name on the React side (`useCopilotAction({ name: "..." })`) doesn't exactly match the backend `@tool` name.
- **Putting the endpoint behind a SSE-incompatible proxy** — many proxies buffer event-stream responses by default. Disable buffering on the route.
- **Trying to use `AGUIStream` with classic `ConversableAgent`** — the description here covers `ag2.Agent`. Classic AG2 agents can be exposed differently; check the AG2 docs for that path.

