什么是 AG-UI:AI Agent 与前端应用之间的交互协议
2025 年 5 月,一个名叫 AG-UI 的协议悄悄出现在 GitHub 上,两个月内已有 LangGraph、CrewAI、Mastra 等主流 Agent 框架相继接入。
它要解决的问题并不复杂,却是每个做 AI 应用的团队迟早会碰到的:Agent 后端和前端界面之间,用什么格式说话?
三层协议,各司其职
在 AG-UI 出现之前,AI Agent 生态里已经有两个协议占据了重要位置:
- MCP(Model Context Protocol,Anthropic 主导):解决 Agent 访问外部工具和数据源的问题
- A2A(Agent to Agent,Google 主导):解决多 Agent 之间协作和任务委托的问题
这两个协议覆盖了"Agent 对外"的两个方向,但都没有管"Agent 对用户"的这一段。
AG-UI 补的就是这个缺口——Agent 和前端应用(用户界面)之间的通信标准。
三个协议拼在一起,才构成一套完整的 Agent 协议栈。
AG-UI 是什么
全称 Agent User Interaction Protocol,由 CopilotKit 社区发起,2025 年 5 月正式开源。
一句话概括:一套开放的、轻量的、基于事件的协议,定义了 AI Agent 后端如何向前端应用发送信息,以及前端如何把用户输入传回给 Agent。
它不绑定任何框架,不要求特定的传输方式(SSE、WebSocket、Webhook 都可以),也不限制 Agent 内部用什么模型或技术栈。
唯一的要求是:当 Agent 需要和用户界面交互时,双方遵守同一套事件格式。
典型的请求链路是这样的:
- 用户在前端输入消息
- 前端通过 AG-UI Client 把消息发给 Agent 后端
- Agent 处理请求,调用 LLM 或工具
- Agent 把结果以事件流的形式返回给前端
- 前端根据事件类型实时更新 UI
整个过程双向流动:Agent 向前端下发事件,前端向 Agent 上报消息和工具调用结果。
核心:16 种标准事件
AG-UI 定义了 16 种标准事件类型,覆盖一次 Agent 交互的完整生命周期。
生命周期事件管理整个 Agent 运行流程:
RUN_STARTED → STEP_STARTED → STEP_FINISHED → RUN_FINISHED出错时发送 RUN_ERROR。前端收到 RUN_STARTED 就可以开始显示"正在思考"状态,收到 RUN_FINISHED 再收起来。
文本消息事件处理流式文字输出,类似 OpenAI streaming API 的拆包形式:
TEXT_MESSAGE_START → TEXT_MESSAGE_CONTENT(多次)→ TEXT_MESSAGE_END工具调用事件让前端清楚地知道 Agent 正在调什么工具、参数是什么:
TOOL_CALL_START → TOOL_CALL_ARGS → TOOL_CALL_ENDAG-UI 的设计里,工具列表由前端告知 Agent,调用结果由前端传回 Agent。
这样前端可以选择是否弹出确认框让用户审批,实现 Human-in-the-Loop。
状态管理事件解决前后端状态同步的问题:
STATE_SNAPSHOT:发送完整状态,用于初始化或恢复STATE_DELTA:发送增量变化,减少数据量
典型场景:Agent 正在实时修改一份文档或表单,状态事件驱动前端 UI 实时更新,不需要轮询。
16 种事件类型详细示例
1. 生命周期事件示例
// RUN_STARTED - Agent 开始处理请求
{
"type": "RUN_STARTED",
"threadId": "thread_123",
"runId": "run_456",
"timestamp": "2026-03-29T10:00:00Z"
}
// STEP_STARTED - Agent 开始执行一个步骤
{
"type": "STEP_STARTED",
"threadId": "thread_123",
"runId": "run_456",
"stepId": "step_789",
"stepType": "llm_call",
"timestamp": "2026-03-29T10:00:01Z"
}
// STEP_FINISHED - 步骤执行完成
{
"type": "STEP_FINISHED",
"threadId": "thread_123",
"runId": "run_456",
"stepId": "step_789",
"timestamp": "2026-03-29T10:00:05Z"
}
// RUN_FINISHED - 整个运行完成
{
"type": "RUN_FINISHED",
"threadId": "thread_123",
"runId": "run_456",
"timestamp": "2026-03-29T10:00:10Z"
}
// RUN_ERROR - 运行出错
{
"type": "RUN_ERROR",
"threadId": "thread_123",
"runId": "run_456",
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "API rate limit exceeded"
},
"timestamp": "2026-03-29T10:00:08Z"
}2. 文本消息事件示例
// TEXT_MESSAGE_START - 开始发送文本消息
{
"type": "TEXT_MESSAGE_START",
"messageId": "msg_001",
"role": "assistant",
"timestamp": "2026-03-29T10:00:02Z"
}
// TEXT_MESSAGE_CONTENT - 流式文本内容(多次发送)
{
"type": "TEXT_MESSAGE_CONTENT",
"messageId": "msg_001",
"delta": "AG-UI 是一套",
"timestamp": "2026-03-29T10:00:02.100Z"
}
{
"type": "TEXT_MESSAGE_CONTENT",
"messageId": "msg_001",
"delta": "开放的事件协议",
"timestamp": "2026-03-29T10:00:02.300Z"
}
// TEXT_MESSAGE_END - 文本消息结束
{
"type": "TEXT_MESSAGE_END",
"messageId": "msg_001",
"timestamp": "2026-03-29T10:00:02.500Z"
}3. 工具调用事件示例
// TOOL_CALL_START - 开始工具调用
{
"type": "TOOL_CALL_START",
"toolCallId": "tool_001",
"toolName": "search_weather",
"timestamp": "2026-03-29T10:00:03Z"
}
// TOOL_CALL_ARGS - 工具调用参数
{
"type": "TOOL_CALL_ARGS",
"toolCallId": "tool_001",
"args": {
"city": "北京",
"date": "2026-03-29"
},
"timestamp": "2026-03-29T10:00:03.100Z"
}
// TOOL_CALL_END - 工具调用结束
{
"type": "TOOL_CALL_END",
"toolCallId": "tool_001",
"timestamp": "2026-03-29T10:00:03.500Z"
}4. 状态管理事件示例
// STATE_SNAPSHOT - 完整状态快照
{
"type": "STATE_SNAPSHOT",
"state": {
"currentDocument": {
"title": "项目报告",
"content": "这是项目报告的初始内容...",
"lastModified": "2026-03-29T09:30:00Z"
},
"userPreferences": {
"theme": "dark",
"language": "zh-CN"
}
},
"timestamp": "2026-03-29T10:00:00Z"
}
// STATE_DELTA - 状态增量变化
{
"type": "STATE_DELTA",
"delta": {
"currentDocument": {
"content": "这是项目报告的更新内容..."
}
},
"timestamp": "2026-03-29T10:00:15Z"
}一个典型的事件流
以简单的对话为例,Agent 收到用户问题后,发出的完整事件序列大概是:
[
{ "type": "RUN_STARTED", "threadId": "t1", "runId": "r1" },
{ "type": "TEXT_MESSAGE_START", "messageId": "m1", "role": "assistant" },
{ "type": "TEXT_MESSAGE_CONTENT", "messageId": "m1", "delta": "AG-UI 是一套" },
{ "type": "TEXT_MESSAGE_CONTENT", "messageId": "m1", "delta": "开放的事件协议" },
{ "type": "TEXT_MESSAGE_END", "messageId": "m1" },
{ "type": "RUN_FINISHED", "threadId": "t1", "runId": "r1" }
]前端只需要处理事件类型,不用关心 Agent 内部用了哪个 LLM 或框架——这就是协议的价值。
传输方式:协议无关
AG-UI 本身不规定传输层。
常见的接法有三种:
| 传输方式 | 适合场景 |
|---|---|
| SSE(Server-Sent Events) | 最常见,单向流式推送,HTTP 友好 |
| WebSocket | 双向低延迟,适合需要高频交互的场景 |
| Webhook | 异步回调,适合任务型 Agent |
绝大多数 Web 应用选 SSE,实现最简单,不需要额外的基础设施。
前后端代码实现示例
1. 后端 Agent 实现(Node.js + Express)
// server.js - AG-UI 后端实现
const express = require('express');
const app = express();
app.use(express.json());
// 模拟 LLM 调用
async function callLLM(prompt) {
// 这里可以替换为实际的 OpenAI、Claude 等 API 调用
return new Promise((resolve) => {
setTimeout(() => {
resolve("AG-UI 是一套开放的事件协议,专门解决 AI Agent 后端与前端应用之间的通信标准化问题。");
}, 1000);
});
}
// SSE 端点 - 处理 AG-UI 事件流
app.get('/api/ag-ui/stream', (req, res) => {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Access-Control-Allow-Origin': '*'
});
const threadId = `thread_${Date.now()}`;
const runId = `run_${Date.now()}`;
// 发送 RUN_STARTED 事件
res.write(`data: ${JSON.stringify({
type: 'RUN_STARTED',
threadId,
runId,
timestamp: new Date().toISOString()
})}\n\n`);
// 模拟 Agent 处理过程
setTimeout(async () => {
// 发送 STEP_STARTED 事件
res.write(`data: ${JSON.stringify({
type: 'STEP_STARTED',
threadId,
runId,
stepId: 'step_llm',
stepType: 'llm_call',
timestamp: new Date().toISOString()
})}\n\n`);
// 发送 TEXT_MESSAGE_START
res.write(`data: ${JSON.stringify({
type: 'TEXT_MESSAGE_START',
messageId: 'msg_001',
role: 'assistant',
timestamp: new Date().toISOString()
})}\n\n`);
// 模拟流式文本输出
const response = await callLLM(req.query.prompt || '什么是 AG-UI?');
const chunks = response.match(/.{1,10}/g) || [response];
for (let i = 0; i < chunks.length; i++) {
res.write(`data: ${JSON.stringify({
type: 'TEXT_MESSAGE_CONTENT',
messageId: 'msg_001',
delta: chunks[i],
timestamp: new Date().toISOString()
})}\n\n`);
// 模拟流式输出的延迟
await new Promise(resolve => setTimeout(resolve, 100));
}
// 发送 TEXT_MESSAGE_END
res.write(`data: ${JSON.stringify({
type: 'TEXT_MESSAGE_END',
messageId: 'msg_001',
timestamp: new Date().toISOString()
})}\n\n`);
// 发送 STEP_FINISHED
res.write(`data: ${JSON.stringify({
type: 'STEP_FINISHED',
threadId,
runId,
stepId: 'step_llm',
timestamp: new Date().toISOString()
})}\n\n`);
// 发送 RUN_FINISHED
res.write(`data: ${JSON.stringify({
type: 'RUN_FINISHED',
threadId,
runId,
timestamp: new Date().toISOString()
})}\n\n`);
res.end();
}, 500);
});
app.listen(3000, () => {
console.log('AG-UI Server running on port 3000');
});2. 前端实现(原生 JavaScript)
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>AG-UI 示例</title>
<style>
.chat-container { max-width: 600px; margin: 0 auto; padding: 20px; }
.messages { border: 1px solid #ccc; height: 400px; overflow-y: auto; padding: 10px; }
.message { margin: 10px 0; padding: 8px; border-radius: 4px; }
.user { background: #e3f2fd; text-align: right; }
.assistant { background: #f5f5f5; }
.thinking { color: #666; font-style: italic; }
.input-area { display: flex; margin-top: 10px; }
.input-area input { flex: 1; padding: 8px; }
.input-area button { padding: 8px 16px; }
</style>
</head>
<body>
<div class="chat-container">
<h2>AG-UI 聊天示例</h2>
<div id="messages" class="messages"></div>
<div class="input-area">
<input type="text" id="userInput" placeholder="输入你的问题..." />
<button onclick="sendMessage()">发送</button>
</div>
</div>
<script>
class AGUIClient {
constructor() {
this.eventSource = null;
this.currentMessage = '';
this.isThinking = false;
}
connect(prompt) {
if (this.eventSource) {
this.eventSource.close();
}
this.eventSource = new EventSource(`/api/ag-ui/stream?prompt=${encodeURIComponent(prompt)}`);
this.eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
this.handleEvent(data);
};
this.eventSource.onerror = (error) => {
console.error('AG-UI 连接错误:', error);
this.addMessage('系统', '连接出错,请重试', 'error');
};
}
handleEvent(event) {
console.log('收到 AG-UI 事件:', event);
switch (event.type) {
case 'RUN_STARTED':
this.isThinking = true;
this.addMessage('系统', 'Agent 开始思考...', 'thinking');
break;
case 'TEXT_MESSAGE_START':
this.currentMessage = '';
break;
case 'TEXT_MESSAGE_CONTENT':
this.currentMessage += event.delta;
this.updateAssistantMessage(this.currentMessage);
break;
case 'TEXT_MESSAGE_END':
this.currentMessage = '';
break;
case 'RUN_FINISHED':
this.isThinking = false;
break;
case 'RUN_ERROR':
this.addMessage('系统', `错误: ${event.error.message}`, 'error');
this.isThinking = false;
break;
}
}
addMessage(role, content, type = 'normal') {
const messagesDiv = document.getElementById('messages');
const messageDiv = document.createElement('div');
messageDiv.className = `message ${role} ${type}`;
messageDiv.textContent = `${role}: ${content}`;
messagesDiv.appendChild(messageDiv);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
}
updateAssistantMessage(content) {
const messagesDiv = document.getElementById('messages');
let messageDiv = messagesDiv.lastChild;
if (!messageDiv || !messageDiv.classList.contains('assistant')) {
messageDiv = document.createElement('div');
messageDiv.className = 'message assistant';
messagesDiv.appendChild(messageDiv);
}
messageDiv.textContent = `Assistant: ${content}`;
messagesDiv.scrollTop = messagesDiv.scrollHeight;
}
}
const aguiClient = new AGUIClient();
function sendMessage() {
const input = document.getElementById('userInput');
const message = input.value.trim();
if (message) {
aguiClient.addMessage('User', message);
aguiClient.connect(message);
input.value = '';
}
}
// 支持回车键发送
document.getElementById('userInput').addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
sendMessage();
}
});
</script>
</body>
</html>3. 工具调用完整示例
// 工具调用示例 - 后端实现
app.post('/api/ag-ui/tools', (req, res) => {
const { toolName, args } = req.body;
// 模拟工具调用
switch (toolName) {
case 'search_weather':
// 这里可以调用实际的天气 API
const weatherData = {
city: args.city,
temperature: '25°C',
condition: '晴朗',
humidity: '60%'
};
res.json({ success: true, data: weatherData });
break;
case 'calculate':
const result = eval(args.expression); // 注意:生产环境不要用 eval
res.json({ success: true, data: result });
break;
default:
res.status(400).json({ success: false, error: '未知的工具' });
}
});
// 前端工具调用处理
class ToolHandler {
async handleToolCall(toolCall) {
// 显示确认对话框(Human-in-the-Loop)
const confirmed = confirm(`是否允许调用工具: ${toolCall.toolName}?`);
if (confirmed) {
try {
const response = await fetch('/api/ag-ui/tools', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
toolName: toolCall.toolName,
args: toolCall.args
})
});
const result = await response.json();
return result;
} catch (error) {
return { success: false, error: error.message };
}
} else {
return { success: false, error: '用户取消了工具调用' };
}
}
}已接入的框架
截至 2026 年初,已官方支持 AG-UI 的 Agent 框架包括:LangGraph、Mastra、CrewAI、AG2(AutoGen 的后续版本)。
微软 Azure Agent Framework 也在官方文档里收录了 AG-UI 集成指南。
前端侧目前有 CopilotKit 提供的 React 客户端库,WhatsApp 和微信的消息客户端在开发中。
AG-UI 解决了什么问题
在 AG-UI 出现之前,一个典型 AI 应用的前后端对接通常是这样的:后端用自己约定的格式推送数据,前端写一堆解析逻辑,换个 Agent 框架就要重写一遍。
协议不统一,对接成本高,代码也难复用。
AG-UI 的思路是:把前端和 Agent 之间的"约定"提升成开放标准。
前端只需要会处理 16 种事件,就能接任何遵守协议的 Agent;Agent 只需要会发这 16 种事件,就能对接任何遵守协议的前端。
前后端彻底解耦,各自专注自己的事情。
传输层实现对比
SSE vs WebSocket 实现差异
SSE 实现(推荐用于简单场景)
// 后端 SSE 实现
app.get('/ag-ui/sse', (req, res) => {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
// 发送 AG-UI 事件
const sendEvent = (event) => {
res.write(`data: ${JSON.stringify(event)}\n\n`);
};
sendEvent({ type: 'RUN_STARTED', threadId: 't1', runId: 'r1' });
// ... 更多事件
});
// 前端 SSE 客户端
const eventSource = new EventSource('/ag-ui/sse');
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
handleAGUIEvent(data);
};WebSocket 实现(适合双向高频交互)
// 后端 WebSocket 实现(使用 ws 库)
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
ws.on('message', (message) => {
const data = JSON.parse(message);
// 处理前端发送的消息
if (data.type === 'USER_MESSAGE') {
// 处理用户输入,发送 AG-UI 事件
ws.send(JSON.stringify({
type: 'RUN_STARTED',
threadId: data.threadId,
runId: 'r1'
}));
}
// 处理工具调用结果
if (data.type === 'TOOL_RESULT') {
// 继续 Agent 执行流程
}
});
});
// 前端 WebSocket 客户端
const ws = new WebSocket('ws://localhost:8080');
ws.onopen = () => {
// 发送用户消息
ws.send(JSON.stringify({
type: 'USER_MESSAGE',
content: '你好',
threadId: 't1'
}));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
handleAGUIEvent(data);
};完整的工作流示例
带工具调用和状态管理的完整 Agent 工作流
// 完整的 AG-UI Agent 实现
class AGUIAgent {
constructor() {
this.state = {
conversationHistory: [],
currentDocument: null,
userPreferences: {}
};
}
async processMessage(userMessage, sendEvent) {
const threadId = `thread_${Date.now()}`;
const runId = `run_${Date.now()}`;
// 1. 发送运行开始事件
sendEvent({
type: 'RUN_STARTED',
threadId,
runId,
timestamp: new Date().toISOString()
});
try {
// 2. 分析用户意图
sendEvent({
type: 'STEP_STARTED',
threadId,
runId,
stepId: 'step_analysis',
stepType: 'intent_analysis',
timestamp: new Date().toISOString()
});
const intent = await this.analyzeIntent(userMessage);
sendEvent({
type: 'STEP_FINISHED',
threadId,
runId,
stepId: 'step_analysis',
timestamp: new Date().toISOString()
});
// 3. 根据意图执行相应操作
if (intent.requiresTool) {
await this.handleToolCall(intent, sendEvent, threadId, runId);
} else {
await this.generateResponse(userMessage, sendEvent, threadId, runId);
}
// 4. 发送运行完成事件
sendEvent({
type: 'RUN_FINISHED',
threadId,
runId,
timestamp: new Date().toISOString()
});
} catch (error) {
// 5. 错误处理
sendEvent({
type: 'RUN_ERROR',
threadId,
runId,
error: {
code: 'PROCESSING_ERROR',
message: error.message
},
timestamp: new Date().toISOString()
});
}
}
async handleToolCall(intent, sendEvent, threadId, runId) {
// 发送工具调用开始事件
sendEvent({
type: 'TOOL_CALL_START',
toolCallId: 'tool_001',
toolName: intent.toolName,
timestamp: new Date().toISOString()
});
// 发送工具参数
sendEvent({
type: 'TOOL_CALL_ARGS',
toolCallId: 'tool_001',
args: intent.parameters,
timestamp: new Date().toISOString()
});
// 这里会等待前端返回工具调用结果
// 前端通过 Human-in-the-Loop 确认后调用工具
// 并将结果通过 TOOL_RESULT 事件传回
// 工具调用结束
sendEvent({
type: 'TOOL_CALL_END',
toolCallId: 'tool_001',
timestamp: new Date().toISOString()
});
}
async generateResponse(userMessage, sendEvent, threadId, runId) {
sendEvent({
type: 'STEP_STARTED',
threadId,
runId,
stepId: 'step_llm',
stepType: 'llm_call',
timestamp: new Date().toISOString()
});
// 开始文本消息
sendEvent({
type: 'TEXT_MESSAGE_START',
messageId: 'msg_001',
role: 'assistant',
timestamp: new Date().toISOString()
});
// 模拟流式响应
const response = "这是一个基于 AG-UI 协议的响应示例。";
const chunks = response.match(/.{1,5}/g) || [response];
for (const chunk of chunks) {
sendEvent({
type: 'TEXT_MESSAGE_CONTENT',
messageId: 'msg_001',
delta: chunk,
timestamp: new Date().toISOString()
});
await new Promise(resolve => setTimeout(resolve, 50));
}
// 结束文本消息
sendEvent({
type: 'TEXT_MESSAGE_END',
messageId: 'msg_001',
timestamp: new Date().toISOString()
});
sendEvent({
type: 'STEP_FINISHED',
threadId,
runId,
stepId: 'step_llm',
timestamp: new Date().toISOString()
});
}
// 状态同步示例
syncState(sendEvent) {
sendEvent({
type: 'STATE_SNAPSHOT',
state: this.state,
timestamp: new Date().toISOString()
});
}
updateState(delta, sendEvent) {
// 更新内部状态
this.state = { ...this.state, ...delta };
// 发送状态增量
sendEvent({
type: 'STATE_DELTA',
delta: delta,
timestamp: new Date().toISOString()
});
}
}快速开始指南
1. 安装依赖
# 后端(Node.js)
npm install express
# 前端(可选使用 CopilotKit)
npm install @copilotkit/react-components2. 创建最简单的 AG-UI 应用
后端(server.js)
const express = require('express');
const app = express();
app.get('/ag-ui/chat', (req, res) => {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
// 发送简单的 AG-UI 事件流
res.write(`data: ${JSON.stringify({
type: 'RUN_STARTED',
threadId: 'demo',
runId: 'run1'
})}\n\n`);
res.write(`data: ${JSON.stringify({
type: 'TEXT_MESSAGE_START',
messageId: 'msg1',
role: 'assistant'
})}\n\n`);
res.write(`data: ${JSON.stringify({
type: 'TEXT_MESSAGE_CONTENT',
messageId: 'msg1',
delta: '你好!这是一个 AG-UI 示例。'
})}\n\n`);
res.write(`data: ${JSON.stringify({
type: 'TEXT_MESSAGE_END',
messageId: 'msg1'
})}\n\n`);
res.write(`data: ${JSON.stringify({
type: 'RUN_FINISHED',
threadId: 'demo',
runId: 'run1'
})}\n\n`);
res.end();
});
app.listen(3000, () => {
console.log('AG-UI 示例服务运行在 http://localhost:3000');
});前端(index.html)
<!DOCTYPE html>
<html>
<body>
<button onclick="startChat()">开始对话</button>
<div id="output"></div>
<script>
function startChat() {
const eventSource = new EventSource('/ag-ui/chat');
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
const output = document.getElementById('output');
switch(data.type) {
case 'TEXT_MESSAGE_CONTENT':
output.innerHTML += data.delta;
break;
case 'RUN_STARTED':
output.innerHTML = 'Agent 开始处理...<br>';
break;
case 'RUN_FINISHED':
output.innerHTML += '<br>对话完成!';
eventSource.close();
break;
}
};
}
</script>
</body>
</html>3. 运行应用
node server.js然后在浏览器中打开 http://localhost:3000 即可体验 AG-UI 的基本功能。
常见问题
AG-UI 和 MCP 的区别是什么?
MCP 解决 Agent 调用外部工具和数据的问题(如查数据库、调 API);
AG-UI 解决 Agent 和用户界面通信的问题。
两者不冲突,一个 Agent 可以同时用 MCP 对接工具、用 AG-UI 对接前端。
AG-UI 和 OpenAI 的 streaming API 有什么不同?
OpenAI streaming API 是厂商私有格式,只适用于 OpenAI 的服务;
AG-UI 是开放协议,不绑定任何 LLM 厂商,任何 Agent 框架都可以实现。
AG-UI 的事件类型也比 token 流更丰富,支持工具调用、状态同步等场景。
前端必须用 React 才能用 AG-UI 吗?
不是。
AG-UI 是协议,不限制前端框架。
CopilotKit 提供了 React 的参考实现,但 Vue、Svelte 或者原生 JS 同样可以解析 AG-UI 的事件流,官方也在开发更多语言的客户端库。
AG-UI 适合什么规模的项目?
不限规模。
简单的聊天机器人和复杂的多 Agent 工作流都可以用。
协议本身很轻量,接入成本低,小项目不会因为用它显得过度设计。
写在最后
AI Agent 的协议生态还在快速演变。
MCP 管工具、A2A 管 Agent 间协作、AG-UI 管用户交互——三块拼图各就其位,才让复杂 Agent 应用的工程化有了标准可循。
如果你在做 AI 应用的前端集成,AG-UI 值得花半天时间研究一下。
版权声明
未经授权,禁止转载本文章。
如需转载请保留原文链接并注明出处。即视为默认获得授权。
未保留原文链接未注明出处或删除链接将视为侵权,必追究法律责任!