# Streaming subgraphs results in duplicate messages as subgraph updates parent

**URL:** <https://forum.langchain.com/t/streaming-subgraphs-results-in-duplicate-messages-as-subgraph-updates-parent/1659>\
**Category:** LangGraph\
**Tags:** python-help\
**Created:** [September 26, 2025, 8:00pm UTC](https://forum.langchain.com/t/streaming-subgraphs-results-in-duplicate-messages-as-subgraph-updates-parent/1659 "2025-09-26T20:00:58Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![SpyMachine](https://yyz1.discourse-cdn.com/flex007/user_avatar/forum.langchain.com/spymachine/32/1106_2.png) [@SpyMachine](https://forum.langchain.com/u/SpyMachine)\
**Post date:** [September 26, 2025, 8:00pm UTC](https://forum.langchain.com/t/streaming-subgraphs-results-in-duplicate-messages-as-subgraph-updates-parent/1659/1 "2025-09-26T20:00:58Z")

</div>

I have a multi-agent setup with a router and multiple sub-agents. I am streaming with `subgraphs=True`.

Streaming the subgraphs is working perfectly fine except at the very end. When the subagent completes, the router agent streams its own update which contains the list of all the messages, including the original HumanMessage which it got from the sub agent node.

I’m not sure if I’m missing something here or if I’m just supposed to handle that filtering of the duplicate messages outside of langgraph? I suppose I can keep each message id and only stream “new” messages but it feels like I might be missing something?

Also to be clear, I am using the “add\_messages” reducer on my messages field in my state, so I don’t think it’s related to that.

In fact, the behavior here is exactly the same as the example in the docs [Stream outputs](https://langchain-ai.github.io/langgraph/how-tos/streaming/#stream-subgraph-outputs) . I just am unclear what the expectation here is around filtering when streaming for a chat agent. FWIW when I run my graph from LangGraph Studio I do not get the duplicate messages.

Thanks!

---

<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:** [September 26, 2025, 10:35pm UTC](https://forum.langchain.com/t/streaming-subgraphs-results-in-duplicate-messages-as-subgraph-updates-parent/1659/2 "2025-09-26T22:35:39Z")

</div>

Hi @SpyMachine

### Streaming subgraphs shows “duplicates” - is this expected?

Short answer: yes, this is expected when `subgraphs=True`. You’ll receive updates from both the subgraph and the parent. The parent’s final update often includes the subgraph’s contributions (e.g., appended messages), so if you render both verbatim you’ll see apparent duplicates. This affects the stream of events, not your state reducer correctness.

Why it happens

- **Streaming semantics** : With `subgraphs=True`, the stream emits outputs from the subgraph namespace and then a parent namespace update that reflects the parent’s state after incorporating those subgraph updates. This is visible in the “Stream subgraph outputs” examples where events arrive for the subgraph, and then the parent emits its own update afterward.
- **Reducers (like `add_messages`)**: Using `add_messages` is fine here - this isn’t a double-append bug. It’s simply that the stream includes both the subgraph event and the parent’s state update that includes the subgraph’s changes.

How to handle it in a chat UI

1. Filter by namespace (recommended for `stream_mode="updates"`)

```python
for namespace, delta in graph.stream(inputs, stream_mode="updates", subgraphs=True):
    is_parent = len(namespace) == 0
    if is_parent:
        # Option A: ignore parent updates for message rendering
        continue
    # Option B: or only pass through certain keys from parent/subgraphs
    render(delta)

```

1. Track message IDs (works across modes)

```python
seen = set()
for namespace, delta in graph.stream(inputs, stream_mode="updates", subgraphs=True):
    for msg in delta.get("messages", []):
        msg_id = getattr(msg, "id", None) or (msg.role, msg.content)
        if msg_id in seen:
            continue
        seen.add(msg_id)
        render(msg)

```

1. If you’re token-streaming, filter by node metadata
  - With `stream_mode="messages"`, filter using `metadata["langgraph_node"]` or `metadata["tags"]` so you only render from the specific node(s) you want (e.g., a sub-agent node), avoiding the parent’s final message tokens.

FWIW: Why LangGraph Studio doesn’t show “duplicates”

- Studio groups and presents events by their namespaces and roles, effectively de-duplicating the UX. When building a custom UI, you’ll want to apply a similar rule: either show only the subgraph’s messages in real time and treat the parent’s final update as a checkpoint, or deduplicate by message identity.

- Sources:

References

- [Stream outputs (includes “Stream subgraph outputs” and examples showing both subgraph and parent updates)](https://langchain-ai.github.io/langgraph/how-tos/streaming/#stream-subgraph-outputs)
- OSS v1-alpha Streaming (subgraph streaming and modes) and filtering by node/tags in token streams: [Streaming - Docs by LangChain](https://docs.langchain.com/oss/python/langgraph/streaming/#stream-subgraph-outputs), [Streaming - Docs by LangChain](https://docs.langchain.com/oss/python/langgraph/streaming/#filter-by-node)

---

<div class="post-metadata">

**Author:** ![SpyMachine](https://yyz1.discourse-cdn.com/flex007/user_avatar/forum.langchain.com/spymachine/32/1106_2.png) [@SpyMachine](https://forum.langchain.com/u/SpyMachine)\
**Post date:** [September 29, 2025, 12:17pm UTC](https://forum.langchain.com/t/streaming-subgraphs-results-in-duplicate-messages-as-subgraph-updates-parent/1659/3 "2025-09-29T12:17:52Z")

</div>

Thank you very much @pawel-twardziak. That jives with my understanding I just wanted to make sure I wasn’t missing something obvious. I thought something like this would have some prebuilt solution given how ubiquitous the “chat bot” use case is.

Appreciate your help!
