一八零、AG-UI:构建AI前端交互的统一协议

一八零、AG-UI:构建AI前端交互的统一协议

AG-UI:构建AI前端交互的统一协议

引言

随着人工智能技术的飞速发展,AI Agent已经从概念走向实际应用。然而,在将这些智能体集成到前端应用中时,开发者面临着一个关键挑战:如何实现AI Agent与用户界面之间的高效、标准化交互?

AG-UI(Agent User Interaction Protocol)正是为解决这一痛点而诞生的开源协议。它不仅仅是一个技术规范,更是连接AI智能体与前端应用的桥梁,让开发者能够构建真正智能化的用户体验。它们能够让开发者构建出真正嵌入UI应用、感知上下文、实时协同的智能体,而不仅仅是一个在后台提供文本答案的API服务。

一、AG-UI是什么?

1.1 核心定义

AG-UI(Agent-User Interaction Protocol) 是由CopilotKit团队提出的开源、轻量级协议,专门用于规范AI Agent与前端用户界面之间的通信流程,是一套开源的Agent与UI界面之间的交互协议。它的核心使命是:

标准化前端应用与AI智能体的连接方式,通过开放协议实现通用的AI驱动系统通信。
在这里插入图片描述

1.2 协议定位

在这里插入图片描述

在AI生态系统中,AG-UI与其他协议形成互补关系:

  • MCP(Model Context Protocol):定义AI模型调用外部工具的协议规范
  • A2A(Agent-to-Agent Protocol):规范智能体之间的通信协议
  • AG-UI专注于智能体与用户(前端应用)之间的交互规范

这种分工明确的设计让AG-UI能够专注于解决人机交互层面的问题,而不与其他协议产生冲突。

二、为什么需要AG-UI?

在AG-UI出现之前,AI应用开发面临诸多挑战:

技术碎片化
  • 每个AI框架(LangGraph、CrewAI、Mastra等)都有独特的事件机制和API
  • 不同模型提供商的接口格式各异,增加适配成本
  • 缺乏统一的前后端同步机制
实时性困难
  • 用户期待实时的流式响应体验
  • 传统的请求-响应模式无法满足复杂AI工作流需求
  • 状态同步和进度反馈机制不完善
人机协作缺失
  • 用户难以对AI执行过程进行实时干预
  • 缺乏标准化的人机协作(Human-in-the-loop)机制
  • 工具调用和状态共享缺乏统一规范

这些问题会导致开发者在和多个AI服务对接或构建复杂AI应用时重写大量代码。

假设有一套通信协议,可以统一前端应用和后端Agent之间的交互格式,做到前后端解耦,让大家各司其职。AG-UI的出现,就是为了解决这个问题

三、AG-UI核心架构

3.1 整体架构设计

在这里插入图片描述
  • Application:直接与用户交互的前端应用层,比如ChatGPT、Cursor等任何AI powered应用。
  • AG-UI Client:在前端侧负责与后端Agent进行通信,使用AG-UI协议。
  • Agent:后端Agent通常和AI服务或其他Agent对接,用来处理用户请求。

3.2 核心特性

统一事件流

AG-UI 的核心是单一序列的 JSON 事件,简化了代理与前端的实时同步,确保流畅无碍的通信,不论代理使用何种"语言"或内部实现。

实时交互

支持 LLM 逐步生成的 token 立即显示,提供流畅、自然的用户体验,并实现人机协同工作流程。

工具编排

现代代理可调用函数、运行代码、访问 API。AG-UI 确保前端能实时显示进度和结果,支持人工批准并无缝恢复运行。

共享状态

通过高效传输差异更新,代理能够生成逐步演进的计划、表格或代码文件夹,节省带宽并保持同步状态。

并发与取消

支持用户同时发出多个查询、中途停止或切换线程,通过线程 ID、运行 ID 和有序的关闭路径确保稳定运行。

安全边界

**协议内建权限管理、身份认证等机制,**提供企业级的 CORS,确保数据传输的安全性和可靠性。

3.3 事件Events

AG-UI定义了17种标准化事件类型,构成完整的AI交互生命周期管理体系。基于官方文档,以下是完整的事件系统架构:

EventType 枚举定义
enum EventType { TEXT_MESSAGE_START = "TEXT_MESSAGE_START", TEXT_MESSAGE_CONTENT = "TEXT_MESSAGE_CONTENT", TEXT_MESSAGE_END = "TEXT_MESSAGE_END", TOOL_CALL_START = "TOOL_CALL_START", TOOL_CALL_ARGS = "TOOL_CALL_ARGS", TOOL_CALL_END = "TOOL_CALL_END", TOOL_CALL_RESULT = "TOOL_CALL_RESULT", STATE_SNAPSHOT = "STATE_SNAPSHOT", STATE_DELTA = "STATE_DELTA", MESSAGES_SNAPSHOT = "MESSAGES_SNAPSHOT", RAW = "RAW", CUSTOM = "CUSTOM", RUN_STARTED = "RUN_STARTED", RUN_FINISHED = "RUN_FINISHED", RUN_ERROR = "RUN_ERROR", STEP_STARTED = "STEP_STARTED", STEP_FINISHED = "STEP_FINISHED", } 
AG-UI事件分类总览
事件分类事件类型事件名称功能描述使用场景
生命周期事件(5)流程控制、错误处理RUN_STARTED运行开始标记Agent执行开始初始化UI状态,显示加载状态
STEP_STARTED步骤开始标记单个步骤开始显示当前执行步骤
STEP_FINISHED步骤完成标记单个步骤完成更新步骤状态,显示进度
RUN_FINISHED运行完成标记整个执行完成清理状态,显示最终结果
RUN_ERROR运行错误标记执行出现错误错误处理,显示错误信息
文本消息事件(3)实时对话、流式输出TEXT_MESSAGE_START消息开始开始新的文本消息创建消息容器
TEXT_MESSAGE_CONTENT消息内容流式传输消息内容实时显示打字效果
TEXT_MESSAGE_END消息结束标记消息传输完成完成消息渲染
工具调用事件(4)功能扩展、透明度TOOL_CALL_START工具调用开始开始调用外部工具显示工具调用状态
TOOL_CALL_ARGS工具参数传输工具调用参数显示调用参数信息
TOOL_CALL_RESULT工具调用结果返回工具执行结果显示工具返回的数据
TOOL_CALL_END工具调用结束工具调用完成显示调用结果
状态管理事件(3)数据同步、一致性STATE_SNAPSHOT状态快照完整状态数据同步完整应用状态
STATE_DELTA状态变更增量状态更新高效更新部分状态
MESSAGES_SNAPSHOT消息快照完整消息历史同步对话历史
特殊事件(2)系统集成、定制化RAW原始事件未处理的原始数据调试和扩展用途
CUSTOM自定义事件用户定义的事件特殊业务逻辑处理
事件流程示例
sequenceDiagram participant User as 👤 用户 participant Frontend as 🖥️ 前端 participant Agent as 🤖 AI Agent participant Tool as 🛠️ 工具 User->>Frontend: 发送消息 Frontend->>Agent: 用户输入 Agent->>Frontend: RUN_STARTED Agent->>Frontend: STEP_STARTED Agent->>Frontend: TEXT_MESSAGE_START Agent->>Frontend: TEXT_MESSAGE_CONTENT (流式) Agent->>Frontend: TEXT_MESSAGE_CONTENT (流式) Agent->>Frontend: TEXT_MESSAGE_END Agent->>Frontend: TOOL_CALL_START Agent->>Frontend: TOOL_CALL_ARGS Agent->>Tool: 执行工具 Tool->>Agent: 工具结果 Agent->>Frontend: TOOL_CALL_RESULT Agent->>Frontend: TOOL_CALL_END Agent->>Frontend: STATE_SNAPSHOT Agent->>Frontend: STEP_FINISHED Agent->>Frontend: RUN_FINISHED Frontend->>User: 显示完整响应 

3.4 Agents 智能体

Agent是AG-UI里的核心组成部分,负责处理前端发起的请求,和LLM交互并生成响应(响应需遵循Events格式),同时还要管理对话状态和消息历史。在Agent底层可以和其他任意的AI服务连接(比如任意的LLM、定制的AI系统、RAG、其他Agent等等)。

Agent具备丰富的交互能力:

  • 基本的文本传输: 通过TEXT_MESSAGE_*系列事件实现流式文本交互
  • 工具调用: 在AG-UI的规范下,Agent可以使用哪些Tools是由前端告知的。当Agent决策需要使用工具时,可以通过一系列事件(TOOL_CALL_START -> TOOL_CALL_ARGS -> TOOL_CALL_END)通知到前端,前端在收到事件后,可决定是否给用户展示对应交互,告知需要调用哪些工具以及对应参数,由用户决定是否调用。调用结果会通过Message传递给Agent。
  • 状态管理: Agent可以向前端传递最新完整的状态(STATE_SNAPSHOT)或增量同步状态(STATE_DELTA),可以让前端应用从中断状态恢复。
  • 多Agent交互: Agent可以通过A2A等其他协议和其他Agent交互,此过程可以不让前端用户感知(只要不发送Event就行)。
  • Human-in-the-Loop控制: 可以将人在回路的控制能力作为Tool注入给Agent,由Agent决定在必要时候让人进行决策(仍然通过工具调用链路)

3.5 Messages

传统与LLM通信时,message中的role通常被分为systemuserassistant。在AG-UI中,developer、工具调用的结果也被当成一种消息类型(tool)。

核心特性:

  • 流式传输: 通过TEXT_MESSAGE_* 实现打字机效果
  • 角色管理: 支持developer、user、assistant、system、tool等多种角色
  • 消息历史: MESSAGES_SNAPSHOT提供完整消息快照(上下文)
  • 工具集成: 工具调用结果作为独立的消息类型处理

对话示例:

 [ // User { id: "msg_1", role: "user", content: "What's the weather in New York?", }, // Assistant response with tool call { id: "msg_2", role: "assistant", content: "Let me check the weather for you.", toolCalls: [ { id: "call_1", type: "function", function: { name: "get_weather", arguments: '{"location": "New York", "unit": "celsius"}', }, }, ], }, // 注意,这里的工具调用其实是由Agent通知给前端,由前端用户决定是否调用工具,并把调用结果传给Agent,让Agent继续后续流程 // Tool result { id: "result_1", role: "tool", content: '{"temperature": 22, "condition": "Partly Cloudy", "humidity": 65}', toolCallId: "call_1", }, // Assistant's final response using tool results { id: "msg_3", role: "assistant", content: "The weather in New York is partly cloudy with a temperature of 22°C and 65% humidity.", }, ] 

3.6 状态管理

除了基本的同步聊天消息之外,可以同步任意的状态,让人和AI的操作可以衔接操作。

官方提供了一个比较有意思的Demo:让AI优化一份菜谱,菜谱在前端使用富交互展示的,随着AI Agent的优化,前端交互可实时进行更新。

https://feature-viewer-langgraph.vercel.app/feature/shared_state

核心特性:

  • 状态快照: STATE_SNAPSHOT提供完整应用状态的一次性同步,一般用于初始状态同步、中断状态恢复等
  • 增量更新: STATE_DELTA支持高效的部分状态更新,使用JSON Patch,可以流式快速更新
  • 复杂交互: 前端应用可以实现更复杂交互的流式更新,给用户更好的交互体验

3.7 工具调用 Tools

需要和前端交互的工具可以在前端定义,并通过协议传给Agent,当Agent认为需要使用工具时,会使用Event向前端发消息,前端可向用户展示被调用的工具名称和参数,让用户决定是否继续。

在AG-UI中,工具可以:

  • 获取更多的信息: 如天气查询、搜索引擎等
  • 操作外部系统: 如发送邮件、创建文档等
  • 让人进行信息输入或二次确认: Human-in-the-loop机制

核心特性:

  • 前端定义: 工具由前端定义并传递给Agent
  • 用户控制: 用户可以决定是否执行工具调用
  • 参数透明: TOOL_CALL_ARGS支持复杂参数的流式传输
  • 结果返回: TOOL_CALL_RESULT提供工具执行结果的标准化返回
  • 执行监控: 完整的工具调用生命周期跟踪

工具调用流程:

// 1. 开始工具调用 - Agent通知前端需要调用工具 const toolStart: ToolCallStartEvent = { type: EventType.TOOL_CALL_START, toolCallId: "tool_456", toolCallName: "get_weather", parentMessageId: "msg_123" } // 2. 传输参数 - 显示给用户工具调用的参数 const toolArgs: ToolCallArgsEvent = { type: EventType.TOOL_CALL_ARGS, toolCallId: "tool_456", delta: '{"location": "New York", "unit": "celsius"}' } // 3. 返回结果 - 用户确认后,前端执行工具并返回结果 const toolResult: ToolCallResultEvent = { type: EventType.TOOL_CALL_RESULT, messageId: "msg_124", toolCallId: "tool_456", content: '{"temperature": 22, "condition": "Partly Cloudy", "humidity": 65}', role: "tool" } // 4. 结束调用 - 工具调用完成 const toolEnd: ToolCallEndEvent = { type: EventType.TOOL_CALL_END, toolCallId: "tool_456" } 

工具调用事件序列:
ToolCallStart -> ToolCallArgs -> ToolCallResult -> ToolCallEnd

四、AG-UI的技术优势

4.1 灵活性与兼容性

事件结构灵活性
  • 事件无需完全匹配AG-UI格式,只需保持兼容性
  • 现有框架可以最小化改动适配AG-UI
  • 支持渐进式迁移策略

4.2 开发者友好性

丰富的SDK支持
  • TypeScript SDK:提供完整的类型定义和开发工具
  • Python SDK:支持主流AI框架集成
  • 多语言扩展:社区驱动的其他语言实现
现成的集成方案

AG-UI已与多个主流AI框架深度集成:

FrameworkStatusAG-UI Resources
No-framework✅ Supported➡️ Docs coming soon
LangGraph✅ Supported➡️ Demo
Mastra✅ Supported➡️ Demo
CrewAI✅ Supported➡️ Demo
AG2✅ Supported➡️ Demo
Agno✅ Supported➡️ Docs
LlamaIndex✅ Supported➡️ Docs
Pydantic AI🛠️ In Progress
Vercel AI SDK🛠️ In Progress
Google ADK🛠️ In Progress
OpenAI Agent SDK💡 Open to Contributions
AWS Bedrock Agents💡 Open to Contributions
Cloudflare Agents💡 Open to Contributions
Strands Agents SDK💡 Open to Contributions
Language SDKStatusAG-UI Resources
.NET🛠️ In Progress➡️ PR
Nim🛠️ In Progress➡️ PR
Rust🛠️ In Progress

五、演示Demo

5.1 **CopilotKit的演示Demo **

****iCode 仓库

CopilotKit 可以被看作 AG-UI 协议实现的一个框架。它提供了完整的前后端集成方案,使开发者能够快速将 AI Copilot引入应用,包括:TypeScript/React 前端组件库、Python/Node SDK、以及可选的云端代理服务等。
  • 后端Agent:使用Python + LangGraph构建的一个Workflow智能体。
  • 前端应用:使用React+TS构建简单的Demo。
  • Copilot助手:前端接入CopilotKit给应用嵌入的智能助手。
5.1.1 后端python + Copilotkit LangGraph SDK
pip install copilotkit ... 
 import os from dotenv import load_dotenv load_dotenv() from fastapi import FastAPI import uvicorn from copilotkit.integrations.fastapi import add_fastapi_endpoint from copilotkit import CopilotKitRemoteEndpoint, LangGraphAgent from sample_agent.agent import graph app = FastAPI() sdk = CopilotKitRemoteEndpoint( agents=[ LangGraphAgent( name="sample_agent", description="一个模拟智能体", graph=graph, ) ], ) add_fastapi_endpoint(app, sdk, "/copilotkit") def main(): port = int(os.getenv("PORT", "8080")) uvicorn.run( "sample_agent.demo:app", host="0.0.0.0", port=port, reload=True, ) if __name__ == "__main__": main() 
5.1.2 前端React + Copilotkit React-ui
  1. 创建前端应用
npx create-next-app@latest 
  1. 集成Copilot SDK
npm install @copilotkit/react-ui @copilotkit/react-core npm install @copilotkit/runtime class-validator 
  1. 增加路由
... const runtime = new CopilotRuntime({ remoteEndpoints: [{url: "http://localhost:8080/copilotkit"},], }); exportconst POST = async (req: NextRequest) => { const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({ runtime, serviceAdapter, endpoint: "/api/copilotkit", }); return handleRequest(req); }; 
  1. 配置全局 CopilotKit 功能(agent是后端agent的名字)
<CopilotKit agent="sample_agent" runtimeUrl="/api/copilotkit" showDevConsole={false} > {children} </CopilotKit> 
  1. 增加Copilot界面,与Agent对话,实现智能交互体验。可以选择sidebar(边栏)、popup(弹出式)、chat(聊天)等多种UI形式。这里我们添加一个sidebar形式的Copilot到主页。
import { CopilotSidebar } from "@copilotkit/react-ui"; import { useCoAgent, useCoAgentStateRender,useCopilotAction ,useLangGraphInterrupt} from "@copilotkit/react-core"; export default function App() { return ( <> <Home/> <CopilotSidebar defaultOpen={true} instructions={"您应尽可能地帮助用户。请根据您拥有的数据以最佳方式回答问题。"} labels={{ title: "智能AI Copilot", initial: `# 👋 您好! 我是你的智能Copilot。演示功能: - **共享状态**: 搜索历史实时的展示 - **前端工具**: 调用前端工具打招呼 - **生成式UI**: 获取天气信息展示卡片 - **HITL流程**: 工具调用的人工审核` }}/> </> ); } 
5.1.3 工具调用(不仅可以调用后端设置的工具(比如搜索、访问数据库、MCP),还可以调用前端定义的UI“工具”(比如更改样式)
  1. 使用langchain_mcp_adapters.client 提供的MCPClient连接tavily-mcp,注册agent工具
from langchain_mcp_adapters.client import MultiServerMCPClient ... async def get_all_tools(): """ 统一的工具准备函数,避免重复初始化MCP客户端 Returns: list: 包含所有可用工具的列表 """ global _all_tools # 如果已经初始化过,直接返回 if _all_tools is not None: return _all_tools # 创建MCP客户端以获取搜索工具 try: client = MultiServerMCPClient( { "tavily-mcp": { "command": "npx", "args": ["-y", "tavily-mcp"], "env": {**os.environ}, "transport": "stdio" } } ) # 获取MCP工具 mcp_tools = await client.get_tools() _all_tools = mcp_tools + [get_weather] logger.info(f"工具初始化成功,可用工具: {[tool.name for tool in _all_tools]}") except Exception as e: logger.warning(f"⚠️ MCP工具初始化失败: {e}") # 如果MCP工具失败,只使用邮件工具 _all_tools = [get_weather] logger.info(f"使用备用工具: {[tool.name for tool in _all_tools]}") return _all_tools 
  1. 使用useCopilotAction hook来注册一个前端Action,创建一个前端Action向用户弹出简单的Alert消息和天气获取
... useCopilotAction({ name: "get_weather", description: "获取指定位置的天气信息。", available: "disabled", // 保持为disabled,确保不被当作前端工具 render: ({status, args, result}) => { return ( <p className="text-gray-500 mt-2"> {status !== "complete" && "Calling weather API..."} {status === "complete" && <WeatherCard location={args.location} result={result} themeColor="#3b82f6" />} </p> ); }, }); useCopilotAction({ name: "sayHello", // Action 名称,Agent 将通过此名称来调用工具 description: "向指定用户问好", // 对该 Action 的描述(供 Agent 理解用途) parameters: [ // 定义参数列表 { name: "name", type: "string", description: "要问好的对象名字" } ], render: "正在发送问候...", // (可选) 执行时在Chat中显示的提示文本 handler: async ({ name }) => { // 定义具体执行逻辑的函数(异步支持) alert(`Hello, ${name}!`); // 这里在浏览器弹出提示框 return('问候已发送给' + name); // 返回结果给agent } }); ... 
  1. 并将前端Action作为工具给Agent使用
 def should_continue(state: AgentState): last_message = state["messages"][-1] if not hasattr(last_message, 'tool_calls') or not last_message.tool_calls: return END # 检查工具调用是前端还是后端 tool_call_name = last_message.tool_calls[0].get("name") frontend_actions = state["copilotkit"]["actions"] is_frontend_action = any( action.get("name") == tool_call_name for action in frontend_actions ) # 如果是前端动作,则结束,让copilotkit前端处理 if is_frontend_action: return END else: # 否则,转到后端工具节点 return "tool_node" 
5.1.4 状态共享
  1. 定义Agent的State
class AgentState(CopilotKitState): search_history: list[dict] = [] 
  1. 增加搜索记录
... # 更新状态信息 updated_state = {"messages": response} # 如果是搜索工具,更新搜索历史 - 搜索开始阶段 if response.tool_calls[0].get("name") in ["tavily-search", "tavily-extract", "tavily-crawl"]: search_history = state.get("search_history", []) search_query = response.tool_calls[0].get("args", {}) # 创建搜索历史记录 - 开始时标记为未完成 search_record = { "query": search_query.get("query", ""), "completed": False, "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"), "tool_name": response.tool_calls[0].get("name") } logger.info(f"🔍 添加搜索查询到历史 (开始): {search_record}") search_history.append(search_record) updated_state["search_history"] = search_history return updated_state ... 
  1. 前端使用CopilotKit提供的useCoAgent这个hook函数,useCoAgentStateRender获取实时状态,
... const {state} = useCoAgent<AgentState>({ name: "sample_agent", initialState: { search_history: [] }, }) ... useCoAgentStateRender<AgentState>({ name: "sample_agent", render: ({ status, state, nodeName }) => { return ( <div> {state.search_history?.map((search, index) => ( <div key={index}> {search.completed ? "✅" : "❌"} 正在执行:{search.query} {search.completed ? "" : "..."} </div> ))} </div> ) }, }); ... const [localHistory, setLocalHistory] = useState<AgentState['search_history']>([]); useEffect(() => { if (state.search_history && state.search_history.length > 0 ) { const latestSearch = state.search_history[0]; if(latestSearch.query.length <=0){ return; } setLocalHistory(prevHistory => { if (prevHistory.length > 0 && prevHistory[prevHistory.length - 1].query === latestSearch.query) { const newHistory = [...prevHistory]; newHistory[prevHistory.length - 1] = latestSearch; return newHistory; } else { return [...prevHistory, latestSearch]; } }); } }, [state.search_history]); 
5.1.5 HITL(Human-in-the-loop)人工审核(人机协作)流程
  1. Agent增加中断环节
approval_request = { "type": "tool_approval_request", "tool_name": tool_call.get("name"), "tool_args": tool_call.get("args", {}), "tool_id": tool_call.get("id"), "timestamp": "2025-07-08" } # 拒绝 approve_status = interrupt(approval_request) if approve_status in ["rejected", "reject"]: .... # 如果审核通过,执行工具调用 elif approve_status in ["approved", "approve"]: .... 
  1. 前端增加中断反馈 hook
 useLangGraphInterrupt({ render: ({ event, resolve }) => { const { tool_name, tool_args } = event.value; return ( <div className="bg-gradient-to-br from-blue-50 to-indigo-50 border border-blue-200 rounded-2xl p-6 my-4 shadow-lg"> {/* 标题 */} <div className="flex items-center gap-3 mb-4"> <div className="w-10 h-10 bg-blue-100 rounded-full flex items-center justify-center"> <span className="text-lg">🔧</span> </div> <div> <h3 className="text-lg font-bold text-gray-800">工具调用审核</h3> <p className="text-sm text-gray-600">请确认是否执行以下工具调用</p> </div> </div> {/* 工具信息 */} <div className="bg-white rounded-xl p-4 mb-4 border border-gray-100"> <div className="grid grid-cols-1 gap-3"> <div> <label className="block text-xs font-medium text-gray-500 mb-1">工具名称</label> <div className="bg-gray-50 px-3 py-2 rounded-lg"> <code className="text-blue-600 font-mono text-sm">{tool_name}</code> </div> </div> <div> <label className="block text-xs font-medium text-gray-500 mb-1">参数</label> <div className="bg-gray-50 px-3 py-2 rounded-lg max-h-24 overflow-y-auto"> <pre className="text-xs text-gray-700 whitespace-pre-wrap font-mono"> {JSON.stringify(tool_args, null, 2)} </pre> </div> </div> </div> </div> {/* 操作按钮 */} <div className="mt-4"> <div className="flex gap-2"> <button type="button" onClick={() => resolve("approve")} className="flex-1 bg-green-500 hover:bg-green-600 text-white font-medium py-2 px-4 rounded-lg transition-colors duration-200 flex items-center justify-center gap-2 text-sm" > <span>✅</span> 通过 </button> <button type="button" onClick={() => resolve("reject")} className="flex-1 bg-red-500 hover:bg-red-600 text-white font-medium py-2 px-4 rounded-lg transition-colors duration-200 flex items-center justify-center gap-2 text-sm" > <span>❌</span> 拒绝 </button> </div> </div> </div> ); } }); 

5.2 nodejs示例

import express, {Request, Response} from 'express'; import dotenv from 'dotenv'; dotenv.config(); import {RunAgentInputSchema, RunAgentInput, EventType, Message} from '@ag-ui/core'; import {EventEncoder} from '@ag-ui/encoder'; import {v4 as uuidv4} from 'uuid'; import OpenAI from 'openai'; const app = express(); app.use(express.json()); app.post('/awp', async (req: Request, res: Response) => { console.log('app.post > req:'); try { // 解析请求体 const input: RunAgentInput = RunAgentInputSchema.parse(req.body); // 设置 SSE headers res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); const encoder = new EventEncoder(); // 发送 started 事件 const runStarted = { type: EventType.RUN_STARTED, threadId: input.threadId, runId: input.runId }; res.write(encoder.encode(runStarted)); // 初始化 OpenAI 客户端 const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); // 将 前端传入的 AG-UI 消息转换为 OpenAI 消息格式 const requestMessages = input.messages .filter((msg: Message) => ['user', 'system', 'assistant'].includes(msg.role)) .map((msg: Message) => ({ role: msg.role as 'user' | 'system' | 'assistant', content: msg.content || '' })); // 生成消息 ID const messageId = uuidv4(); // 发送 ‘文本消息开始’ 事件 const textMessageStart = { type: EventType.TEXT_MESSAGE_START, messageId, role: 'assistant' }; res.write(encoder.encode(textMessageStart)); // 创建流式传输完成请求 const stream = await client.chat.completions.create({ model: 'gpt-4o', messages: requestMessages, stream: true }); console.log('🚀 > app.post > stream:', stream); // 处理流并发送 ‘文本消息内容’ 事件 for await (const chunk of stream) { if (chunk.choices[0]?.delta?.content) { const content = chunk.choices[0].delta.content; const textMessageContent = { type: EventType.TEXT_MESSAGE_CONTENT, messageId, delta: content }; res.write(encoder.encode(textMessageContent)); } } // 发送 ‘文本消息结束’ 事件 const textMessageEnd = { type: EventType.TEXT_MESSAGE_END, messageId }; res.write(encoder.encode(textMessageEnd)); console.log('🚀 > app.post > TEXT_MESSAGE_END:'); // 发送 finished 事件 const runFinished = { type: EventType.RUN_FINISHED, threadId: input.threadId, runId: input.runId }; res.write(encoder.encode(runFinished)); console.log('🚀 > app.post > RUN_FINISHED:'); // 结束响应 res.end(); } catch (error) { res.status(422).json({error: 'Internal Server Error'}); } }); app.listen(3001, () => { console.log('Server running on http://localhost:3001'); }); 

六、总结

AG-UI 协议和 CopilotKit 框架代表了智能应用开发的新规范。它们不仅解决了 AI 集成的技术难题,更重要的是建立了一套标准化的开发模式,让每个开发者都能轻松构建智能应用。从前端工程师的角度,无需深究复杂的后端 AI 推理流程,只需使用熟悉的 React 组件和 Hooks,即可调动强大的AI为应用服务。从后端AI工程师的角度,你也无需操心前端展示,只要按照协议产出标准事件,UI 就会自动配合渲染。这种清晰的前后端职责分离与协同,使AI应用开发更加高效与标准化。

对于开发者:这意味着更高的开发效率和更低的学习成本
对于企业:这意味着更快的 AI 能力落地和更好的用户体验
对于用户:这意味着更自然的人机交互和更智能的应用体验


参考资源:

Read more

10分钟零代码!用OpenClaw搭建私人微信AI助理,彻底解放双手

10分钟零代码!用OpenClaw搭建私人微信AI助理,彻底解放双手

做了这么久AI应用落地,我被问得最多的问题就是:“能不能给我的微信整个AI助理,自动回消息、管日程、汇总群聊?” 说实话,这个需求我自己折腾了快两年,踩过的坑能绕开三圈: * 最早用itchat、wechaty写Python脚本,代码写了几百行,调试了半个月,结果用了不到3天,微信直接限制登录,差点把主号搞封了; * 后来用企业微信机器人,只能在企业群里用,个人微信、私域群完全用不了,局限性拉满; * 再后来试了市面上的第三方SaaS工具,要么是按月付费贵得离谱,要么是所有聊天数据都要传到人家服务器,客户信息、私人聊天全泄露了,根本不敢用; * 最头疼的是,所有方案都要写代码、调接口、搭环境,新手根本无从下手,就算是开发者,也要折腾好几天才能跑通。 直到我把OpenClaw部署落地后,这个问题被彻底解决了。不用写一行代码,不用研究微信协议,不用申请任何企业资质,10分钟就能搭好一个完全私有化的微信AI助理,消息自动回复、群聊汇总、日程提醒、待办管理全搞定,而且数据全在本地,大模型可以接本地开源的,完全不用担心隐私泄露,封号风险也降到了最低。 这篇文章,我就用保姆级的步骤

深度解析 MySQL 与 MCP 集成:从环境构建到 AI 驱动的数据交互全流程

深度解析 MySQL 与 MCP 集成:从环境构建到 AI 驱动的数据交互全流程

前言 在当前大语言模型(LLM)应用开发的浪潮中,MCP(Model Context Protocol)协议正在成为连接 AI 模型与本地数据设施的关键桥梁。本文将以 MySQL 数据库为例,详细拆解如何通过 MCP 协议让 AI 模型直接操作关系型数据库,涵盖从服务器发现、数据库架构设计、数据初始化、MCP 配置文件编写到复杂自然语言查询与写入的全过程。 第一部分:MCP 服务器的发现与配置获取 在进行任何数据交互之前,首要任务是确立连接协议与服务源。通过蓝耘 MCP 广场,开发者可以快速检索并获取所需的 MCP 服务器配置。 在搜索栏输入 mysql 关键字,系统会立即检索出相关的 MCP 服务器资源。如下图所示,搜索结果中清晰展示了 MySQL 对应的 MCP 服务卡片。 点击选中该 MCP 服务器后,

AI的提示词专栏:用 Prompt 生成正则表达式进行文本匹配

AI的提示词专栏:用 Prompt 生成正则表达式进行文本匹配

AI的提示词专栏:用 Prompt 生成正则表达式进行文本匹配 本文围绕 “用 Prompt 生成正则表达式” 展开,先阐述二者结合的价值,即降低正则使用门槛、提升效率并适配灵活场景;接着介绍正则核心基础,为精准描述 Prompt 打基础;随后详解 Prompt 设计的三大原则与四段式结构,确保模型生成精准正则;还通过匹配固定电话、提取 URL 域名等 5 个高频场景,提供完整 Prompt 示例、模型输出及验证分析;最后梳理常见问题与解决方案,并给出总结与扩展学习建议,整体为读者提供从需求描述到工具落地的完整指南,助力高效解决文本匹配问题。 人工智能专栏介绍     人工智能学习合集专栏是 AI 学习者的实用工具。它像一个全面的 AI 知识库,把提示词设计、AI 创作、智能绘图等多个细分领域的知识整合起来。无论你是刚接触 AI 的新手,还是有一定基础想提升的人,都能在这里找到合适的内容。

人工智能|大模型 —— 开发 —— opencode与agent skills的安装与使用

人工智能|大模型 —— 开发 —— opencode与agent skills的安装与使用

一、Skills下载源 常用的GitHub仓库: 1、https://github.com/anthropics/skills 2、https://github.com/nextlevelbuilder/ui-ux-pro-max-skill 3、https://github.com/hesreallyhim/awesome-claude-code 4、https://github.com/ComposioHQ/awesome-claude-skills Agent Skills市场: Agent Skills 市场 - Claude、Codex 和 ChatGPT Skills | SkillsMP Open Agent Skills Ecosystem: The Agent Skills Directory ClawHub: ClawHub 二、