Skip to content
预计 1 分钟右侧目录可快速定位

Agent 事件怎么推给前端:SSE、WebSocket 与 Event Stream ​

前置:长任务 API 用普通 REST 还是 Streaming HTTP
核心问题:前端怎样持续看到 Agent 事件,同时在断线重连后不丢事件、不重复解释顺序?

先按“通信方向”选 Transport ​

如果前端主要订阅 /runs/{id}/events 接收 model/tool/status,而审批、取消等命令通过普通 POST 提交,通信主体是 server→client,SSE 通常更简单。实时语音、远程终端这类需要持续双向低延迟消息的场景,WebSocket 才更自然。

SSE ​

事件应有 type/id 并处理代理缓冲/重连。

SSE 是基于 HTTP 的服务端→客户端文本事件流,浏览器支持简单、自动重连,适合 Agent status/token stream。它是单向通道,不适合高频双向交互。

WebSocket ​

WebSocket 提供持久双向 channel,适合实时双向控制;需要额外 heartbeat、backpressure、reconnect/session 设计。

代价是连接状态、心跳、重连、扩容和代理配置更复杂。

Agent Event Stream ​

定义领域事件如 run.started/model.delta/tool.started/node.completed,而不是把 provider 原始 event 直接暴露给前端。

事件流应定义 typed event schema、sequence/id、run correlation 和 terminal event,避免前端解析任意日志字符串。事件是观察视图,不应成为唯一 durable state。

Resumable Event Stream:重连后从哪里继续 ​

长 Run 的浏览器连接必然会断。真正需要恢复的不是 socket,而是事件消费位置。事件 envelope 至少应提供稳定 event_id 或单 Run 单调 sequence:

text
run_id = r-123
sequence = 184
type = tool.completed
occurred_at = ...
payload = ...

客户端重连时携带最后确认位置,服务端从 durable event projection 补发后续事件;如果保留窗口已经过期,就先返回当前 Run snapshot,再从新的 cursor 继续。重复收到同一 event_id 时 UI 应幂等应用。

这里解决的是“观察流如何续上”。客户端断线是否要取消 Run,属于下一篇的 Runtime cancellation 语义。

SSE 和 WebSocket 怎么选 ​

如果客户端主要是“服务端不断推 Run event”,SSE 通常更简单:天然单向、基于普通 HTTP、浏览器支持事件重连语义。若客户端和服务端需要长期双向低延迟消息,例如远程终端、实时 computer-use control,WebSocket 更自然。

不要让 transport 决定内部事件模型。内部可以统一成:

json
{
  "run_id": "r-42",
  "seq": 318,
  "type": "tool.completed",
  "timestamp": "...",
  "payload": {"tool_call_id":"tc-9","status":"SUCCEEDED"}
}

SSE 只是把它编码成 event stream,WebSocket 则把同一 envelope 放进 frame。这样以后切 transport、同时支持 Web 和 CLI,Runtime 都不需要知道连接细节。

还要区分可丢的“体验事件”和必须可恢复的“系统事件”:token delta 丢几个通常可以接受,但 approval.requested、run.failed、artifact ready 等关键事件应能从 durable event log 或当前 state 重建。

Failure Modes ​

单向事件流无理由使用 WebSocket ​

症状: 只需 server→client 推送却承担双向连接复杂度。

为什么危险: 运维、代理兼容和重连更复杂。

处理: 单向优先 SSE/streaming HTTP;持续双向低延迟才用 WebSocket。

如何验证 ​

Case断言
单向事件流无理由使用 WebSocket比较两种实现的断线重连/代理兼容/状态复杂度。
客户端从旧 cursor 重连关键状态事件不丢失;重复 event_id 不造成 UI 状态重复推进。

自测 ​

  1. 只需要服务端持续推送 Run event,客户端几乎不反向发送消息。SSE 与 WebSocket 哪个更简单,为什么?
  2. 断线重连后如何避免前端既漏事件又重复处理?event id/offset 应承担什么作用?

Sources ​

AI Engineering · Agent · Harness · Backend Systems