本页介绍 Deep Agents 特有的 streaming 关注点,最重要的是通过 stream.subagents 从 delegated subagents 进行 streaming。对于通用 agent streaming(stream.messagesstream.values、tool calls、custom updates),请参阅 LangChain Event Streaming

Stream subagents

Deep Agents 在 LangGraph streaming 之上添加了 subagent projection。当你希望每个 delegated task call 都有一个 stream handle 时,请使用 stream.subagents。该 projection 很轻量:它会先发现 subagent tasks,只有当你在 subagent handle 上访问 message、tool-call 和 value streams 时才会打开它们。 每个 handle 的 name 都是 sub-agent 配置的 name:也就是 coordinator 调用 task tool 时传入的 subagent_type。Deep Agents 会将该 name 绑定到 delegated run,因此你在 subagent specs 中定义的同一 label,就是你在 stream 中用于 filter 和 route 的 label。
const stream = await agent.streamEvents(
  { messages: [{ role: "user", content: "Write me a haiku about the sea" }] },
  { version: "v3" }
);

for await (const subagent of stream.subagents) {
  console.log(subagent.name);
  console.log(await subagent.taskInput);

  for await (const message of subagent.messages) {
    console.log(await message.text);
  }
}

Subagent stream fields

每个 subagent stream 都会暴露与 parent run 相同类型的 projections,例如 messages、tool calls、nested subagents 和 final output。关于通用 parent-run streaming model,请参阅 LangChain Event Streaming TypeScript 使用 toolCallstaskInput 等 camelCase projection names。每个 subagent stream 都可以暴露 .messages.toolCalls.values.subagents.output
FieldDescription
nameSub-agent name,来自 coordinator 在其 task call 中选择的 subagent_type
messagesSubagent emitted messages。
subagentsNested subagent invocations。
outputFinal subagent state,或 delegated task 的 completion signal。
taskInput传给 task tool 的 prompt 对应的 Promise。
toolCalls作用域限定到 subagent 的 tool calls。

跟踪 subagent lifecycle

当你只需要显示哪些 subagents started 和 finished 时,请使用 stream.subagents。除非访问单个 subagent 上的这些 projections,否则不需要订阅 message 或 value streams。
const stream = await agent.streamEvents(input, { version: "v3" });

let running = 0;
let completed = 0;
let failed = 0;
const watchers: Promise<void>[] = [];

for await (const subagent of stream.subagents) {
  running += 1;
  console.log(`${subagent.name}: started`);

  watchers.push(
    subagent.output.then(
      () => {
        running -= 1;
        completed += 1;
        console.log(`${subagent.name}: completed`);
      },
      () => {
        running -= 1;
        failed += 1;
        console.log(`${subagent.name}: failed`);
      }
    )
  );
}

await Promise.all(watchers);
console.log({ running, completed, failed });

Stream messages

Deep Agents 可以从 coordinator agent 和 delegated subagents 发出 messages。对 top-level messages 使用 stream.messages,对每个 delegated subagent 使用 subagent.messages
const stream = await agent.streamEvents(input, { version: "v3" });

for await (const message of stream.messages) {
  console.log("[coordinator]", await message.text);
}

for await (const subagent of stream.subagents) {
  for await (const message of subagent.messages) {
    console.log(`[${subagent.name}]`, await message.text);
  }
}

Stream tool calls

Deep Agents 会在 agent tree 的每一层暴露 tool calls。对 coordinator tools 使用 top-level stream.tool_calls,对 delegated work 使用每个 subagent.tool_calls
const stream = await agent.streamEvents(input, { version: "v3" });

for await (const call of stream.toolCalls) {
  console.log("[coordinator tool]", call.name, call.input);
  console.log(await call.status);
}

for await (const subagent of stream.subagents) {
  for await (const call of subagent.toolCalls) {
    console.log(`[${subagent.name} tool]`, call.name, call.input);

    const status = await call.status;
    if (status === "finished") {
      console.log(await call.output);
    } else if (status === "error") {
      console.error(await call.error);
    }
  }
}

Stream nested work

你可以递归进入 subagent stream,以观察 nested subagents、messages 和 tool calls。
const stream = await agent.streamEvents(input, { version: "v3" });

for await (const subagent of stream.subagents) {
  console.log(`subagent ${subagent.name}: started`);

  for await (const toolCall of subagent.toolCalls) {
    console.log(`${toolCall.name}(${JSON.stringify(toolCall.input)})`);

    const status = await toolCall.status;
    if (status === "finished") {
      console.log(await toolCall.output);
    } else if (status === "error") {
      console.error(await toolCall.error);
    }
  }

  for await (const nested of subagent.subagents) {
    console.log(`nested subagent ${nested.name}: started`);
  }
}

并发消费

Coordinator 和 subagent output 经常交错。当需要 live UI updates 时,请并发消费 projections。 在 JavaScript 中使用 concurrent consumers:
const stream = await agent.streamEvents(input, { version: "v3" });

await Promise.all([
  (async () => {
    for await (const message of stream.messages) {
      console.log("[coordinator]", await message.text);
    }
  })(),
  (async () => {
    for await (const subagent of stream.subagents) {
      void (async () => {
        for await (const message of subagent.messages) {
          console.log(`[${subagent.name}]`, await message.text);
        }
      })();
    }
  })(),
]);
当你需要 coordinator 和所有 subagents 之间的精确 arrival order 时,请遍历 raw protocol events,并使用 namespace 识别来源:
const stream = await agent.streamEvents(input, { version: "v3" });

for await (const event of stream) {
  if (event.method !== "messages") continue;

  const data = event.params.data;
  if (data.event !== "content-block-delta") continue;

  const block = data.delta ?? {};
  if (block.type === "text-delta") {
    const isSubagent = event.params.namespace.some((seg) => seg.startsWith("tools:"));
    const source = isSubagent ? "subagent" : "coordinator";
    console.log(`[${source}] ${block.text}`);
  }
}

Subagents 与 subgraphs

stream.subgraphs 显示 graph execution structure。stream.subagents 显示 product-level Deep Agents task delegations。对于 user-facing UI,请使用 stream.subagents,因为它会隐藏 internal graph nodes,并直接暴露 subagent concept。

相关