人们说MCP的下一步时AG-UI,那么AG-UI到底是什么呢?
其实看他的定义就知道,代理+前端。我最近开发时应用时发现Cursor对前端的支持很糟糕,我需要新的工具和方法!!
以下是一些AG-UI的尝试,希望能帮助我解决这一难题。
什么是AG-UI
AG-UI(Agent-User Interaction Protocol)的开源协议由CopilotKit提供,你可以把它想象成一套“通用语言”,专门用来解决AI代理和前端应用之间的沟通难题。

简单来说,AG-UI就像是在AI代理和你的App界面之间搭了一座“鹊桥”!我喜欢这个想法,不管它好用与否,他就是我需要的。
https://docs.agentwire.io/introduction 。
https://github.com/ag-ui-protocol/ag-ui
这是它的官方信息
AG-UI的优点
1、实时代币流
2、工具使用进度
3、状态差异和补丁
4、错误和生命周期事件
5、多代理切换
它的架构很重要,也就是说:前端既是代理又是UI。让它可以自动交互。我开发一个产品如果调用一个MCP还需要多种方法验证是否真实的调用和返回数据,如果它能解决我的问题,那我就可以节约很多时间。

目前尽管多步骤代理工作流(multi-step agentic workflows)很强大,把代理放到app时还是会遇到一些问题,人们常提到的场景有:
1、当想逐个令牌地传输 LLM 响应,而无需构建自定义 WebSocket 服务器
2、实时显示工具执行进度,并在不阻断或丢失上下文的情况下暂停以等待人工反馈
3、同步大型、不断变化的对象(例如代码或表格),而无需将所有内容重新发送到 UI
4、允许用户在代理运行过程中中断、取消或回复,而不会丢失上下文
而且每个代理后端有自己的工具调用机制、ReAct规划、状态差异(state diff)、输出格式等等。比如使用LangGraph时,前端会实现自定义的WebSocket逻辑、复杂的JSON以及LangGraph专用的UI适配——如果要迁移到CrewAI,这一切必须要因地制宜对应地调整。可扩展性的缺乏可见一斑。
**随着我对CURSOR的使用,我实在太爱这个产品了,我认为它代表着AI Agent的产品的未来的方向。**想做出这样的AI应用产品,工具的进化是必不可少的。
截至目前它能支持的Framework有:

如何使用AG-UI
我这边先放一个官网的例子,我也准备用它开发一些好玩的玩意,之后单开一个板块吧。
直接在代理框架中实施 AG-UI 事件
在本教程中,您将学习如何构建与 AG-UI 协议兼容的 HTTP 端点。
Prerequisites 先决条件
确保已安装 Python 和 Poetry。Poetry 是一款用于 Python 依赖性管理和打包的工具
https://python-poetry.org/docs/#installing-with-pipx
或者pipx 可以安装不同版本的 Poetry,语法与 pip 相同
1 2
| pipx install --suffix=@1.8.4 poetry==1.8.4 poetry@1.8.4 --version
|
用Poetry创建新项目
首先,让我们创建一个新项目,并为依赖关系管理设置 Poetry:
1
| poetry new my-endpoint && cd my-endpoint
|
Install Dependencies 安装依赖项
1
| poetry add ag-ui openai fastapi uvicorn
|
使用 FastAPI 创建基本端点
创建一个名为 my_endpoint/main.py 的新文件,其中包含以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13
| from fastapi import FastAPI, Request import json from ag_ui.core.types import RunAgentInput
app = FastAPI(title="AG-UI Endpoint")
@app.post("/awp") async def my_endpoint(): return { "message": "Hello World" }
if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)
|
运行并测试终端
用以下命令启动服务器
1
| poetry run uvicorn my_endpoint.main:app --reload
|
在另一个终端中,使用 curl 测试终端是否正在运行:
1
| curl -X POST http://localhost:8000/awp
|
您应该会看到如下回复:
1
| { "message": "Hello World" }
|
解析 AG-UI 输入
接下来,让我们更新端点,使用 RunAgentInput Pydantic 模型正确解析传入的 AG-UI 请求:
1 2 3 4 5 6 7 8 9 10
| from fastapi import FastAPI, Request, HTTPException from ag_ui.core import RunAgentInput, Message
app = FastAPI(title="AG-UI Endpoint")
@app.post("/awp") async def my_endpoint(input_data: RunAgentInput): thread_id = input_data.thread_id
return { "message": "Hello World from " + thread_id }
|
FastAPI 会根据 RunAgentInput 模式自动验证传入的请求。如果请求与预期格式不符,它将返回 422 验证错误,并详细说明出错的原因。
添加事件流 Add Event Streaming
AG-UI 支持使用服务器发送事件(SSE)进行事件流处理,跟MCP是一样的。让我们修改 /awp 端点,将事件流传回客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| from fastapi import FastAPI, Request, HTTPException from fastapi.responses import StreamingResponse from ag_ui.core import RunAgentInput, Message, EventType, RunStartedEvent, RunFinishedEvent from ag_ui.encoder import EventEncoder
app = FastAPI(title="AG-UI Endpoint")
@app.post("/awp") async def my_endpoint(input_data: RunAgentInput): async def event_generator(): encoder = EventEncoder()
yield encoder.encode( RunStartedEvent( type=EventType.RUN_STARTED, thread_id=input_data.thread_id, run_id=input_data.run_id ) )
yield encoder.encode( RunFinishedEvent( type=EventType.RUN_FINISHED, thread_id=input_data.thread_id, run_id=input_data.run_id ) )
return StreamingResponse( event_generator(), media_type="text/event-stream" )
if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)
|
太棒了!我们已经在发送 RunStartedEvent 和 RunFinishedEvent 事件,这为我们提供了一个基本的 AG-UI 兼容端点。现在,让我们让它做些有用的事情。
Implementing Basic Chat 实现基本聊天
让我们增强我们的端点,以调用 OpenAI 的 API 并将响应作为 AG-UI 事件流传回去:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| from fastapi import FastAPI, Request from fastapi.responses import StreamingResponse from ag_ui.core import ( RunAgentInput, Message, EventType, RunStartedEvent, RunFinishedEvent, TextMessageStartEvent, TextMessageContentEvent, TextMessageEndEvent ) from ag_ui.encoder import EventEncoder import uuid from openai import OpenAI
app = FastAPI(title="AG-UI Endpoint")
@app.post("/awp") async def my_endpoint(input_data: RunAgentInput): async def event_generator(): encoder = EventEncoder()
yield encoder.encode( RunStartedEvent( type=EventType.RUN_STARTED, thread_id=input_data.thread_id, run_id=input_data.run_id ) )
client = OpenAI()
message_id = uuid.uuid4()
yield encoder.encode( TextMessageStartEvent( type=EventType.TEXT_MESSAGE_START, message_id=message_id, role="assistant" ) )
stream = client.chat.completions.create( model="gpt-3.5-turbo", messages=openai_messages, stream=True )
for chunk in stream: if hasattr(chunk.choices[0].delta, "content") and chunk.choices[0].delta.content: content = chunk.choices[0].delta.content yield encoder.encode( TextMessageContentEvent( type=EventType.TEXT_MESSAGE_CONTENT, message_id=message_id, delta=content ) )
yield encoder.encode( TextMessageEndEvent( type=EventType.TEXT_MESSAGE_END, message_id=message_id ) )
yield encoder.encode( RunFinishedEvent( type=EventType.RUN_FINISHED, thread_id=input_data.thread_id, run_id=input_data.run_id ) )
return StreamingResponse( event_generator(), media_type="text/event-stream" )
if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000) )
return StreamingResponse( event_generator(), media_type="text/event-stream" )
if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)
|
您需要将 OpenAI API 密钥设置为环境变量,然后重启服务器:
1 2
| export OPENAI_API_KEY=your-api-key poetry run uvicorn my_endpoint.main:app --reload
|
该实施方案创建了一个功能齐全的 AG-UI 端点,可实时处理信息并回传响应流。
动手试试吧