langchain.js(包括langgraph和deepagents)中流式输出核心解决的是Agent/LLM 实时输出、运行进度、工具调用、自定义业务进度、模型思考链实时打印,分为传统 stream() 多模式 和 新版推荐 streamEvents(v3) 事件流式 两套 API。
一、总览:Streaming 的核心价值
LLM 推理存在网络延迟,一次性返回完整回答会造成用户长时间空白;Streaming 实现逐块实时推送,大幅提升交互体验。 LangChain JS 流式系统支持四类实时数据输出:
- Agent 每一步运行状态变更(工具调用、LLM 节点切换)
- LLM 逐 Token 文本输出
- 模型内部思考/推理 reasoning 片段实时推送
- 开发者自定义业务进度日志(如“正在查询数据库 10/100”)
文档重点提示:LangChain v1.3 推荐 Event Streaming(streamEvents + version:v3),替代传统
stream()多分支判断;它把消息、工具调用、子图、最终状态拆成独立迭代器,无需通过streamMode判断数据类型,代码更简洁。
二、三种基础 Stream Mode(stream() 方法使用)
调用 agent.stream(inputs, { streamMode: 模式 }),支持单模式或数组多模式并发。
| streamMode | 输出内容 | 适用场景 |
|---|---|---|
updates | 每一个 Agent 节点执行后的状态增量更新;同一轮多个节点会分多次推送 | 展示 Agent 运行流程:LLM 请求工具 → 工具返回结果 → 最终回答 |
messages | LLM 生成的逐 Token + 元数据元组 (token, metadata),包含节点名称、子图标识 | 聊天打字动画、实时输出模型回答、提取 reasoning 思考内容 |
custom | 开发者在 Tool/Graph 节点内主动推送自定义字符串/对象,依赖 config.writer | 业务进度、中间查询日志、自定义提示信息 |
1. updates:流式 Agent 执行进度
Agent 调用工具的完整推送链路(三步):
- LLM 节点:携带 tool_call 的 AIMessage
- Tool 节点:工具执行结果 ToolMessage
- 最终 LLM 节点:整合工具数据后的完整回答
配套关键配置:
configurable.thread_id:对话持久化 ID,必须搭配MemorySaver记忆存储,实现多轮对话断点续跑- 支持 OpenAI / Anthropic / Gemini / Ollama / OpenRouter / Fireworks / Baseten 全模型厂商
示例代码核心逻辑:
const agent = createAgent({
model: "openai:gpt-5.5",
tools: [getWeather],
checkpointer: new MemorySaver(), // 持久化对话必须
});
const config = { configurable: { thread_id: crypto.randomUUID() } };
// streamMode="updates" 监听节点状态变更
const stream = await agent.stream(input, { ...config, streamMode: "updates" });
2. messages:逐 Token 流式 LLM 输出
返回格式 [token, metadata],metadata 携带 langgraph_node(当前执行节点)。
适用场景:纯聊天、不需要看工具进度,只实时打印文字。
for await (const [token, metadata] of await agent.stream(input, { streamMode: "messages" })) {
console.log("当前节点:", metadata.langgraph_node);
console.log("输出片段:", token.contentBlocks);
}
3. custom:自定义业务流式日志
在 Tool 函数入参增加 config: LangGraphRunnableConfig,调用 config.writer?.("自定义内容") 向外推送日志。
限制:工具脱离 LangGraph 运行时(单独调用)会报错,必须在 Agent 图流程内执行。
const getWeather = tool(async (input, config: LangGraphRunnableConfig) => {
config.writer?.(`正在查询城市:${input.city}`); // 自定义流输出
config.writer?.(`城市数据获取完成`);
return `天气晴朗`;
}, schema);
// 消费自定义流
for await (const chunk of agent.stream(input, { streamMode: "custom" })) {
console.log("业务日志:", chunk);
}
4. 多模式并发:同时监听进度、Token、自定义日志
streamMode 传入数组 ["updates", "messages", "custom"],返回统一格式 [mode, chunk],通过第一个字段区分数据类型:
for await (const [streamMode, chunk] of agent.stream(input, {
streamMode: ["updates", "messages", "custom"]
})) {
if (streamMode === "messages") { /* 打印token */ }
if (streamMode === "updates") { /* 节点进度 */ }
if (streamMode === "custom") { /* 业务日志 */ }
}
三、新版 Event Streaming(streamEvents,官方推荐 v3)
核心优势(对比旧 stream())
- 无需
streamMode分支判断,内置独立迭代器:stream.messages:所有 LLM 文本/思考 Tokenstream.toolCalls:所有工具调用请求与返回结果stream.output:Promise,等待全流程结束获取最终完整状态
- LangChain v1.3 标准化类型投影,自动归一化各厂商模型的 reasoning 思考块
- 天然支持子图、多工具并行场景,前端交互最友好(文档推荐新项目优先使用)
完整示例(同时打印文字+实时打印工具调用)
const stream = await agent.streamEvents(input, { ...config, version: "v3" });
// 并行两个异步循环:打印文字 + 打印工具调用
await Promise.all([
// 1. 流式输出文本
(async () => {
for await (const message of stream.messages) {
for await (const token of message.text) {
process.stdout.write(token);
}
}
})(),
// 2. 监听工具调用全过程
(async () => {
for await (const call of stream.toolCalls) {
console.log(`\n调用工具:${call.name} 参数:`, call.input);
console.log(`工具返回结果:`, await call.output);
}
})(),
]);
const finalState = await stream.output; // 等待全部执行完成
四、高级场景:流式模型思考链(reasoning tokens)
部分模型(Claude、深度思考类开源模型)会先输出内部推理过程再生成答案,LangChain 统一标准化为 type:"reasoning" 内容块,两种获取方式:
方式1:streamEvents v3(推荐)
// Claude 开启思考预算
const model = new ChatAnthropic({
model: "claude-sonnet-4-6",
thinking: { type: "enabled", budget_tokens: 5000 },
});
const agent = createAgent({ model, tools });
const stream = await agent.streamEvents(input, { version: "v3" });
for await (const msg of stream.messages) {
// 实时打印思考片段
for await (const thinkToken of msg.reasoning) {
process.stdout.write(`[思考]${thinkToken}`);
}
// 打印最终回答文字
for await (const textToken of msg.text) {
process.stdout.write(textToken);
}
}
方式2:旧 messages 模式过滤 contentBlocks
遍历 token.contentBlocks,判断 block.type === "reasoning" 提取思考内容。
五、禁用流式输出
部分场景需要一次性完整返回,关闭单模型流式:
- 标准 OpenAI 等模型:
streaming: false
import { ChatOpenAI } from "@langchain/openai";
const model = new ChatOpenAI({ model: "gpt-5.5", streaming: false });
- 不支持
streaming参数的小众模型:使用基类通用配置disableStreaming: true
适用场景:
- 多 Agent 系统中,控制部分子 Agent 不实时推送
- LangSmith 部署,屏蔽敏感模型输出到前端
六、配套关键概念与依赖
1. Checkpointer 记忆持久化
使用 thread_id 保存对话历史必须配置 checkpointer:
- 本地开发:
new MemorySaver()(内存存储,重启丢失) - LangSmith 云端部署:自动预置持久化存储,无需手动传入
2. createAgent 嵌入子图
若把 Agent 作为父 StateGraph 的节点:
- 传入
agent.graph而不是 agent 实例 - 流式开启
subgraphs: true,保证子图 Token 携带命名空间,区分父子节点输出
七、相关拓展文档(文档末尾 Related)
- Frontend streaming:React
useStreamHook,前端实时渲染流式对话 - Streaming with chat models:不使用 Agent,纯 ChatModel 基础流式
- Reasoning with chat models:模型思考链完整配置指南
- Standard content blocks:统一内容块规范(text/reasoning/tool_call)
- Streaming with human-in-the-loop:流式 + 人工审核中断
- LangGraph streaming:底层图流式完整高级参数(values/debug/checkpoints 模式)
八、stream() vs streamEvents(version:"v3") 选型总结
| 场景 | 推荐 API |
|---|---|
| 新项目、前端交互、需要同时拿 Token + 工具调用 | streamEvents v3 |
| 简单脚本,仅监听 LLM 文字输出 | stream({streamMode:"messages"}) |
| 仅监控 Agent 执行步骤,不展示文字 | stream({streamMode:"updates"}) |
| 需要自定义业务进度日志 | stream custom 模式 / streamEvents 搭配 writer |
| 兼容旧 LangGraph 代码、复杂多分支逻辑 | 传统 stream 多模式 |
九、完整执行流程示例(用户提问查天气)
- 用户输入:sf 的天气
- streamEvents.toolCalls 捕获 get_weather 工具调用,打印参数 city=San Francisco
- 工具内部 writer 推送自定义日志(custom 流)
- 工具执行完成返回 ToolMessage
- streamEvents.messages 同时输出模型思考链 + 最终回答逐字 Token
- stream.output 等待全部结束,拿到完整对话状态用于保存/二次处理