graph.astream checkpoint_id not working properly #519

Closed
opened 2026-02-20 17:40:32 -05:00 by yindo · 5 comments
Owner

Originally created by @us on GitHub (Mar 18, 2025).

Checked other resources

  • This is a bug, not a usage question. For questions, please use GitHub Discussions.
  • 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

async def astream_graph(state, config):
    try:
        async with AsyncMongoDBSaver.from_conn_string(os.getenv("MONGODB_URI"),
                                                      db_name=os.getenv("MONGODB_DB_NAME")) as checkpointer:
            graph = build_graph(checkpointer)
            # print("graph.get_state_history(config)", [state for state in graph.get_state_history(config)])
            async for event in graph.astream(state, config, stream_mode=["messages", "debug", "custom"]):
                yield event
    except Exception as e:
        print(f"Error in streaming: {str(e)}")
        raise

def build_graph(checkpointer):
    """Build and return the graph with tools."""
    try:
        workflow = StateGraph(AgentState)

        workflow.add_node("agent", call_model)
        workflow.add_node("tools", call_tools)
        workflow.add_edge(START, "agent")

        workflow.add_conditional_edges(
            "agent",
            should_continue,
            {
                "tools": "tools",
                END: END
            }
        )

        workflow.add_edge("tools", "agent")

        return workflow.compile(checkpointer=checkpointer)
    except Exception as e:
        print(f"Error building graph: {str(e)}")
        raise

async def call_model(state: AgentState) -> Dict:
    """Process messages and get model response."""
    try:
        messages = state["messages"]
        ...
        response = await model.ainvoke(messages)
    if hasattr(response, 'additional_kwargs') and 
       response.additional_kwargs.get('tool_calls'):
            return {"messages": [response]}

        return {"messages": [response]}

    except Exception as e:
        print(f"Error in call_model: {str(e)}")
        raise e

async def call_tools(state: AgentState) -> Dict:
    """Execute tools asynchronously."""
    try:
        messages = state["messages"]
        last_message = cast(AIMessage, messages[-1])
        ...
        result = await tool_node.ainvoke({"messages": [last_message]})
        # The result contains tool messages that we can return directly
        return {"messages": result["messages"]}

    except Exception as e:
        print(f"Error in call_tools: {str(e)}")
        raise e

Error Message and Stack Trace (if applicable)


Description

When I send checkpoint_id inside config['configurable'], its resume from there, i was expecting the continue in from that checkpoint like messages should properly show only the prev messages from that checkpoint, but its gives me full messages!

System Info

osx/linux

Originally created by @us on GitHub (Mar 18, 2025). ### Checked other resources - [x] This is a bug, not a usage question. For questions, please use GitHub Discussions. - [x] I added a clear and detailed title that summarizes the issue. - [x] I read what a minimal reproducible example is (https://stackoverflow.com/help/minimal-reproducible-example). - [x] 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 ```python async def astream_graph(state, config): try: async with AsyncMongoDBSaver.from_conn_string(os.getenv("MONGODB_URI"), db_name=os.getenv("MONGODB_DB_NAME")) as checkpointer: graph = build_graph(checkpointer) # print("graph.get_state_history(config)", [state for state in graph.get_state_history(config)]) async for event in graph.astream(state, config, stream_mode=["messages", "debug", "custom"]): yield event except Exception as e: print(f"Error in streaming: {str(e)}") raise def build_graph(checkpointer): """Build and return the graph with tools.""" try: workflow = StateGraph(AgentState) workflow.add_node("agent", call_model) workflow.add_node("tools", call_tools) workflow.add_edge(START, "agent") workflow.add_conditional_edges( "agent", should_continue, { "tools": "tools", END: END } ) workflow.add_edge("tools", "agent") return workflow.compile(checkpointer=checkpointer) except Exception as e: print(f"Error building graph: {str(e)}") raise async def call_model(state: AgentState) -> Dict: """Process messages and get model response.""" try: messages = state["messages"] ... response = await model.ainvoke(messages) if hasattr(response, 'additional_kwargs') and response.additional_kwargs.get('tool_calls'): return {"messages": [response]} return {"messages": [response]} except Exception as e: print(f"Error in call_model: {str(e)}") raise e async def call_tools(state: AgentState) -> Dict: """Execute tools asynchronously.""" try: messages = state["messages"] last_message = cast(AIMessage, messages[-1]) ... result = await tool_node.ainvoke({"messages": [last_message]}) # The result contains tool messages that we can return directly return {"messages": result["messages"]} except Exception as e: print(f"Error in call_tools: {str(e)}") raise e ``` ### Error Message and Stack Trace (if applicable) ```shell ``` ### Description When I send checkpoint_id inside config['configurable'], its resume from there, i was expecting the continue in from that checkpoint like messages should properly show only the prev messages from that checkpoint, but its gives me full messages! ### System Info osx/linux
yindo added the question label 2026-02-20 17:40:32 -05:00
yindo closed this issue 2026-02-20 17:40:32 -05:00
Author
Owner

@vbarda commented on GitHub (Mar 18, 2025):

your example is incomplete - please provide how you're actually invoking the graph

from your description it's unclear whether you're trying to fork or replay https://langchain-ai.github.io/langgraph/concepts/time-travel/, but you shouldn't be seeing full messages in either of the two cases.

also, i would also recommend running your code with langgraph.checkpoint.memory.MemorySaver and verifying that it's not an issue with MongoDBSaver

@vbarda commented on GitHub (Mar 18, 2025): your example is incomplete - please provide how you're actually invoking the graph from your description it's unclear whether you're trying to fork or replay https://langchain-ai.github.io/langgraph/concepts/time-travel/, but you shouldn't be seeing full messages in either of the two cases. also, i would also recommend running your code with `langgraph.checkpoint.memory.MemorySaver` and verifying that it's not an issue with MongoDBSaver
Author
Owner

@us commented on GitHub (Mar 19, 2025):

ah sorry, i missed! here how i am invoking that:
(yes i am giving 2 times the config! just to make sure for all cases i need to clean, i know..)

config = {
    "user_id": user_id,
    "thread_id": thread_id,
    "checkpoint_id": checkpoint_id
}

state = {
    "messages": messages,
    "config": config
}

astream_graph(
    state,
    {'configurable': config},
)


class AgentState(TypedDict):
    """State for the agent."""
    messages: Annotated[Sequence[BaseMessage], add]
    config: Dict
@us commented on GitHub (Mar 19, 2025): ah sorry, i missed! here how i am invoking that: *(yes i am giving 2 times the config! just to make sure for all cases i need to clean, i know..)* ```python config = { "user_id": user_id, "thread_id": thread_id, "checkpoint_id": checkpoint_id } state = { "messages": messages, "config": config } astream_graph( state, {'configurable': config}, ) class AgentState(TypedDict): """State for the agent.""" messages: Annotated[Sequence[BaseMessage], add] config: Dict ```
Author
Owner

@vbarda commented on GitHub (Apr 11, 2025):

what's in add? i would recommend using the built-in messages reducer from langgraph.graph.message import add_messages

@vbarda commented on GitHub (Apr 11, 2025): what's in `add`? i would recommend using the built-in messages reducer `from langgraph.graph.message import add_messages`
Author
Owner

@nfcampos commented on GitHub (May 23, 2025):

Have you tried with other checkpointers, eg. the sqlite checkpointer?

@nfcampos commented on GitHub (May 23, 2025): Have you tried with other checkpointers, eg. the sqlite checkpointer?
Author
Owner

@us commented on GitHub (May 25, 2025):

working now!

@us commented on GitHub (May 25, 2025): working now!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraph#519