AG-UI:把 Agent 与前端之间的“私有暗号”变成标准协议
AG-UIï¼æ Agent ä¸å端ä¹é´çâç§ææå·âåææ ååè®®
åé¢ç³ 2026-08-17 0 é 读8åéå Agent åºç¨æ¶ï¼é¾ç¹å¾å¾ä¸åªæ¯æ¨¡åè°ç¨ï¼èæ¯å¦ä½ææµå¼ææ¬ãå·¥å ·æ§è¡ã页é¢ç¶æå人工确认稳å®å°ä¼ å°å端ãAG-UI è§£å³çæ£æ¯è¿ä¸å±é®é¢ã
ä¸ãAG-UI æ¯ä»ä¹
AG-UIï¼Agent-User Interaction Protocolï¼æ¯ä¸å¥è¿æ¥ AI Agent ä¸ç¨æ·çé¢ç弿¾ãè½»éãäºä»¶é©±å¨åè®®ã
å®ä¸è´è´£æ¨¡åæ¨çï¼èæ¯å®ä¹ï¼å端å¦ä½åèµ·ä¸æ¬¡ Agent è¿è¡ï¼ä»¥å Agent å¦ä½æç»å馿§è¡è¿ç¨ã
- MCPï¼Agent å¦ä½è¿æ¥å·¥å ·ãèµæºåæç¤ºè¯
- A2Aï¼Agent å¦ä½åç°å¹¶åä½å ¶ä» Agent
- AG-UIï¼Agent å¦ä½ä¸ç¨æ·çé¢å®æ¶äº¤äº
AG-UI å½åè¿æä¾è½ååç°ååè®®æ¡ææºå¶ï¼å¯ä½ä¸ºåç«¯å ¥å£è¿æ¥æ¯æ MCPãA2A ç Agentãå®ä¸ä¼æ¿ä»£ MCP æ A2Aï¼èæ¯æè¿äºè½åç»ä¸åç°å° UIã
äºã为ä»ä¹ä¸è½åªå®ä¹ä¸ä¸ª SSE æ¥å£
SSE åªæ¯ä¼ è¾æ¹å¼ãå®é 项ç®ä»è¦èªè¡çº¦å®ææ¬å¢éãå·¥å ·è¿åº¦ãå ±äº«ç¶æã人工确认ãåæ¶åå¼å¸¸çæ ¼å¼ã
æ¥å ¥å
/chat/stream â æµå¼åç
/tool/status â å·¥å
·è¿åº¦
/page/state â 页é¢ç¶æ
/action/confirm â 人工确认
/error â å¼å¸¸ä¿¡æ¯
æ¥å ¥ AG-UI å
POST /ag-ui
请æ±ï¼RunAgentInput
ååºï¼ä¸æ¡æç±»åç AG-UI Event Stream
å·®å«ä¸åªæ¯å°åå 个æ¥å£ï¼èæ¯ææ¬ãå·¥å ·ãç¶æåçå½å¨æå¼å§ä½¿ç¨åä¸ç§äº¤äºè¯è¨ã
AG-UI ç®åäº¤äºæµç¨
ä¸ãAG-UI å¦ä½ç®å交äº
1. ä¸ä¸ªè¾å ¥æºå¸¦å®æ´ä¸ä¸æ
RunAgentInput
âââ threadId / runId ä¼è¯ä¸è¿è¡æ è¯
âââ messages å岿¶æ¯
âââ tools åç«¯å¯æ§è¡å·¥å
·
âââ state å½åå
±äº«ç¶æ
âââ context 页颿ä¸å¡ä¸ä¸æ
âââ resume 䏿æ¢å¤ä¿¡æ¯
å端æ éåä»å¤ä¸ªæ¥å£æ¼è£ æ¶æ¯ãå·¥å ·å页é¢ä¸ä¸æã
2. 䏿¡äºä»¶æµè¦ç宿´è¿è¡è¿ç¨
çå½å¨æï¼RUN_STARTED / RUN_FINISHED / RUN_ERROR
ææ¬æ¶æ¯ï¼TEXT_MESSAGE_START / CONTENT / END
å·¥å
·è°ç¨ï¼TOOL_CALL_START / ARGS / END / TOOL_CALL_RESULT
å
±äº«ç¶æï¼STATE_SNAPSHOT / STATE_DELTA
å端åªå»ºç«ä¸å¥è¿æ¥ï¼å¹¶æäºä»¶è¯ä¹æ´æ° UIï¼
TEXT_MESSAGE_CONTENT â è¿½å æµå¼ææ¬
TOOL_CALL_* â å±ç¤ºå·¥å
·è¿åº¦æäº¤äºç»ä»¶
STATE_DELTA â æ´æ°é¡µé¢å±é¨ç¶æ
RUN_FINISHED â ç»æ loading æè¿å
¥ä¸æç¶æ
3. å·¥å ·è°ç¨ç´æ¥åæçæå¼ UI
Agent ä¸ååªè½è¿å Markdownãå®å¯ä»¥è°ç¨åç«¯å·¥å ·ï¼ç±é¡µé¢æ¸²æå¡çãå¾è¡¨ãæé®æè¡¨åãç¨æ·æä½ç»æååå° Agentï¼å½¢æè¿ç»ç人æºåä½ã
4. å ±äº«ç¶æä¸åä¾èµè½®è¯¢
STATE_SNAPSHOT åé宿´ç¶æï¼STATE_DELTA åéå¢éååãéå表ååä½ãé¿ä»»å¡è¿åº¦ãç»æåæ°æ®ç¼è¾å页颿¢å¤ã
5. äººå·¥ç¡®è®¤ææ åçæå䏿¢å¤æ¹å¼
AG-UI è½åæ¨¡åæ¯æ approvalsãinterventionsãfeedback å interruptsãæææä½å¯å
è¿å interruptï¼ç¨æ·ç¡®è®¤æä¿®æ¹åæ°åï¼åéè¿ RunAgentInput.resume æ¢å¤ã
6. Agent å¯ä»¥å£°æèªèº«è½å
客æ·ç«¯å¯è¯»å Agent capabilitiesï¼å¤æå®æ¯å¦æ¯æä¼ è¾æ¹å¼ãå·¥å ·è°ç¨ãç»æåè¾åºãç¶æåæ¥ã夿¨¡æå人工确认ï¼å卿å¯ç¨å¯¹åºç»ä»¶ã
7. MCP è´è´£è¿æ¥å·¥å ·ï¼AG-UI è´è´£è¿æ¥ç¨æ·
ç¨æ·æä½
â AG-UI åéä¸ä¸æ
â Agent éè¿ MCP è°ç¨å·¥å
·
â AG-UI è¿åå·¥å
·ãææ¬åç¶æäºä»¶
â åç«¯å®æ¶å±ç¤ºè¿ç¨ä¸ç»æ
æ°å¢ MCP Server åï¼å·¥å ·æ¥æºè½ç¶ååï¼ä½åç«¯ä»æ¶è´¹åä¸å¥ AG-UI äºä»¶ã
åãAG-UI 带æ¥çä¸»è¦æ¶ç
- ç»ä¸äº¤äºæ¨¡åï¼ææ¬ãå·¥å ·ãç¶æãçå½å¨æä½¿ç¨åä¸å¥äºä»¶
- åå°ç§ææ¥å£ï¼ä¸å¿ åå«è®¾è®¡å·¥å ·è¿åº¦ãç¶æåæ¥å确认åè°
- éä½å端è¦åï¼æ¿æ¢æ¨¡åæ Agent æ¡æ¶æ¶ï¼UI åè®®åºæ¬ä¸å
- æå宿¶ä½éªï¼åçãè¿åº¦ãå·¥å ·åæ°åç¶æé½è½å¢éåç°
- æ¯æçæå¼ UIï¼Agent å¯ä»¥é©±å¨å¡çãå¾è¡¨ãæé®å表å
- æ¯æå ±äº«ç¶æï¼Agent ä¸é¡µé¢å´ç»åä¸ä»½ç¶æåä½
- æ¯æäººæºååï¼å®¡æ¹ã䏿ãä¿®æ¹åæ°åæ¢å¤è¿è¡æç»ä¸è¡¨è¾¾
- æ¯æè½ååç°ï¼å端å¯ä»¥æ ¹æ® Agent capabilities 卿éé
- å ¼å®¹ MCP ä¸ A2Aï¼å·¥å ·åå ¶ä» Agent è½åå¯ä»¥è¿å ¥åä¸ç¨æ·ä½éª
äºãä¸å¥å¯è¿ç§»çæ¥å ¥ç»æ
ç®å½ä¸å¿ å®å ¨ä¸è´ï¼å ³é®æ¯æ¾å°å个èè´£ï¼Agent æå»ºãAG-UI Endpointãæå¡ç«¯ Runtime å UI 渲æã
backend/
âââ app/agents/chat_agent.py # æå»º Agent graph
âââ app/api/ag_ui.py # æè½½ AG-UI Endpoint
âââ app/main.py # FastAPI å
¥å£
frontend/
âââ src/app/api/copilotkit/route.ts # Runtime 代ç
âââ src/app/providers.tsx # Provider
âââ src/features/agent/
âââ agent-chat.tsx # è天 UI
âââ use-agent-tools.tsx # å端工å
·
åæä»¶ãDDDãæä»¶åæå¾®æå¡é¡¹ç®åæ ·éç¨ï¼åªéæç¤ºä¾æä»¶æ å°å°èªå·±çæ©å±ç¹ã
AG-UI éç¨æ¥å ¥æ¶æå¾
å ãPython ä¾§ï¼æç°æ Agent æ´é²ä¸º AG-UI Endpoint
1. å®è£ ä¾èµ
pip install fastapi uvicorn langgraph ag-ui-protocol ag-ui-langgraph
2. ä¿çç°æ Agent æå»ºæ¹å¼
示ä¾ï¼app/agents/chat_agent.py
from my_agent.workflow import build_workflow
def create_chat_graph():
"""è¿åå·²ç» compile ç LangGraph graphã"""
return build_workflow().compile()
my_agent.workflow æ¯å ä½ãå®é
项ç®åºç»§ç»å¤ç¨èªå·±ç模åãå·¥å
·ãcheckpointãä¾èµæ³¨å
¥åå¯è§æµæ§é
ç½®ã
3. ä½¿ç¨ CopilotKit å端è½åæ¶æ¥å ¥ Middleware
妿åªéè¦åºç¡ AG-UI æ¶æ¯åäºä»¶ä¼ è¾ï¼åè®®éé
卿¬èº«å³å¯å·¥ä½ï¼å¦æè¿è¦ä½¿ç¨ useFrontendToolãå
±äº«ç¶æã䏿æ¢å¤ç CopilotKit è½åï¼ååºå¨å建 Agent æ¶å å
¥ CopilotKitMiddlewareã
pip install copilotkit deepagents
示ä¾ï¼å¨ Agent Builder 䏿³¨å Middleware
from copilotkit import CopilotKitMiddleware
from deepagents import create_deep_agent
agent = create_deep_agent(
model=model,
tools=tools,
middleware=[CopilotKitMiddleware()],
)
妿项ç®ä½¿ç¨èªå®ä¹ Descriptor æå·¥åï¼å¯ä»¥æ Middleware ä½ä¸ºé ç½®ä¼ å ¥ï¼
middleware=(CopilotKitMiddleware(),)
AG-UI Endpoint è´è´£åè®®ä¼ è¾åäºä»¶æµï¼CopilotKitMiddleware è´è´£è®© Agent æ§è¡è¿ç¨è¯å«å端工å
·ãä¸ä¸æå CopilotKit 交äºè½åã两è
èè´£ä¸åï¼å®æ´ççæå¼ UI æ¥å
¥é常éè¦åæ¶é
ç½®ã
4. åç¬å°è£ å议路ç±
示ä¾ï¼app/api/ag_ui.py
from ag_ui_langgraph import add_langgraph_fastapi_endpoint
from fastapi import FastAPI
from app.agents.chat_agent import create_chat_graph
def register_ag_ui(app: FastAPI) -> None:
add_langgraph_fastapi_endpoint(
app,
create_chat_graph(),
"/ag-ui",
)
è¿ä¸ªæä»¶åªè´è´£åè®®éé
ãä»¥åæ´æ¢ Agent æ¶ï¼åªéè¦æ¿æ¢ create_chat_graph()ã
5. æè½½å° FastAPI
示ä¾ï¼app/main.py
from fastapi import FastAPI
from app.api.ag_ui import register_ag_ui
app = FastAPI()
register_ag_ui(app)
妿 graph ä¾èµæ°æ®åºã弿¥ checkpoint æè¿è¡æ¶é ç½®ï¼å¯å¨ lifespan ä¸åå§åï¼
from contextlib import asynccontextmanager
from fastapi import FastAPI
@asynccontextmanager
async def lifespan(app: FastAPI):
await initialize_dependencies()
register_ag_ui(app)
yield
await close_dependencies()
app = FastAPI(lifespan=lifespan)
6. å¯å¨æå¡
uvicorn app.main:app --host 0.0.0.0 --port 8000
è³æ¤ï¼å端å¾å°ä¸ä¸ªæ¥æ¶ RunAgentInputãè¿å AG-UI äºä»¶æµç POST /ag-uiã
é LangGraph 项ç®å¯ä»¥éæ©å¯¹åºéé å¨ï¼æ²¡æç°æéé 卿¶ï¼ä¹å¯ä½¿ç¨
RunAgentInputãEventEncoderåStreamingResponseæå¨åéäºä»¶ã
ä¸ãNext.js ä¾§ï¼å»ºç« Runtime 代ç并渲æ UI
以ä¸éç¨ App RouterãPages Router çç®å½ä¸åï¼ä½ RuntimeãProvider å HttpAgent çèè´£ç¸åã
1. å®è£ ä¾èµ
pnpm add @ag-ui/client @copilotkit/runtime @copilotkit/react-core zod
2. é ç½®å端å°å
示ä¾ï¼.env.development
BACKEND_API_URL=http://localhost:8080
该åéåªå¨æå¡ç«¯è¯»åï¼ä¸éè¦æ´é²ä¸º NEXT_PUBLIC_*ã
3. å建 Runtime 代ç
示ä¾ï¼src/app/api/copilotkit/route.ts
import { HttpAgent } from '@ag-ui/client';
import {
CopilotRuntime,
createCopilotRuntimeHandler
} from '@copilotkit/runtime/v2';
const backendUrl = process.env.BACKEND_API_URL;
if (!backendUrl) throw new Error('BACKEND_API_URL is required');
const runtime = new CopilotRuntime({
agents: {
assistant: new HttpAgent({
agentId: 'assistant',
url: `${backendUrl}/ag-ui`
})
}
});
const handler = createCopilotRuntimeHandler({
runtime,
basePath: '/api/copilotkit',
mode: 'single-route'
});
export const GET = handler;
export const POST = handler;
export const OPTIONS = handler;
è¿å±ä»£çç¨äºéèå端å°åãéä¸å¤ç认è¯ï¼å¹¶ææµè§å¨è¯·æ±è½¬åå° AG-UI Endpointãå·²æ BFF æ API Gateway ç项ç®ä¹å¯æ HttpAgent 注åå¨é£éã
4. æè½½ Provider
示ä¾ï¼src/app/providers.tsx
'use client';
import { CopilotKitProvider } from '@copilotkit/react-core/v2';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<CopilotKitProvider
runtimeUrl='/api/copilotkit'
useSingleEndpoint>
{children}
</CopilotKitProvider>
);
}
Provider å¯ä»¥æå¨æ ¹å¸å±ï¼ä¹å¯ä»¥åªå 裹éè¦ Agent çä¸å¡é¡µé¢ã使ç¨å ç½®è天ç»ä»¶æ¶ï¼è¿éè¦å¨å¸å±æä»¶ä¸å¼å ¥æ ·å¼ï¼
import '@copilotkit/react-core/v2/styles.css';
5. 渲æè天ç»ä»¶
示ä¾ï¼src/features/agent/agent-chat.tsx
'use client';
import { CopilotChat } from '@copilotkit/react-core/v2';
import { useAgentTools } from './use-agent-tools';
export function AgentChat() {
useAgentTools();
return (
<CopilotChat
agentId='assistant'
labels={{ welcomeMessageText: 'ä»å¤©æ³å¤çä»ä¹ï¼' }}
/>
);
}
agentId='assistant' å¿
é¡»ä¸ Runtime key å HttpAgent.agentId ä¸è´ã
6. 注ååç«¯å·¥å ·
示ä¾ï¼src/features/agent/use-agent-tools.tsx
'use client';
import { useFrontendTool } from '@copilotkit/react-core/v2';
import { z } from 'zod';
export function useAgentTools() {
useFrontendTool({
name: 'show_summary',
description: 'å¨é¡µé¢ä¸å±ç¤ºç»æåæè¦',
parameters: z.object({
title: z.string(),
items: z.array(z.string())
}),
handler: async ({ title }) => `å·²å±ç¤ºæè¦ï¼${title}`,
render: ({ args }) => (
<section>
<h3>{args.title}</h3>
<ul>
{args.items.map((item) => <li key={item}>{item}</li>)}
</ul>
</section>
)
});
}
Agent 触å show_summary æ¶ï¼åç«¯ç´æ¥æ¸²æç»æåç»ä»¶ï¼è䏿¯è®©æ¨¡åæ¼ä¸æ®µåºå®æ ¼å¼ MarkdownãVueãåç TypeScript æèªç ç»ä»¶åºä¹å¯éç¨ç¸åæ å°æè·¯ã
å «ãä»è¾å ¥å°æ¸²æç宿´è°ç¨é¾
- ç¨æ·å¨è天ç»ä»¶è¾å ¥æ¶æ¯
- Provider å°è¯·æ±åéå°
/api/copilotkit - Next.js Runtime æ ¹æ®
agentIdæ¾å°HttpAgent HttpAgentå Python/ag-uiåéRunAgentInput- Agent è¿è¡æ¨¡åå¹¶æéè°ç¨ MCP æä¸å¡å·¥å ·
- Python æç»è¿åææ¬ãå·¥å ·åç¶æäºä»¶
- Runtime å°äºä»¶æµè½¬åç»æµè§å¨
- è天ç»ä»¶ååç«¯å·¥å ·æäºä»¶è¯ä¹æ´æ° UI
ä¸å¡ä»£ç å¯ä»¥ååï¼ä½æµè§å¨ä¸ Agent ä¹é´çåè®®ä¿æç¨³å®ã
ä¹ãæ¥å ¥æ£æ¥ç¹
- å端å°åæ¯ Next.js æå¡ç«¯å¯è®¿é®çå°å
- ç½å ³å ³é SSE ç¼å²ï¼å¹¶å 许足å¤é¿çè¶ æ¶æ¶é´
- Agent åç§°ãRuntime key å页é¢
agentIdä¿æä¸è´ - å·¥å ·åååæ° Schema ä¸ Agent è¾åºä¸è´
threadIdãrunIdãmessageIdä¿æç¨³å®- é«é£é©å·¥å ·å¢å é´æãåæ°æ ¡éªå人工确认
- AG-UIãCopilotKit å Python éé 卿å¥å级éªè¯
åãéç¨è¾¹ç
AG-UI ä¸ä¼æ¿ä»£é´æãä¼è¯åå¨ãéæµåä¸å¡æéï¼è¿äºä»å±äºåºç¨èªèº«èè´£ã对äºä¸æ¬¡æ§è¿åç®åææ¬çæ¥å£ï¼æ®é REST ä¹å¯è½æ´è½»éã
åä¸ãæ»ç»
AG-UI çæ ¸å¿ä»·å¼ä¸æ¯âååä¸ä¸ªè天æ¥å£âï¼èæ¯æåæ£çææ¬æµãå·¥å ·è°ç¨ãå ±äº«ç¶æã人工确认åè¿è¡çå½å¨æç»ä¸æå¯å¤ç¨ç宿¶äºä»¶å¥çº¦ã
MCP è´è´£è®© Agent æ¥ä¸å·¥å ·ï¼A2A è´è´£è®© Agent æ¥ä¸å ¶ä» Agentï¼AG-UI åè´è´£è®©è¿äºè½åçæ£è¿å ¥ç¨æ·çé¢ã
æ 论ç®å½ãAgent æ¡æ¶å UI ç»ä»¶åºå¦ä½ååï¼æ¥å ¥æ¶åªè¦æ¾å°å个ä½ç½®å³å¯ï¼Agent æå»ºãAG-UI Endpointãæå¡ç«¯ Runtimeãå端渲æã
Aitishiku.com