欢迎光临
我们一直在努力

DeepAgents + AG-UI:让 Agent 从后端执行走向真正的前端交互

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */
#content_views .toc,
/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */
#content_views.markdown_views > p:empty:has(+ .toc),
#content_views.markdown_views > .toc + p:empty,
/* 富文本旧版目录标记 */
#content_views.htmledit_views #main-toc,
#content_views.htmledit_views #hr-toc,
#content_views.htmledit_views p[id*=\”-toc\”] {
display: none !important;
}
/* 目录去掉后,紧跟的首个标题不再多出一块上边距 */
#content_views.markdown_views > .toc + h1,
#content_views.markdown_views > .toc + h2,
#content_views.markdown_views > .toc + h3,
#content_views.markdown_views > .toc + h4,
#content_views.markdown_views > .toc + p:empty + h1,
#content_views.markdown_views > .toc + p:empty + h2,
#content_views.markdown_views > .toc + p:empty + h3,
#content_views.markdown_views > .toc + p:empty + h4 {
margin-top: 0 !important;
}

一、一个容易被忽略的问题:Agent 做完了,用户却不知道它做了什么

开发 Agent 应用时,我们通常把大量精力放在后端:

  • 如何让 LLM 规划任务?
  • 如何调用工具、执行任务?
  • 如何管理上下文和记忆?
  • 如何实现多 Agent 协作?
  • 如何处理任务中断和异常恢复?

但当 Agent 真正接入业务系统时,还有一个问题绕不开:

前端如何感知 Agent 的执行过程?

假设我们开发了一个企业级 AI 研究助手。

用户输入:

帮我调研国内 RAG 技术的发展情况,整理主要厂商、技术路线和市场趋势,最后生成一份报告。

后端 Agent 可能需要经历:

  • 分析用户需求
  • 制定研究计划
  • 拆分子任务
  • 调用搜索工具
  • 汇总检索结果
  • 分析和整理材料
  • 生成研究报告
  • 如果前端只收到最终结果,用户看到的就是一个不断转圈的等待界面。

    问题在于,Agent 并不是一个简单的 API 请求。它是一个持续运行、可能调用多个工具、甚至需要人工介入的执行过程。

    传统的请求-响应模式,很难完整表达这种交互关系。

    LangChain 在 DeepAgents 文档中介绍了一个解决方案:AG-UI(Agent User Interaction Protocol)。

    它的核心思路是:

    把 Agent 的执行过程转换为标准化事件流,让前端能够实时接收消息、工具调用、状态变化和任务生命周期事件。

    这也是本文重点讨论的内容。

    二、AG-UI 到底是什么?

    AG-UI 全称 Agent User Interaction Protocol,是一个开放、轻量级、基于事件的协议。

    它主要解决的问题是:

    如何建立 Agent 后端与用户界面之间的标准化通信机制。

    可以把它理解为 Agent 与前端之间的一层交互协议。

    传统模式:

    用户
    |
    v
    前端发送 HTTP 请求
    |
    v
    Agent 后端执行任务
    |
    v
    返回最终结果
    |
    v
    前端展示结果

    AG-UI 模式:

    用户
    |
    v
    前端应用
    |
    v
    AG-UI 协议
    |
    v
    Agent Runtime
    |
    +—- LLM 推理
    |
    +—- 工具调用
    |
    +—- 子 Agent
    |
    +—- 状态更新
    |
    v
    持续产生事件
    |
    v
    AG-UI
    |
    v
    前端实时更新界面

    两者最大的区别:

    传统模式关注最终响应,AG-UI 关注整个执行过程。

    例如 Agent 正在调用搜索工具,前端可以立即收到工具调用事件;Agent 更新了任务计划,前端也可以同步更新任务列表。

    用户不必等到 Agent 完成全部工作,才能知道发生了什么。

    三、不要把 AG-UI、MCP、A2A 和 ACP 混为一谈

    LangChain 的 DeepAgents 文档将几种协议的职责划分得比较清楚。

    协议主要解决的问题连接对象
    AG-UI Agent 如何与用户交互 Agent ↔ 前端
    MCP Agent 如何使用外部工具 Agent ↔ 工具服务
    A2A Agent 如何与其他 Agent 协作 Agent ↔ Agent
    ACP Agent 如何连接代码编辑器等开发环境 Agent ↔ IDE

    这里需要特别注意:

    MCP 不是 AG-UI 的替代品。

    MCP 解决的是工具接入问题,例如 Agent 调用搜索服务、数据库或第三方 API。

    AG-UI 解决的是前端交互问题,例如前端如何知道 Agent 正在调用哪个工具、任务执行到哪一步、是否需要用户确认。

    两者处于不同的技术层次。

    如果把一个完整的 Agent 应用拆开来看:

    • MCP 负责工具连接。
    • A2A 负责 Agent 之间的协作。
    • AG-UI 负责 Agent 与用户界面的交互。
    • ACP 负责 Agent 与开发工具环境的交互。

    它们可以组合使用,而不是相互竞争。

    四、AG-UI 最重要的技术机制:事件流

    这是理解 AG-UI 的重点。

    AG-UI 并不是简单地把 Agent 的输出文字通过 SSE 推送给前端。

    它定义了多种具有明确语义的事件类型。

    根据 LangChain 文档,主要事件可以分成以下几类。

    1. 任务生命周期事件

    RUN_STARTED
    RUN_FINISHED
    RUN_ERROR

    表示一次 Agent 执行任务的开始、结束和异常。

    例如:

    RUN_STARTED
    |
    | Agent 开始执行
    |
    RUN_FINISHED

    前端可以利用这些事件管理:

    • 加载状态
    • 执行状态
    • 任务完成提示
    • 异常处理

    注意,任务完成不一定意味着用户已经拿到了最终答案。某些场景下,Agent 可能是因为等待人工输入而暂停。

    2. 节点执行事件

    STEP_STARTED
    STEP_FINISHED

    这两个事件用于表示图执行过程中的节点进度。

    如果使用 LangGraph 构建 Agent,可以利用这些事件让前端感知执行进度。

    例如:

    STEP_STARTED: research
    STEP_FINISHED: research

    STEP_STARTED: analysis
    STEP_FINISHED: analysis

    STEP_STARTED: report
    STEP_FINISHED: report

    前端可以把它展示为:

    研究资料 已完成
    分析材料 已完成
    生成报告 执行中

    这样用户就不再面对一个无法解释的等待过程。

    3. 消息事件

    TEXT_MESSAGE_START
    TEXT_MESSAGE_CONTENT
    TEXT_MESSAGE_END

    这组事件负责处理 Agent 的文本输出。

    其中:

    • START:消息开始。
    • CONTENT:文本内容增量。
    • END:消息结束。

    例如:

    TEXT_MESSAGE_START

    TEXT_MESSAGE_CONTENT
    delta = "根据本次调研"

    TEXT_MESSAGE_CONTENT
    delta = "发现以下几个趋势"

    TEXT_MESSAGE_END

    前端可以逐步拼接 delta,实现类似 ChatGPT 的流式输出。

    一个值得注意的细节:

    消息事件和任务生命周期事件不是一回事。

    一次 Agent Run 可能产生多条消息,也可能包含多次工具调用。

    因此,前端不能简单地认为一次 Run 就对应一条完整消息。

    4. 工具调用事件

    TOOL_CALL_START
    TOOL_CALL_ARGS
    TOOL_CALL_END
    TOOL_CALL_RESULT

    这组事件对于 Agent 产品非常重要。

    以搜索 Agent 为例:

    TOOL_CALL_START
    tool = web_search

    TOOL_CALL_ARGS
    query = "国内 RAG 技术发展"

    TOOL_CALL_END

    TOOL_CALL_RESULT
    result = 搜索结果

    前端就可以展示:

    正在调用搜索工具
    搜索关键词:国内 RAG 技术发展
    搜索完成,正在整理结果

    这里有个工程上的细节:

    工具调用的参数、调用结束和工具返回结果是不同的事件,不应该全部当作普通文本处理。

    如果前端想展示工具执行卡片,就需要根据工具调用 ID 和事件类型进行关联。

    5. 状态同步事件

    STATE_SNAPSHOT
    STATE_DELTA

    这是我认为 AG-UI 很值得关注的一组设计。

    为什么?

    因为复杂 Agent 不只是产生文本,还会持续修改内部状态。

    例如:

    {
    "todos": [
    {
    "task": "收集行业资料",
    "status": "completed"
    },
    {
    "task": "分析技术路线",
    "status": "in_progress"
    },
    {
    "task": "生成报告",
    "status": "pending"
    }
    ]
    }

    如果每次状态变化都发送完整数据,会产生不必要的数据传输。

    AG-UI 提供了两种机制:

    STATE_SNAPSHOT:完整状态快照。

    前端先获取一个完整的状态基线。

    STATE_DELTA:增量状态更新。

    后续只发送发生变化的部分。

    文档明确指出,STATE_DELTA 使用 JSON Patch(RFC 6902)表达增量变化。

    例如:

    原始状态:

    {
    "research": "pending",
    "analysis": "pending"
    }

    发生变化后:

    [
    {
    "op": "replace",
    "path": "/research",
    "value": "completed"
    }
    ]

    前端只需要应用这次变更,不必重新接收整个状态对象。

    对于多步骤 Agent、任务列表、子 Agent 状态展示,这种机制很实用。

    6. 对话历史事件

    MESSAGES_SNAPSHOT

    用于同步当前对话消息的完整快照。

    它与实时消息增量事件承担不同职责:

    • MESSAGES_SNAPSHOT:同步已有消息。
    • TEXT_MESSAGE_CONTENT:接收正在生成的文本。

    实际开发中,需要同时考虑历史消息初始化和新消息实时更新。

    五、DeepAgents 如何接入 AG-UI?

    下面结合官方文档,走一遍基本接入过程。

    这里有一个容易忽略的地方:

    DeepAgents 使用 Python 构建 Agent,但官方快速接入示例中的 @ag-ui/langgraph 适配器是 TypeScript 包。

    也就是说,Python Agent 和 AG-UI 适配器并不一定要写在同一个语言环境里。

    整体结构:

    Python
    |
    v
    DeepAgents
    |
    v
    LangGraph Graph
    |
    v
    LangGraph Server
    |
    v
    @ag-ui/langgraph
    |
    v
    AG-UI Client
    |
    v
    前端界面

    第一步:安装 Python 依赖

    pip install deepagents "langgraph-cli[inmem]"

    如果使用 uv:

    uv add deepagents "langgraph-cli[inmem]"

    第二步:创建 DeepAgent

    新建 agent.py:

    from deepagents import create_deep_agent

    agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    system_prompt="You are an expert researcher.",
    )

    这里使用 create_deep_agent 创建一个 DeepAgent。

    它本质上是一个 LangGraph Graph,可以通过 LangGraph Server 对外提供服务。

    实际项目中,可以继续配置工具、子 Agent、Middleware、Backend 等能力。

    第三步:配置 LangGraph Server

    项目根目录创建 langgraph.json:

    {
    "dependencies": ["."],
    "graphs": {
    "deep_agent": "./agent.py:agent"
    },
    "env": ".env"
    }

    其中:

    • dependencies:项目依赖。
    • graphs:注册需要对外提供服务的 Graph。
    • env:环境变量文件。

    启动服务:

    langgraph dev

    默认开发服务地址:

    http://localhost:2024

    至此,Python DeepAgent 已经通过 LangGraph Server 暴露出来。

    第四步:接入 AG-UI 适配器

    在 TypeScript 项目中安装对应依赖:

    npm install @ag-ui/langgraph

    创建 Agent:

    import { LangGraphAgent } from "@ag-ui/langgraph";

    const agent = new LangGraphAgent({
    graphId: "deep_agent",
    deploymentUrl: "http://localhost:2024",
    });

    这里有两个关键参数:

    graphId

    必须与 langgraph.json 中注册的 Graph 名称一致。

    deploymentUrl

    指向 LangGraph Server 的地址。

    这样就建立了 TypeScript AG-UI 适配器与 Python DeepAgent 之间的连接。

    第五步:监听 Agent 事件

    下面是一个简化的事件监听示例:

    import { LangGraphAgent } from "@ag-ui/langgraph";

    const agent = new LangGraphAgent({
    graphId: "deep_agent",
    deploymentUrl: "http://localhost:2024",
    initialMessages: [
    {
    id: "1",
    role: "user",
    content: "Research the AG-UI protocol."
    }
    ]
    });

    await agent.runAgent(
    {},
    {
    onTextMessageContentEvent({ event }) {
    process.stdout.write(event.delta);
    },

    onToolCallStartEvent({ event }) {
    console.log(
    "[tool]",
    event.toolCallName
    );
    },

    onStateSnapshotEvent({ event }) {
    console.log(
    "[state]",
    event.snapshot
    );
    },

    onRunFinishedEvent() {
    console.log("[done]");
    }
    }
    );

    这段代码主要演示四件事:

  • 初始化 DeepAgent 连接。
  • 设置初始用户消息。
  • 监听文本增量事件。
  • 监听工具调用和状态快照。
  • 这里的 onTextMessageContentEvent 可以实现文本实时输出。

    onToolCallStartEvent 可以让前端知道 Agent 正在调用什么工具。

    onStateSnapshotEvent 则可以接收 Agent 的完整状态。

    实际业务开发中,可以把这些事件进一步映射到 Vue 或 React 的响应式状态中。

    六、比事件监听更重要的是:Human-in-the-loop

    如果 Agent 只能执行任务、推送消息,那么它仍然只是一个能够实时展示过程的应用。

    但企业级 Agent 往往需要人参与决策。

    例如:

    • 发送邮件之前需要用户确认。
    • 执行数据库修改之前需要审批。
    • 生成合同之前需要人工检查。
    • 执行高风险操作之前需要授权。

    这就涉及 Human-in-the-loop(人在回路)。

    DeepAgents 支持通过 interrupt 暂停执行,等待人工输入,然后恢复任务。

    AG-UI 负责把这个交互过程传递到前端。

    官方文档提供了一个值得注意的配置:

    const agent = new LangGraphAgent({
    graphId: "deep_agent",
    deploymentUrl: "http://localhost:2024",
    emitInterruptOutcome: true,
    });

    开启 emitInterruptOutcome 后,可以在 RUN_FINISHED 事件中获取结构化的中断结果:

    outcome.type === "interrupt"

    这里要注意:

    Agent 暂停等待人工确认时,Run 可能已经结束当前这次执行,但不代表整个业务任务已经完成。

    接下来需要向 Agent 发送 resume 信息。

    例如:

    const input = {
    threadId: "t1",
    runId: "r2",
    messages: [],
    resume: [
    {
    interruptId: "int-abc",
    status: "resolved",
    payload: {
    approved: true
    }
    }
    ]
    };

    这里几个字段需要理解:

    • threadId:对应的对话线程。
    • runId:对应的执行记录。
    • interruptId:需要处理的中断标识。
    • status:中断处理状态。
    • payload:人工提交的处理结果。

    这意味着前端不再只是一个聊天窗口,还可以成为 Agent 的任务审批入口。

    例如:

    Agent:已经生成客户报价单。

    系统:等待人工确认。

    用户:
    [确认发送]
    [修改报价]
    [取消任务]

    Agent:收到确认,继续执行。

    这才是企业 Agent 真正需要的交互能力。

    七、LangGraphAgent 提供了哪些 API?

    官方文档还介绍了 LangGraphAgent 的几个主要方法。

    方法作用
    runAgent() 执行 Agent,并通过回调接收事件
    subscribe() 注册持续订阅者,跨多次 Run 接收事件
    abortRun() 取消当前正在执行的任务
    addMessage() 添加一条消息
    setMessages() 设置消息列表

    其中值得关注的是 subscribe() 和 abortRun()。

    subscribe()

    普通 runAgent 的 subscriber 主要针对当前这次执行。

    而 subscribe() 可以注册持续监听器,在多次 Run 中持续接收事件。

    适合需要统一管理事件的应用。

    abortRun()

    允许主动取消正在执行的任务。

    例如用户发现任务方向不对,可以点击停止按钮。

    前端调用 abortRun(),而不是简单地关闭聊天窗口。

    这两个 API 对构建真正可用的 Agent 工作台很有价值。

    八、从工程角度看,AG-UI 带来了什么?

    读完官方文档,我认为 AG-UI 的价值主要体现在三个方面。

    1. 降低 Agent 后端与前端的耦合

    以前开发 Agent 前端,往往需要针对后端的执行逻辑设计一套专用接口。

    比如:

    POST /agent/run
    GET /agent/status
    GET /agent/result
    POST /agent/approve
    POST /agent/cancel

    不同 Agent 框架、不同执行引擎,接口设计可能完全不同。

    AG-UI 通过标准化事件,减少了前端对具体 Agent 框架内部实现的依赖。

    前端主要关注:

    • 事件类型
    • 事件数据
    • 状态变化
    • 消息更新

    后端则负责把自己的执行过程转换成符合协议的事件。

    2. Agent 从聊天机器人走向任务工作台

    一个普通聊天机器人,前端主要需要展示消息。

    一个复杂 Agent,前端需要展示的东西明显更多:

    前端能力对应事件或机制
    实时消息 TEXT_MESSAGE_CONTENT
    工具执行过程 TOOL_CALL_*
    任务进度 STEP_*
    任务状态 RUN_*
    Todo 列表 STATE_SNAPSHOT / STATE_DELTA
    对话历史 MESSAGES_SNAPSHOT
    人工审批 Interrupt / Resume
    停止任务 abortRun()

    这也解释了为什么复杂 Agent 不能只靠一个 Chat UI。

    用户真正需要的是一个能够观察、控制和管理任务的交互界面。

    3. 为多 Agent 应用提供统一的前端交互基础

    假设一个企业 Agent 系统有:

    • 需求分析 Agent
    • 数据检索 Agent
    • 文档处理 Agent
    • 报告生成 Agent

    这些 Agent 可能由不同的节点和工具组成。

    如果每个 Agent 都采用自己的前端通信格式,后续维护会越来越复杂。

    通过统一事件协议,可以让前端以相对一致的方式处理不同 Agent 的执行信息。

    当然,这并不意味着 AG-UI 自动解决了多 Agent 调度、任务依赖和状态一致性问题。

    这些仍然需要 Agent Runtime 和业务系统负责。

    九、实际项目中需要注意的几个问题

    协议解决了通信标准化问题,但不代表接入之后就能直接满足生产要求。

    我认为有几个地方值得提前设计。

    1. 不要把所有事件都直接展示给用户

    后端执行事件和用户需要看到的信息不是一回事。

    例如工具参数可能包含内部数据、访问令牌或敏感业务信息。

    应该设计事件过滤和展示映射层。

    另外,文档中存在 REASONING 相关事件类型,也不意味着应该把模型的私有推理过程直接展示给用户。产品界面更适合展示经过整理的执行状态、操作摘要和可验证结果。

    2. 正确处理状态快照和增量更新

    STATE_SNAPSHOT 和 STATE_DELTA 需要配合使用。

    前端需要维护一份本地状态,并按照 JSON Patch 规则应用增量更新。

    如果事件丢失、顺序错乱或者客户端重新连接,就需要考虑状态恢复机制。

    不能简单地把每个 STATE_DELTA 当作一份完整状态。

    3. 做好任务与事件关联

    生产环境中通常会有多个用户、多个会话、多个任务同时执行。

    需要正确管理 threadId、runId、消息 ID、工具调用 ID 和 interruptId。

    否则很容易出现任务状态串线、消息显示错误等问题。

    4. 把人工审批作为业务流程,而不是前端按钮

    人工审批不只是前端弹出一个确认框。

    后端必须保证中断状态可以持久化、审批结果可以追踪、恢复执行时能够关联原来的任务。

    涉及付款、发送、删除、数据修改等操作时,还应该增加服务端权限校验和幂等控制。

    5. 生产环境还要考虑鉴权和部署

    官方示例使用本地 LangGraph 开发服务,适合快速验证。

    真正上线时,还需要处理:

    • 用户身份认证
    • Graph 访问权限
    • 服务端与前端的跨域配置
    • 多用户并发
    • 长时间任务管理
    • 断线重连
    • 事件持久化
    • 异常恢复

    这些不是 AG-UI 自动替你完成的。

    十、我的理解:Agent 工程正在从模型调用转向运行时与交互系统

    以前我们开发 AI 应用,关注点主要是:

    Prompt
    |
    v
    LLM
    |
    v
    Response

    后来引入 RAG、Function Calling 和 Agent:

    用户
    |
    v
    Agent
    |
    +—- LLM
    |
    +—- Tools
    |
    +—- RAG
    |
    v
    执行结果

    现在,随着 DeepAgents、LangGraph 等框架逐渐支持更复杂的任务执行,Agent 的工程形态也在发生变化。

    一个完整的 Agent 应用,需要考虑:

    用户交互层
    |
    v
    AG-UI
    |
    v
    Agent Runtime
    |
    +—- 任务规划
    |
    +—- 上下文管理
    |
    +—- 工具执行
    |
    +—- 子 Agent
    |
    +—- 状态管理
    |
    +—- Human-in-the-loop
    |
    v
    业务系统与外部服务

    从这个角度看,AG-UI 的意义并不只是让聊天界面支持流式输出。

    它让 Agent 的执行过程拥有了标准化的表达方式。

    对于未来的 Agent 产品,前端可能不再只是一个输入框和消息列表,而是一个真正的任务交互界面。

    用户可以看到 Agent 在做什么,可以检查执行结果,可以修改计划,可以中断任务,也可以在关键节点参与决策。

    Agent 不应该只是回答问题,还应该能够执行任务;而一个成熟的 Agent 产品,也不能只展示答案,还应该让用户能够理解、监督和控制执行过程。

    赞(0)
    未经允许不得转载:171主机测评 » DeepAgents + AG-UI:让 Agent 从后端执行走向真正的前端交互
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址