Remembering the conversation
Every invoke so far started from nothing. A checkpointer saves the conversation after each step, and a thread_id says which conversation a call belongs to.
Ravi asks about one order and then another. With lesson 8's agent, the second call has no idea the first happened.
from langchain.agents import create_agent
from shop_model import ShopModel
from tools import lookup_order
agent = create_agent(ShopModel(), tools=[lookup_order])first = agent.invoke({"messages": [{"role": "user", "content": "Where is A17?"}]})
second = agent.invoke({"messages": [{"role": "user", "content": "And C40?"}]})
print(len(first["messages"]), len(second["messages"]))
print([m.text for m in second["messages"] if m.type == "human"])Each call returned its own four messages. The conversation you pass in is all the agent has, so the second call never saw A17.
A checkpointer and a thread
from langchain.agents import create_agent
from shop_model import ShopModel
from tools import lookup_order
from langgraph.checkpoint.memory import InMemorySaver
agent = create_agent(ShopModel(), tools=[lookup_order], checkpointer=InMemorySaver())A checkpointer saves the agent's state, the conversation included, after every step, and reads it back at the start of the next. InMemorySaver keeps it in a Python dictionary.
ravi = {"configurable": {"thread_id": "ravi-1"}}
agent.invoke({"messages": [{"role": "user", "content": "Where is A17?"}]}, ravi)
result = agent.invoke({"messages": [{"role": "user", "content": "And C40?"}]}, ravi)
print(len(result["messages"]))
print([m.text for m in result["messages"] if m.type == "human"])The second call passed one new message and got back eight. A thread is one conversation, named by thread_id in the config; everything saved under that id came back and the new message was added to the end.
state = agent.get_state(ravi)
print(len(state.values["messages"]))
print(state.values["messages"][-1].text)get_state reads what the checkpointer saved for a thread without running the agent. Its values are the state: here the eight messages, ending with the answer about C40.
Another thread starts empty
mei = {"configurable": {"thread_id": "mei-1"}}
result = agent.invoke({"messages": [{"role": "user", "content": "Hello"}]}, mei)
print(len(result["messages"]))Mei's thread holds only her two messages, even though Ravi's is in the same checkpointer. Each thread's history is kept apart.
InMemorySaver is gone when the program ends. A checkpointer backed by a database is what you want in production, such as Postgres or SQLite, each a separate package with the same interface.- Invoke the checkpointed agent without the config and read the error.
- Print
agent.get_state(mei).values["messages"]after Mei's call. - Ask a third question in Ravi's thread and predict the message count before you run it.
Slow is fine. Stopping is the only problem.