agentclientprotocol.com → docs.ag-ui.com
A reference bridge that gives any ACP coding agent (Kiro, Claude, Codex, etc.) a web UI via the AG-UI protocol.
Left: Kiro CLI powering the workspace. Right: same UI with Claude Code. Just swap the agent.
Select your agent from the frontend. No restart needed. Each session spawns the chosen binary.
There are now 33+ coding agents that support the Agent Client Protocol (ACP): Kiro, Claude Code, Codex CLI, Cursor, Gemini CLI, GitHub Copilot, OpenCode, Cline, and many more. They all speak JSON-RPC 2.0 over stdio. You can use them in terminals. You can use them in editors.
But teams keep needing purpose-built web interfaces on top of these agents: a micro-app creation platform where non-engineers iterate on device experiences, a report generation UI where analysts interact with agents without learning CLI commands, deployment dashboards with team-visible approval flows, domain-specific editors powered by an agent underneath.
Today, building any of these means implementing the protocol bridge yourself: parsing JSON-RPC streams, managing subprocesses, translating events into something a web frontend can render.
This project is a reference bridge that sits between any ACP agent and any web frontend:
graph TB
subgraph agents["ACP Agents (33+)"]
A1["kiro-cli"] ~~~ A2["claude-agent-acp"] ~~~ A3["codex"] ~~~ A4["gemini cli"] ~~~ A5["cursor"] ~~~ A6["ANY ACP binary"]
end
agents <-->|"JSON-RPC 2.0 over stdio"| bridge
subgraph bridge["This Bridge (Python / FastAPI)"]
B1["AgentRunner"] ~~~ B2["AcpToAguiBridge"] ~~~ B3["SessionManager"]
end
bridge -->|"AG-UI Events over SSE"| frontends
subgraph frontends["Your Frontend"]
F1["Reference UI"] ~~~ F2["CopilotKit"] ~~~ F3["AG-UI HttpAgent"] ~~~ F4["Anything"]
end
style agents fill:#1e3a5f,stroke:#60a5fa,color:#fff
style bridge fill:#3b1f6e,stroke:#a78bfa,color:#fff
style frontends fill:#1a4731,stroke:#6ee7b7,color:#fff
Clone this repo, select your agent, and you have a working web UI with streaming chat, tool visualization, and human-in-the-loop approvals.
Same agent underneath. Different frontend for each audience:
- Micro-app creation platforms: non-engineers iterating on apps through a web workspace
- Report generation: analysts interacting with agents without CLI commands
- Deployment dashboards: team-visible approval flows for infrastructure changes
- Domain-specific IDEs: focused editors (config, pipelines) powered by an agent
- Any internal tooling: the agent does the heavy lifting, users get a tailored UI
AG-UI (Agent-User Interaction Protocol) is the open standard for connecting AI agents to frontends. Instead of rolling your own SSE/WebSocket protocol, you get:
- ~16 standard event types: streaming chat, tool calls, state sync, generative UI, interrupts
- Transport agnostic: works over SSE, WebSockets, or webhooks
- Rich ecosystem: supported by CopilotKit, LangGraph, Google ADK, AWS Strands, Pydantic AI, and 20+ frameworks
- Frontend SDKs: TypeScript, Python, Kotlin, Go, Rust, and more
- Human-in-the-loop built in: pause, approve, reject, or redirect agent execution mid-flow
By emitting AG-UI events, your frontend becomes portable across the entire agent ecosystem. See docs/why-agui.md for a deep dive on what this unlocks: CopilotKit integration, shared state, generative UI, and more.
Works on macOS, Linux, and Windows (PowerShell or cmd). Prereqs: Python 3.11+, Node.js 18+, pnpm.
git clone https://github.com/namanrajpal/acp-to-agui.git
cd acp-to-agui
pnpm install
pnpm devOpen http://localhost:3000. Select your agent (Kiro, Claude, Codex, or OpenCode), enter a project path, and start chatting. The bridge spawns the agent subprocess, translates its output to AG-UI events, and streams them to the React frontend.
Prefer side-by-side logs? Run each half in its own terminal:
pnpm dev:backend # FastAPI on :8000
pnpm dev:ui # Vite on :3000Both commands run identically on every platform. The launcher resolves PYTHONPATH to the repo root, so you can run them from any working directory.
Platform notes
- macOS / Linux:
pnpm dev:backendruns uvicorn with--reload, so Python edits hot-reload automatically. - Windows:
--reloadis skipped automatically because uvicorn's reload supervisor installs an asyncio event loop policy that can't spawn subprocesses (you'd hitNotImplementedErrorfrom_make_subprocess_transportthe moment you tried to start a session). Restartpnpm dev:backendmanually after backend edits. The Vite frontend hot-reloads everywhere. - Windows + non-
.exeagents (npx,claude-agent-acp, etc.): the bridge auto-wraps.cmd/.batshims withcmd.exe /cso you can use the sameagentCommandconfig as on Unix. Native.exeagents likekiro-clipass through unchanged.
There are two ways to select an agent:
The workspace UI has an agent toggle on the project selector page. Pick Kiro, Claude, Codex, or OpenCode. the selected agent command is sent with the session creation request and the backend spawns that specific binary.
This means you can switch agents between sessions without restarting anything.
The config file sets the fallback agent when no command is specified per-session:
{
"projectName": "acp-to-agui",
"displayTitle": "ACP → AG-UI Bridge",
"agentCommand": ["kiro-cli", "acp"],
"backendPort": 8000,
"corsOrigins": ["http://localhost:3000", "http://localhost:3001"]
}| Agent | Command | Auth |
|---|---|---|
| Kiro CLI | ["kiro-cli", "acp"] |
AWS Builder ID |
| Claude Agent | ["claude-agent-acp"] |
ANTHROPIC_API_KEY |
| Codex CLI | ["codex-acp"] |
ChatGPT subscription or API key |
| OpenCode | ["opencode", "acp"] |
OpenCode Zen or provider API key |
| Gemini CLI | ["gemini", "cli", "acp"] |
Google auth |
| Cursor | ["cursor", "--acp"] |
Cursor subscription |
| GitHub Copilot | ["github-copilot-cli", "--acp"] |
GitHub auth |
| Goose | ["goose", "--acp"] |
Provider API key |
| Any ACP binary | ["your-agent", "acp"] |
Varies |
You can also pass agentCommand directly when creating a session via REST:
curl -X POST http://localhost:8000/v2/tasks \
-H "Content-Type: application/json" \
-d '{"cwd": "/your/project", "agentCommand": ["claude-agent-acp"]}'graph TB
subgraph frontend["React Frontend (Vite)"]
direction LR
CP["ChatPanel"]
AD["ApprovalDialog"]
TC["ToolCard"]
SS["SessionSidebar"]
end
frontend -->|"SSE stream + REST"| backend
subgraph backend["Python Backend (FastAPI)"]
SM["SessionManager"]
BR["AcpToAguiBridge"]
ST["SessionStore"]
AR["AgentRunner"]
PE["PolicyEngine"]
API["REST APIs"]
SM --> AR
SM --> BR
SM --> ST
BR --> PE
end
AR <-->|"JSON-RPC 2.0 / stdio"| agent
subgraph agent["ACP Agent (subprocess)"]
AG["kiro-cli / claude-agent-acp / any"]
end
style frontend fill:#1a4731,stroke:#6ee7b7,color:#fff
style backend fill:#3b1f6e,stroke:#a78bfa,color:#fff
style agent fill:#1e3a5f,stroke:#60a5fa,color:#fff
| ACP Event | AG-UI Event(s) | Notes |
|---|---|---|
agent_message_chunk |
TEXT_MESSAGE_START + TEXT_MESSAGE_CONTENT |
Opens message on first chunk |
tool_call |
TOOL_CALL_START + TOOL_CALL_ARGS |
Closes open text message first |
tool_call_update |
TOOL_CALL_ARGS or TOOL_CALL_END |
Based on status field |
turn_end |
TEXT_MESSAGE_END + TOOL_CALL_END(s) + RUN_FINISHED |
Closes everything |
session/request_permission |
STATE_UPDATE (approval pending) |
Uses asyncio.Future for async bridge |
Vendor extensions (_*.dev/*) |
CUSTOM events |
Normalized to agent:* namespace |
See docs/protocol-translation.md for the full mapping with diagrams.
ACP and AG-UI do not map one-to-one. These required a normalization layer:
Tool Approvals: ACP's SDK calls request_permission() and blocks waiting for a return value. But our approval comes asynchronously from a REST endpoint. We bridge this with asyncio.Future: the SDK callback awaits the future, the REST endpoint resolves it.
Message Boundaries: ACP streams agent_message_chunk continuously. AG-UI needs explicit TEXT_MESSAGE_START and TEXT_MESSAGE_END events. The bridge tracks open message state and auto-closes before tool calls or turn end.
Vendor Extensions: ACP agents send custom notifications (e.g., _kiro.dev/mcp_servers_ready). The SDK routes these to ext_notification(). We normalize them into CUSTOM AG-UI events with a clean agent:* namespace.
| Approach | How it consumes AG-UI | Lines of Code | Use When |
|---|---|---|---|
Custom Workspace (example-frontends/custom-workspace-ui-demo/) |
Direct REST + raw SSE parsing | ~2000 | You want full control over every pixel |
CopilotKit (example-frontends/copilotkit-demo/) |
AG-UI via framework (zero UI code) | ~20 | You want to ship fast with production features |
AG-UI HttpAgent (example-frontends/httpagent-demo/) |
AG-UI via client library (you build UI) | ~50 | You want the raw protocol with your own UI framework |
- Select an agent. via the UI toggle, the
agentCommandAPI field, or thebridge.config.jsondefault - Create a session:
POST /v2/tasksspawns the agent subprocess, initializes ACP - Start a run:
POST /v2/tasks/{id}/runsends your prompt via JSON-RPC - Stream events:
GET /v2/tasks/{id}/events?runId=...returns AG-UI SSE stream - Or use the standard endpoint:
POST /ag-ui(what CopilotKit and AG-UI HttpAgent use) - Handle approvals:
POST /v2/tasks/{id}/approvalresolves pending tool permissions
Project Structure
├── backend/ # Python FastAPI (the bridge)
│ ├── agent/ # ACP SDK integration (spawn + protocol)
│ ├── bridge/ # ACP → AG-UI event translation
│ ├── agui/ # AG-UI event types + SSE encoding
│ ├── sessions/ # Session lifecycle, store, routes
│ ├── policy/ # Tool approval engine
│ ├── api/ # Side-channel REST (files, git)
│ └── agui_endpoint.py # POST /ag-ui (AG-UI standard endpoint)
├── example-frontends/
│ ├── custom-workspace-ui-demo/ # Full workspace UI (React + Vite + Tailwind)
│ ├── copilotkit-demo/ # CopilotKit in 20 lines
│ ├── httpagent-demo/ # Raw @ag-ui/client AG-UI HttpAgent
│ └── agents.md # Agent configuration guide
├── docs/
│ ├── architecture.md # Detailed system design
│ ├── integration-contract.md # REST + SSE API spec
│ ├── protocol-translation.md # Full ACP ↔ AG-UI mapping
│ └── why-agui.md # AG-UI ecosystem benefits
├── bridge.config.json # Your agent configuration
└── package.json # Workspace orchestrator
| Agent | Version | Status | Notes |
|---|---|---|---|
| Kiro CLI | 2.3.0 | ✅ Working | 13 modes, extension notifications, full streaming |
| Claude Agent (claude-agent-acp) | 0.36.1 | ✅ Working | 5 modes, prompt queueing, embedded context |
| Codex CLI (codex-acp) | 0.14.0 | 🟡 Supported | Via Zed adapter, tool calls + edit review |
| OpenCode | 1.15.6 | 🟡 Supported | Native ACP, 2 agents (build/plan), MCP servers |
Kiro and Claude Agent tested end-to-end with zero code changes between them. Codex and OpenCode are ACP-compatible and supported by this bridge; community testing welcome. Just swap agentCommand. See docs/demo-walkthrough.md for full test results and example-frontends/agents.md for setup guides.
Full ACP Ecosystem (33+ agents)
| Agent | ACP Type | Notes |
|---|---|---|
| Kiro CLI | Native | Full-featured, 13+ modes, custom agents |
| Claude Code | Via adapter (claude-agent-acp) | Permission modes, tool calls, MCP |
| Codex CLI | Via adapter (codex-acp) | Edit review, slash commands, MCP |
| OpenCode | Native | 2 built-in agents, custom tools, MCP |
| Gemini CLI | Native | Google's coding agent |
| GitHub Copilot | Native (public preview) | Copilot in terminal |
| Cursor | Native | IDE agent over ACP |
| Goose | Native | Block's open-source agent |
| Cline | Native | VS Code agent with ACP |
Also supported: Augment Code, AutoDev, Blackbox AI, Docker cagent, fast-agent, Factory Droid, Hermes Agent, Junie (JetBrains), Kimi CLI, Mistral Vibe, OpenHands, Poolside, Qwen Code, and more.
Full list: agentclientprotocol.com/get-started/agents
This repository accompanies a live demo presented at Seattle AI Tinkerers, May 2026.
Contributions welcome! Areas of interest:
- Additional agent configuration examples
- Frontend components for new AG-UI event types
- Policy engine enhancements (configurable approval rules)
- Session resume/persistence improvements
- More AG-UI event types (STATE_DELTA, activities, reasoning)
MIT
This project is independent and is not affiliated with, endorsed by, or sponsored by Amazon/Kiro, Anthropic/Claude, OpenAI/Codex, Google/Gemini, GitHub/Copilot, Cursor/Anysphere, OpenCode, Cline, or their respective owners. All product names, logos, and trademarks are property of their respective owners.


