在开发 Go Agent 框架 Covonaut 的过程中,我意识到一个核心问题:对于有界面的 Agent 产品,仅返回最终答案是远远不够的。用户希望看到模型正在生成什么、调用了哪些工具、经历了怎样的推理过程。为了解决这个问题,我给 Covonaut 实现了 AG-UI(Agent-User Interaction Protocol)协议。这是由 CopilotKit 开源的一套协议,核心价值在于将一次 Agent 运行过程拆解为细粒度的事件流,通过 SSE 实时推送到浏览器,让前端的渲染与后端的思考同频。
一次运行,就是一串事件流AG-UI 的灵魂是事件流。在 Covonaut 的实现中,我将 Agent 的运行状态映射为以下几类标准事件:
生命周期:RUN_STARTED / RUN_FINISHED / RUN_ERROR,清晰标记运行的起止与异常;文本增量:TEXT_MESSAGE_START → CONTENT → END。其中 CONTENT 是 token 级别的增量,前端收到即可追加渲染,实现打字机效果;工具调用:从 TOOL_CALL_START 到 RESULT,连参数传递都是增量式的,确保工具执行过程透明可见;推理过程:THINKING_START/END 包裹文本增量,专门适配支持原生推理预算的模型,展示“思维链”;状态同步:通过 STATE_SNAPSHOT / DELTA 及 MESSAGES_SNAPSHOT,将对话或自定义状态实时同步给前端;步骤边界:STEP_STARTED/FINISHED 以 turn_1、turn_2 命名,帮助前端将长运行拆解为可视化的步骤进度条或折叠面板。Covonaut 的 AG-UI 模块本质上是一个翻译层,在框架内部事件与 AG-UI 标准事件之间做映射。无论后端跑的是哪个模型、编排了多少个 Agent,前端只需按统一的事件类型渲染,彻底解耦了视图与逻辑。
Thread 与 Run,让对话可恢复AG-UI 明确区分了两个概念:Thread**(一段连续对话)和 Run(该对话中的一次执行)。Covonaut 沿用了这一模型,请求携带 threadID,同一 Thread 下的多次 Run 共享上下文。
这带来了一个极其实用的特性:状态可恢复。如果某个 Thread 之前已有运行记录且状态持久化到了 Store 中,新一轮 Run 启动前,系统会先推送 MESSAGES_SNAPSHOT。这意味着即使刷新页面,界面也能瞬间恢复到上次的对话,长对话场景至关重要。
能力协商,运行前先“对表”除了事件流,AG-UI 还引入了能力声明机制。Agent 在运行前会主动暴露自己支持的能力维度,包括传输方式、工具集、输出形态、多 Agent 协作、推理模式、Human-in-the-loop 等。
前端拿到这份声明后,就能动态决定渲染哪些交互组件,要不要展示工具面板,是否启用人工干预按钮等。这种“先对齐再运行”的设计,有效避免了前端假设了后端不具备的能力而导致的体验断层。
Human-in-the-loop,让 Agent 可控当 Agent 遇到需要确认的关键节点时,运行会以包含中断信息(interrupt)的结果暂停。前端捕获后展示确认界面,用户的决策再通过 Resume 接口回灌,Agent 随即继续执行。这正是能力声明中 Human-in-the-loop 的具体落地,也是构建安全、可控 Agent 的基石。
CUSTOM 事件,透传框架内部信号AG-UI 规范覆盖了通用场景,但 Covonaut 在实际运行中还会产生一些特有的内部信号。为了不丢失这些信息,我利用 CUSTOM 事件进行透传,前端按 name 字段区分即可。目前主要包含三类:
多 Agent 交接:记录控制权流转,包含源/目标 Agent、交接模式及耗时,让多智能体编排过程可视化;上下文压缩:当对话接近窗口上限(默认 0.75)触发自动压缩时,实时反馈压缩前后的 Token 数、裁剪消息条数及耗时,让用户感知到系统的“自我瘦身”;自动重试:遇到限流或偶发错误时,透传重试次数、最大重试数及退避等待时间,提升系统的透明度。此外,任何未被显式映射的内部事件都会自动落入 CUSTOM 通道直接透出,确保信息零丢失。
小结把 Agent 的运行过程抽象为标准事件流,前端才能真正“接得住”复杂的智能体交互。另外,Go 全能 Agent 框架 covonaut 的 GitHub 仓库是 covoyage/covonaut。
让前端看得见 Agent 的思考过程,Covonaut 框架中的 AG...
在开发 Go Agent 框架 Covonaut 的过程中,我意识到一个核心问题:对于有界面的 Agent 产品,仅返回
阅读:0
点赞:0