# Seems like streaming with multiple agents is totally broken

**URL:** <https://forum.langchain.com/t/seems-like-streaming-with-multiple-agents-is-totally-broken/3073>\
**Category:** LangChain\
**Tags:** js-help\
**Created:** [March 4, 2026, 6:18pm UTC](https://forum.langchain.com/t/seems-like-streaming-with-multiple-agents-is-totally-broken/3073 "2026-03-04T18:18:44Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![george32](https://yyz1.discourse-cdn.com/flex007/user_avatar/forum.langchain.com/george32/32/2527_2.png) [@george32](https://forum.langchain.com/u/george32)\
**Post date:** [March 4, 2026, 6:18pm UTC](https://forum.langchain.com/t/seems-like-streaming-with-multiple-agents-is-totally-broken/3073/1 "2026-03-04T18:18:44Z")

</div>

I am using typedscript sdk to create main agent which uses tool call (lets imagine ask\_subagent).  
This tool creates separate new agent using “createAgent“ function.

Both agents (main and subagent) use stream() method with “messages“ stream mode.

The problem is no matter how I was trying to isolate output of both agents I am getting interleaved responses.  
I even used `await new Promise(resolve => setTimeout(resolve, 5000));` before returning “ask\_subagent“ tool call result to the main agent but it still prints messages generated by sug-agent while sub-agent is working.

I have only two ideas:

1. Bun runtime stdout is broken
2. You reuse some global state while streaming responses.

What’s goind on why I am getting duplicate messages like “ This This is is a a …“

---

<div class="post-metadata">

**Author:** ![george32](https://yyz1.discourse-cdn.com/flex007/user_avatar/forum.langchain.com/george32/32/2527_2.png) [@george32](https://forum.langchain.com/u/george32)\
**Post date:** [March 4, 2026, 7:02pm UTC](https://forum.langchain.com/t/seems-like-streaming-with-multiple-agents-is-totally-broken/3073/2 "2026-03-04T19:02:10Z")

</div>

Seems like if I specify `callback: []` when call stream() on a sub-agent this fixes the issue.

Can someone clarify what’s going on and what is callbacks?

---

<div class="post-metadata">

**Author:** ![hntrl](https://avatars.discourse-cdn.com/v4/letter/h/ccd318/32.png) [@hntrl](https://forum.langchain.com/u/hntrl)\
**Post date:** [March 4, 2026, 10:53pm UTC](https://forum.langchain.com/t/seems-like-streaming-with-multiple-agents-is-totally-broken/3073/3 "2026-03-04T22:53:50Z")

</div>

Hey! Do you have a full code sample that you can share to help us diagnose this?

We do have a dedicated section to subagent streaming in case it’s of interest: [Frontend - Docs by LangChain](https://docs.langchain.com/oss/javascript/deepagents/streaming/frontend)

---

<div class="post-metadata">

**Author:** ![pawel-twardziak](https://yyz1.discourse-cdn.com/flex007/user_avatar/forum.langchain.com/pawel-twardziak/32/960_2.png) [@pawel-twardziak](https://forum.langchain.com/u/pawel-twardziak)\
**Post date:** [March 6, 2026, 11:06pm UTC](https://forum.langchain.com/t/seems-like-streaming-with-multiple-agents-is-totally-broken/3073/4 "2026-03-06T23:06:51Z")

</div>

hi @george32

The `callbacks` config in LangChain/LangGraph is an inheritable property. Any callback handler added to a parent runnable automatically propagates to all child runnables via `getChild()`. When both parent and child independently add their own `StreamMessagesHandler` (by both calling `.stream()` with `"messages"` mode), you get two handlers listening to the same token events = double output. Breaking the chain with `callbacks: []` or restructuring as a subgraph node are both valid fixes.

Why `callbacks: []` fixes the issue?  
By passing `callbacks: []` in the subagent’s `.stream()` config you break the inheritance chain. The empty array replaces the inherited callback list, so the subagent starts fresh with only the new `StreamMessagesHandler` it creates internally. Result: each token is emitted exactly once.

This issue is a well-known footgun in LangGraph JS when nesting agents or subgraphs that both stream in `"messages"` mode. The root cause is callback handler inheritance - the parent’s `StreamMessagesHandler` propagates into child runnables and listens to the same LLM token events that the child’s own handler also listens to, producing every token twice.

## Solutions

**1: Pass `callbacks: []` on the subagent stream (your workaround)**

**2: Use `.invoke()` instead of `.stream()` on the subagent**

If you only need the parent’s stream for the final UI and the subagent’s output can be returned as a complete message, call `.invoke()` on the subagent inside the tool. The parent’s `StreamMessagesHandler` will still capture the subagent’s LLM tokens (since it inherits into the child), giving you streaming in the parent output without any duplication:

```ts
const tool = tool(async (input) => {
  const subAgent = createAgent({ model, tools: subTools });
  const result = await subAgent.invoke({
    messages: [{ role: "user", content: input.query }],
  });
  return result.messages.at(-1)?.content ?? "";
}, { name: "ask_subagent", schema: z.object({ query: z.string() }) });

```

**3: Model the subagent as a subgraph node (for complex setups)**

Instead of spawning a subagent inside a tool, add it as a proper subgraph node:

```ts
const subAgent = createAgent({ model, tools: subTools });
const parentGraph = new StateGraph(AgentState)
  .addNode("main_agent", mainAgentNode)
  .addNode("sub_agent", subAgent) // subgraph node
  .addEdge("main_agent", "sub_agent")
  .compile();

// Stream with subgraphs to get events from both
for await (const [ns, mode, chunk] of await parentGraph.stream(
  input,
  { streamMode: "messages", subgraphs: true }
)) {
  // ns tells you which agent emitted the chunk
}

```

LangGraph handles callback scoping correctly for subgraph nodes, and the `subgraphs: true` flag gives you namespaced events so you can tell which agent produced each chunk.

**4: Use the `nostream` tag to suppress streaming from internal llm calls**

If the subagent’s LLM is called inside a tool and you don’t want its tokens leaking into the parent stream at all, tag it:

```ts
const quietModel = model.withConfig({
  tags: ["langsmith:nostream"] // or just "nostream"
});
const subAgent = createAgent({ model: quietModel, tools: subTools });

```
