Skip to content

RemoteGraph.astream(subgraphs=True) emits incorrect namespaces vs in-memory Pregel graphs #6604

@Rakshit-gen

Description

@Rakshit-gen

Checked other resources

  • This is a bug, not a usage question. For questions, please use the LangChain Forum (https://forum.langchain.com/).
  • I added a clear and detailed title that summarizes the issue.
  • I read what a minimal reproducible example is (https://stackoverflow.com/help/minimal-reproducible-example).
  • I included a self-contained, minimal example that demonstrates the issue INCLUDING all the relevant imports. The code run AS IS to reproduce the issue.

Example Code

import asyncio
import re

from langgraph.graph import StateGraph, START, END
from langgraph.pregel import Pregel
from langgraph.pregel.remote import RemoteGraph
from langgraph.types import RunnableConfig

# Dummy node
def echo_node(state: dict) -> dict:
    return state

# Build a simple in-memory graph
builder = StateGraph(dict)
builder.add_node("echo", echo_node)
builder.add_edge(START, "echo")
builder.add_edge("echo", END)
inmem_graph: Pregel = builder.compile()

# Assume we have deployed the same graph remotely and know its assistant_id/URL.
# For the minimal repro, you can plug in your own values here.
remote_graph = RemoteGraph(
    "my_assistant_id",
    url="https://my-langgraph-server",
)

uid_pattern = re.compile(
    r"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"
)

def monotonic_uid():
    val = 0
    while True:
        val += 1
        hexval = f"{val:032x}"
        yield f"{hexval[:8]}-{hexval[8:12]}-{hexval[12:16]}-{hexval[16:20]}-{hexval[20:32]}"

async def main():
    config: RunnableConfig = {"configurable": {"thread_id": "thread_1"}}

    # Collect namespaces from RemoteGraph
    remote_namespaces = []
    uid_gen = monotonic_uid()
    async for ns, messages in remote_graph.astream(
        {"messages": [{"role": "user", "content": "hello"}]},
        config,
        stream_mode="messages",
        subgraphs=True,
    ):
        # Normalize UUIDs for comparison
        ns = tuple(uid_pattern.sub(next(uid_gen), p) for p in ns)
        remote_namespaces.append(ns)

    # Collect namespaces from in-memory graph
    inmem_namespaces = []
    uid_gen = monotonic_uid()
    async for ns, messages in inmem_graph.astream(
        {"messages": [{"role": "user", "content": "hello"}]},
        config,
        stream_mode="messages",
        subgraphs=True,
    ):
        ns = tuple(uid_pattern.sub(next(uid_gen), p) for p in ns)
        inmem_namespaces.append(ns)

    print("Remote namespaces:", remote_namespaces)
    print("In-memory namespaces:", inmem_namespaces)

asyncio.run(main())

Error Message and Stack Trace (if applicable)

# TODO: Fix the namespace matching in the next api release.
# assert namespaces == inmem_namespaces

Description

I’m trying to use the langgraph library to stream from a remote graph using RemoteGraph.astream(..., subgraphs=True) and compare/debug its behavior against an equivalent in-memory Pregel graph.
I expect the namespaces emitted when subgraphs=True to match the in-memory graph semantics: caller namespace (when RemoteGraph is used as a subgraph) plus the remote graph’s internal namespace hierarchy, so that traces and tests like test_remote_graph_stream_messages_tuple can assert namespaces == inmem_namespaces.
Instead, RemoteGraph.astream parses mode/ns from chunk.event, then correctly prefixes ns with the caller namespace, but later re-parses mode/ns again from chunk.event inside the if subgraphs: block, overwriting the caller-prefixed ns. This causes the final namespaces yielded to differ from in-memory Pregel behavior and breaks namespace-based comparisons and observability for remote subgraphs.

System Info

python -m langchain_core.sys_info

or, if you use python3

python3 -m langchain_core.sys_info

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpendingawaiting review/confirmation by maintainer

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions