-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Description
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 json
from typing import Annotated, TypedDict
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import END, START, StateGraph, add_messages
class State(TypedDict):
messages: Annotated[list[str], add_messages]
async def node1(state: State) -> State:
print("Node1 executing:", state)
return {"messages": ["node1"]}
async def main():
graph = StateGraph(State)
graph.add_node("node1", node1)
graph.add_edge(START, "node1")
graph.add_edge("node1", END)
checkpointer = InMemorySaver()
workflow = graph.compile(checkpointer=checkpointer)
thread_id = "test-thread-1"
config = {
"metadata": {
"foo": "bar",
},
"configurable": {
"thread_id": thread_id,
},
}
print("Running graph with RunnableConfig:")
print(json.dumps(config, indent=2))
await workflow.ainvoke({"messages": []}, config=config)
print("\n" + "=" * 60)
print("State history:")
print("=" * 60 + "\n")
get_state_config = {"configurable": {"thread_id": thread_id}}
async for snapshot in workflow.aget_state_history(config=get_state_config):
print("snapshot RunnableConfig:")
print(snapshot.config)
print("\nsnapshot CheckpointMetadata:")
print(snapshot.metadata)
print("\n" + "-" * 60 + "\n")
if __name__ == "__main__":
asyncio.run(main())Error Message and Stack Trace (if applicable)
Running graph with RunnableConfig:
{
"metadata": {
"foo": "bar"
},
"configurable": {
"thread_id": "test-thread-1"
}
}
Node1 executing: {'messages': []}
============================================================
State history:
============================================================
snapshot RunnableConfig:
{'configurable': {'thread_id': 'test-thread-1', 'checkpoint_ns': '', 'checkpoint_id': '1f0c4ac4-15e7-6ea6-8001-1150b7285acf'}}
snapshot CheckpointMetadata:
{'source': 'loop', 'step': 1, 'parents': {}, 'foo': 'bar'}
------------------------------------------------------------
snapshot RunnableConfig:
{'configurable': {'thread_id': 'test-thread-1', 'checkpoint_ns': '', 'checkpoint_id': '1f0c4ac4-15e6-6be6-8000-9923452d125c'}}
snapshot CheckpointMetadata:
{'source': 'loop', 'step': 0, 'parents': {}, 'foo': 'bar'}
------------------------------------------------------------
snapshot RunnableConfig:
{'configurable': {'thread_id': 'test-thread-1', 'checkpoint_ns': '', 'checkpoint_id': '1f0c4ac4-15df-6008-bfff-32845d236c59'}}
snapshot CheckpointMetadata:
{'source': 'input', 'step': -1, 'parents': {}, 'foo': 'bar'}
------------------------------------------------------------Description
This is a run of a simple graph. I fetch the state history after the graph finishes. I've injected metadata foo=bar in the config. In each StateSnapshot in aget_state_history I get my metadata inside snapshot.metadata instead of snapshot.conifg['metadata'].
Documentation says snapshot.metadata:
class CheckpointMetadata(TypedDict, total=False):
"""Metadata associated with a checkpoint."""
source: Literal["input", "loop", "update", "fork"]
"""The source of the checkpoint.
[ ... ]
"""
step: int
"""The step number of the checkpoint.
[ ... ]
"""
parents: dict[str, str]
"""The IDs of the parent checkpoints.
Mapping from checkpoint namespace to checkpoint ID.
"""
so from that ^^^ I shouldn't be expecting to get my metadata there. snapshot.config OTOH is RunnableConfig the exact type where I had put my metadata while doing workflow.ainvoke. So I would also expect my metadata to be populated in snapshot.config['metadata'], but that's not the case.
Either this is a bug or the documentation needs to be clearer about what to expect where, what is the difference between snapshot.config['metadata'] and snapshot.metadata etc.
System Info
$ pip freeze | grep lang
langchain==1.0.7
langchain-classic==1.0.0
langchain-community==0.4.1
langchain-core==1.0.5
langchain-openai==1.0.3
langchain-text-splitters==1.0.0
langgraph==1.0.3
langgraph-checkpoint==3.0.1
langgraph-checkpoint-postgres==3.0.1
langgraph-checkpoint-sqlite==3.0.0
langgraph-prebuilt==1.0.4
langgraph-sdk==0.2.9
langsmith==0.4.43