1. 结论先行

在 MCP / AI Agent 场景里,很多框架从 SSE 转向 Streamable HTTP,核心原因不是 SSE 不能用,而是:

随着 Agent 交互从“单纯吐文本”升级为“多阶段、多类型、可恢复、可协商”的复杂协议,SSE 作为一种固定事件流格式开始显得过窄,而 Streamable HTTP 更适合作为统一传输层。

更直白地说:

2. 先看背景:MCP / AI Agent 到底改变了什么

2.1 早期 LLM streaming 的本质很简单

早期大模型接口的 streaming,本质上往往只有一件事:

  • 用户发请求
  • 模型逐 token 或逐 chunk 输出文本
  • 服务端持续推给客户端

这种模式下,SSE 非常贴切:

  • 服务端单向输出
  • 文本天然适配
  • 浏览器可直接消费
  • 实现和调试都简单

所以很多早期模型 API、前端 Demo、聊天界面都大量采用 SSE。

2.2 Agent 场景把“输出”变成了“会话协议”

到了 Agent 阶段,请求/响应不再只是“生成一段文字”,而是变成:

这意味着传输层承载的不再只是“文本流”,而是 协议消息流 。

而协议消息流通常有这些特征:

  • 消息类型多
  • 内容结构复杂
  • 顺序要求严格
  • 需要错误语义
  • 可能需要 resume / retry
  • 需要兼容浏览器、服务端、CLI、代理层

这就是很多框架转向 Streamable HTTP 的直接背景。

3. 为什么 SSE 在 Agent 场景里开始显得不够用

这里的“不够用”通常不是绝对不能实现,而是 实现成本、协议表达力和工程兼容性越来越差 。

3.1 SSE 天然偏向“服务端事件推送”,不擅长承载复杂协议

SSE 设计初衷是:

  • 服务端持续推送事件
  • 客户端订阅并消费

它适合:

  • message
  • progress
  • done

这类事件模型。

但在 Agent / MCP 场景中,消息可能变成:

虽然这些也能硬塞进 SSE 的 event: + data: 里,但随着消息类型和字段复杂度增长,SSE 就逐渐退化成:

  • 外层是 SSE
  • 内层真正协议还是自定义 JSON

这时 SSE 提供的价值就越来越少,反而成了额外包裹层。

3.2 SSE 过于绑定文本事件格式

SSE 的消息边界与字段语义是固定的,例如:

  • event:
  • data:
  • id:
  • retry:

这带来两个问题:

  1. 真正业务语义只能塞进 data
    也就是你最后还是要定义自己的 JSON envelope。

  2. 协议演进不够自然
    一旦想支持更复杂的 chunk 语义、分片、对象边界、嵌套内容块,就会越来越像“借 SSE 外壳承载另一套协议”。

对于现代 Agent 框架来说,它们更想直接定义:

  • 每个 chunk 的 schema
  • chunk 之间的关系
  • 哪些块可增量,哪些块必须完整
  • 如何结束
  • 如何恢复

这类需求下,Streamable HTTP 更自然,因为它只要求“HTTP 上能持续读写”,不强加事件格式。

3.3 浏览器友好,但非浏览器生态不一定最优

SSE 一个很大优势是浏览器里有 EventSource。但 MCP / Agent 的调用方并不只在浏览器:

这些客户端很多并不会把 EventSource 当作最佳抽象,反而更常见的是:

  • fetch
  • 原生 HTTP client
  • ReadableStream
  • async iterator
  • chunk reader

对这类调用方,Streamable HTTP 往往比 SSE 更统一:

  • 同一个请求方式
  • 同一套认证头
  • 同一套 HTTP 中间件
  • 同一种 body 流读取模型

因此从“全栈兼容性”看,很多框架更愿意把 fetch + streaming body 作为基础面。

3.4 SSE 对请求控制能力较弱

在浏览器里,EventSource 的请求能力相对有限,典型限制包括:

  • 自定义请求方法不灵活
  • 请求 body 支持弱
  • 请求控制能力不如 fetch
  • 中间层处理和高级控制不够统一

而 Agent / MCP 请求常常并不是简单 GET 订阅,它可能需要:

这种情况下,fetch 发 POST 再读取响应流,比 EventSource 模型更顺手。Streamable HTTP 正好与这种用法天然一致。

3.5 SSE 的“单向”心智模型不适合多阶段 Agent 交互

虽然很多 Agent 框架的单次响应依然是服务端到客户端单向流,但整个系统交互往往是:

  • 客户端发起请求
  • 服务端开始流式返回
  • 客户端可能取消
  • 客户端随后提交 tool result
  • 服务端继续后续阶段
  • 中间可能 resume

这不一定要求 WebSocket,但确实说明:

  • 系统需要的是 围绕 HTTP 的可编排会话交互
  • 而不是单纯的“订阅一个事件流”

Streamable HTTP 更容易和普通 HTTP 端点统一建模,例如:

  • POST /responses
  • 返回流式 body
  • POST /responses/{id}/cancel
  • POST /responses/{id}/tool_result
  • GET /responses/{id}

这类 API 设计比“所有东西都挂在 SSE 流里”更清晰。

4. 为什么 Streamable HTTP 更适合 MCP / Agent

4.1 它把“传输层”和“消息协议层”解耦了

这是最核心的一点。

使用 Streamable HTTP 时,框架通常会采用这样的分层:

  • 传输层:HTTP + streaming body
  • 消息层:JSON chunk / NDJSON / framed message / typed event object
  • 业务层:tool call、delta、checkpoint、final output

这样做好处很大:

  • HTTP 只负责传输
  • 协议格式可独立演进
  • SDK 可对 chunk 做高层封装
  • 不必被 SSE 语法限制

换句话说,框架从 “SSE is the protocol” 转成 “HTTP streaming is the transport, protocol is ours”。

这正是 Agent 框架成熟的标志。

4.2 更适合结构化输出和多模态内容

现代 Agent 输出的不只是文本,还可能包含:

如果继续用 SSE,常见做法是:

  • event: message
  • data: {复杂 JSON}

本质上已经是“用文本事件包 JSON 事件对象”。

而 Streamable HTTP 可以更直接地表达:

  • 一块就是一个 JSON object
  • 每行一个对象
  • 或按 framing 协议输出对象序列

这对 SDK 解析、类型系统建模、错误处理都更友好。

4.3 更适合服务间调用、网关和代理透传

MCP / Agent 往往会经过多层链路:

  • client SDK
  • API gateway
  • agent runtime
  • tool router
  • model provider adapter
  • observability / tracing 中间件

在这类链路里,大家通常都已经围绕普通 HTTP request/response 做了很多基础设施:

Streamable HTTP 更容易直接复用这些设施。

尤其在服务间调用中,统一成“一个普通 POST + 流式响应 body”通常比“专门处理 SSE 事件语法”更简单。

4.4 更利于 SDK 抽象一致化

Agent 框架通常希望 SDK 层提供类似这样的统一接口:


或者:


如果底层是 Streamable HTTP,SDK 可以:

  • 在 JavaScript 中映射为 ReadableStream
  • 在 Python 中映射为 iterator / async generator
  • 在 Go 中映射为 decoder loop
  • 在 Java 中映射为 reactive stream / input stream

这比依赖 SSE 的浏览器式模型更便于跨语言统一。

4.5 更适合“一个 API,多种返回模式”

很多现代框架希望同一个接口支持:

  • 非流式返回
  • 流式返回
  • JSON 模式
  • 结构化模式

Streamable HTTP 更容易做到接口统一:

  • 同一个 endpoint
  • 同一个请求 schema
  • 通过参数或 header 决定是否 stream

例如:

  • stream=false:返回完整 JSON
  • stream=true:返回分块 JSON stream

这在 SDK、文档、版本演进上都更整洁。

而 SSE 往往暗示一种特定响应类型:text/event-stream。一旦协议要兼容更多模式,SSE 的外形就没那么优雅了。

5. 放到 MCP 语境里看,转向更明显

5.1 MCP 关注的是“模型与工具/上下文之间的标准交互”

MCP 的重点不是“浏览器怎么收事件”,而是:

  • 模型怎么发现工具
  • 怎么调用工具
  • 怎么交换结构化上下文
  • 怎么保持协议兼容
  • 怎么跨宿主、跨语言、跨运行时工作

因此它天然更看重:

  • 协议清晰
  • 传输可替换
  • 客户端多样性
  • 工程一致性

在这个方向上,SSE 更像一种可选包装;Streamable HTTP 更像一种更中立的承载层。

5.2 MCP / Agent 场景中,消息往往不是“给人看”,而是“给程序消费”

SSE 非常适合把人类可理解的事件流推给前端界面,例如:

  • “正在思考”
  • “正在调用工具”
  • “已完成”

但 MCP 更多时候传的是给程序消费的结构化协议消息。

程序消费更关注:

  • schema 稳定性
  • 可类型化
  • 可校验
  • 可版本化
  • 可恢复

这些维度上,Streamable HTTP + structured chunks 通常比 SSE + data JSON 更规范。

5.3 MCP 生态强调“宿主无关”

MCP 连接的宿主可能是:

  • 桌面应用
  • 编辑器
  • 本地 Agent runtime
  • 云端编排器
  • CLI
  • 后端服务

既然宿主并不局限在浏览器,使用浏览器色彩更浓的 SSE 作为默认主通道,就不一定是最优选择。采用更中性的 Streamable HTTP,能降低生态绑定。

6. 一个非常直观的对比

6.1 用 SSE 做 Agent streaming,通常长这样

外层:


event: message data: {"type":"tool_call_started","tool":"search"}

再来一条:


event: message data: {"type":"tool_call_delta","delta":"..."}

再来一条:


event: done data: {"type":"final","output_text":"..."}

你会发现:

  • 真正协议在 JSON 里
  • SSE 只是承担“分条发出去”的作用

6.2 用 Streamable HTTP 做 Agent streaming,通常会变成


{"type":"tool_call_started","tool":"search"} {"type":"tool_call_delta","delta":"..."} {"type":"final","output_text":"..."}

或者别的 framing 形式。

这样做的好处是:

  • 少一层 SSE 包装
  • 协议对象更直接
  • SDK 更容易映射为类型对象
  • 服务间透传更简单

所以很多框架的真实思路是:

如果最终还是要定义一套自己的 chunk schema,那不如直接使用更通用的 Streamable HTTP 来承载。

7. 这并不意味着 SSE 过时了

这里需要特别区分: “默认主通道发生变化” ,不等于 “SSE 没价值” 。

SSE 仍然非常适合这些场景:

  • 浏览器前端直接接模型输出
  • 快速实现聊天打字机效果
  • 简单进度流
  • 轻量后台任务通知
  • 人类可读的事件输出

所以实际工程里常见的是:

  • 底层核心协议使用 Streamable HTTP
  • 面向 Web UI 再适配成 SSE
  • 或同时支持两种模式

也就是说,很多框架不是完全“抛弃 SSE”,而是把它从“协议核心”降级成“前端友好的适配层”。

8. 转向背后的工程动机,可归纳为 6 点

8.1 从“文本流”升级到“协议流”

Agent 不只是输出字,而是在交换状态、指令和结构化事件。

8.2 从“浏览器优先”升级到“多宿主优先”

调用方不只是网页,还包括 IDE、CLI、服务端和运行时。

8.3 从“事件展示”升级到“程序消费”

消费方更需要 typed chunks,而不是仅适合展示的 event text。

8.4 从“固定格式”升级到“协议可演进”

框架需要更自由地定义 chunk schema、错误语义和恢复机制。

8.5 从“单接口 streaming”升级到“完整会话编排”

需要与 cancel、resume、tool result submit、checkpoint 等 API 协同。

8.6 从“前端实现便利”升级到“全链路工程一致性”

网关、代理、SDK、多语言客户端都更容易围绕普通 HTTP 流构建。

9. 一句话总结两代思路

可以把它概括成下面这组变化:

  • SSE 时代 :重点是“把模型输出实时显示出来”
  • Streamable HTTP 时代 :重点是“把 Agent 协议稳定、统一、可扩展地传输出来”

前者偏 UI streaming,后者偏 protocol streaming。

10. 最终总结

在 MCP / AI Agent 场景里,很多框架从 SSE 转向 Streamable HTTP,本质上是因为系统复杂度上升后,框架需要的已经不只是“服务器持续推事件”,而是:

  • 一种更中立的 HTTP 流式承载层
  • 一套可演进的结构化消息协议
  • 更好的跨语言、跨宿主兼容性
  • 更自然的服务间调用和 SDK 抽象
  • 更方便承载 tool call、delta、state、error、resume 等 Agent 原语

所以这不是简单的“谁性能更高”,而是 协议分层与工程适配方式发生了变化 :

  • SSE 更像前一阶段 AI 产品中非常实用的流式展示方案
  • Streamable HTTP 更适合当前 MCP / Agent 体系下,把复杂交互当作正式协议来建设
Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐