Claude Agent SDK 提供两种输入模式,流式输入(Streaming Input)被官方明确标为 default 与 recommended,而单消息输入(Single Message)只是用于无状态场景的备用通道。流式模式之所以被推荐,关键在于它对工具集成、实时反馈、上下文持久化三件事提供了完整支持,而这三点恰好对应 Agent Loop 的核心目标。
一、两种输入模式的本质差异
两种模式共享底层模型与工具,但运行形态截然不同:
| 维度 | 流式输入模式 | 单消息输入模式 |
|---|---|---|
| 会话形态 | 长生命周期进程 | 一次性查询 |
| 多轮对话 | 自然延续 | 需显式 session 管理 |
| 工具/MCP | 完整访问 | 部分受限 |
| 实时反馈 | 边生成边推送 | 阻塞到完成 |
| 上下文保持 | 自动跨轮 | 需手动 resume |
| 适用场景 | 交互式 Agent、IDE、自动化 | 无状态函数、批处理 |
核心区别在于:流式模式把 Agent 视为一个常驻服务,单消息模式把它视为一个 RPC 调用。前者能完整表达 Agent Loop 的所有能力。
二、工具集成对齐 Agent Loop 的执行层
Agent Loop 的执行层负责”模型推理 → 工具调用 → 观察结果 → 再推理”。流式模式在执行层的对齐体现在三处:
- 工具全开放:会话期内可访问所有内置工具与自定义 MCP 服务器,无须在每次调用时重新声明;
- Hooks 钩子:可在工具调用前后插入生命周期钩子,做权限校验、日志埋点、结果改写;
- 权限请求:模型主动弹出权限请求(permission request),由宿主程序拦截决策,而不是一次性放行。
单消息模式因为会话即结束,Hooks 与中途权限请求都失去意义,所以官方直接砍掉。流式模式保留这两点,让 Agent Loop 里的”工具执行 + 治理”完整可写。
下面是一段工具声明的最小示例。allowedTools 一次性声明后,整个会话期内都生效:
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "扫描 src 下所有 .ts 文件并报告未使用的导出",
options: {
maxTurns: 5,
allowedTools: ["Read", "Grep", "Bash"]
}
})) {
if (message.type === "result") {
console.log(message.result);
}
}
效果:模型可在同一会话内连续 Read → Grep → Bash,无需宿主程序反复握手。注意 allowedTools 之外的工具会被静默拒绝,宿主无须在每轮再做 ACL 判断。
三、实时反馈对齐 Agent Loop 的流式渲染
流式模式的”流”指两件事:一是宿主端能拿到字符级增量,二是模型可边推理边暴露中间状态。Agent Loop 的可视化体验完全依赖这两点。
| 反馈层级 | 流式模式 | 单消息模式 |
|---|---|---|
| 文本增量 | 逐 chunk 推送 | 等待完整 result |
| 工具调用过程 | 实时暴露 | 不暴露 |
| 中间推理 | 可选展示 | 不展示 |
| 取消/中断 | 任意时刻触发 | 不支持 |
把渲染层对齐到流式的好处是:用户能看到模型”在做什么”,而不是盯着空白等待数十秒。流式模式下,宿主可在模型调用 Grep 时立即渲染”正在搜索…”,调用 Read 时渲染文件路径,调用结果返回后再渲染实际内容。这种粒度在单消息模式下做不到。
实现上,宿主只需 for await 遍历消息流,按 message.type 分发到不同 UI 组件:
for await (const message of query({ prompt, options })) {
switch (message.type) {
case "assistant":
ui.appendText(message.content);
break;
case "tool_use":
ui.showToolCall(message.name, message.input);
break;
case "tool_result":
ui.showToolResult(message.output);
break;
case "result":
ui.markComplete(message.result);
break;
}
}
效果:UI 与模型并行推进,体感延迟从”等一个完整 result”压到”等第一个 token”。中间环节一旦出错,宿主也可立即终止流。
四、上下文持久化对齐 Agent Loop 的状态层
Agent Loop 的状态层关心”上一轮决定的事,这一轮还能不能用到”。流式模式天然保留这一特性:
- 同一会话内,模型可见全部历史消息与工具结果;
- 消息排队(queued messages)允许用户在模型未完成时连续发问,由 SDK 顺序消费;
- 跨会话可显式 resume 或 fork,旧上下文按需继承。
单消息模式需要宿主自己用 continue: true 之类参数维护 session 句柄,一旦宿主进程重启或换容器,状态就可能丢失。流式模式把这些都内化到 SDK 里,开发者只关心业务流。
按官方描述,流式模式”allows the agent to operate as a long-lived process that takes in user input, handles interruptions, surfaces permission requests, and handles session management”——四件事都是 Agent Loop 的常规动作,单消息模式天然不能同时承载。
五、为什么”被推荐”是工程结论,不是营销话术
把视角拉远看,三件事是同构的:
- 工具集成回答”能不能动手”;
- 实时反馈回答”动手过程可不可见”;
- 上下文持久化回答”动手结果能不能复用”。
Agent Loop 要稳定运行,缺一件就崩。流式模式同时满足三件,单消息模式一件都不完整。”default & recommended”是工程结果倒推的标签,不是品牌口号。
实际选型时,记住这条经验法则:只要宿主进程能维持一个长连接(IDE 插件、桌面应用、长跑服务、CLI 交互),就应当用流式模式;只有无状态函数(CI 一次性脚本、Serverless lambda、批处理入口)才回退到单消息模式。混用会让状态层断档,是常见的返工来源。
常见问题(FAQ)
Q1:流式模式一定比单消息模式好吗?
不一定。无状态环境(如 Serverless 函数)根本没有长连接可用,单消息模式更省心。
Q2:Hooks 必须用流式模式才能挂载吗?
是。官方文档明确把 Hooks 列为流式模式独有能力,单消息模式不支持。
Q3:消息排队会不会和中断冲突?
不会。队列里的后续消息可在用户触发时整体被取消,已开始处理的那一条可单独中断。