YouTip LogoYouTip

Langchain Store

LangChain Cross-Session Storage β€”β€” Store | Rookie Tutorial\\\\n\\\\n

Checkpointer solves the problem of "memory within a single conversation". But if you need to share data across different conversations β€” such as user preferences, learning progress β€” you need to use Store.

\\\\n\\\\n
\\\\n\\\\n

Checkpointer vs Store

\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n
DimensionCheckpointerStore
ScopeSingle conversation thread (thread_id)Across all conversation threads
Data TypeAgent state snapshot (automatically managed)Arbitrary key-value data (manually managed)
Typical UseMulti-turn conversation memoryUser preferences, knowledge base, configuration
Data Organizationthread_id β†’ checkpoint(namespace, key) β†’ value
\\\\n\\\\n
\\\\n\\\\n

Basic Operations of Store

\\\\n\\\\n

Store uses a hierarchical structure of namespace + key to organize data:

\\\\n\\\\n

Example

\\\\n\\\\n
from langgraph.store.memory import InMemoryStore\\\\n\\\\nstore = InMemoryStore()\\\\n\\\\n# Write data: put(namespace, key, value)\\\\n# namespace is a tuple, key is a string, value is a dictionary\\\\nstore.put(\\\\n    ("users", "user_001"),  # namespace\\\\n    "preferences",          # key\\\\n    {                       # value\\\\n        "theme": "dark",\\\\n        "language": "zh-CN",\\\\n        "level": "Getting Started",\\\\n    }\\\\n)\\\\n\\\\nstore.put(\\\\n    ("users", "user_001"),\\\\n    "progress",\\\\n    {\\\\n        "completed_courses": ["HTML Basics, "Python Basics],\\\\n        "total_hours": 35,\\\\n    }\\\\n)\\\\n\\\\n# Read data: get(namespace, key)\\\\nprefs = store.get(("users", "user_001"), "preferences")\\\\nprint(f"Preferences: {prefs.value}")\\\\n\\\\nprogress = store.get(("users", "user_001"), "progress")\\\\nprint(f"Learning Progress: {progress.value}")\\\\n\\\\n# Search data: search(namespace)\\\\nall_user_data = store.search(("users", "user_001"))\\\\nprint(f"n Userall data ({len(all_user_data)} items):")\\\\nfor item in all_user_data:\\\\n    print(f"  {item.key}: {item.value}")\\\\n\\\\n# Delete data: delete(namespace, key)\\\\nstore.delete(("users", "user_001"), "preferences")\\\\ndeleted = store.get(("users", "user_001"), "preferences")\\\\nprint(f"n After deletion: {deleted}")  # None
\\\\n\\\\n

Running result:

\\\\n\\\\n
Preferences: {'theme': 'dark', 'language': 'zh-CN', 'level': 'Getting Started'}\\\\nLearning Progress: {'completed_courses': ['HTML Basics', 'Python Basics'], 'total_hours': 35}\\\\n\\\\nUserall data (2 items):\\\\n  preferences: {'theme': 'dark', 'language': 'zh-CN', 'level': 'Getting Started'}\\\\n  progress: {'completed_courses': ['HTML Basics', 'Python Basics'], 'total_hours': 35}\\\\n\\\\nAfter deletion: None
\\\\n\\\\n
\\\\n\\\\n

Using Store in Agent

\\\\n\\\\n

Pass Store to create_agent(), and all tools in the Agent can access it through InjectedStore:

\\\\n\\\\n

Example

\\\\n\\\\n
from dotenv import load_dotenv\\\\nload_dotenv()\\\\n\\\\nfrom typing import Annotated\\\\nfrom langgraph.store.base import BaseStore\\\\nfrom langgraph.store.memory import InMemoryStore\\\\nfrom langchain.tools import tool, InjectedStore\\\\nfrom langchain.agents import create_agent\\\\nfrom langchain.chat_models import init_chat_model\\\\nfrom langchain.messages import HumanMessage\\\\n\\\\n# Create Store and pre-populate data\\\\nstore = InMemoryStore()\\\\n\\\\nstore.put(("tutorial", "courses"), "catalog", {\\\\n    "Python3 BasicsTutorial": {"price": "Free", "hours": 20, "level": "Getting Started"},\\\\n    "Python Data Analysis": {"price": "Member", "hours": 30, "level": "Advanced"},\\\\n    "Java Object-Oriented": {"price": "Free", "hours": 25, "level": "Advanced"},\\\\n})\\\\n\\\\nstore.put(("tutorial", "users"), "user_vip_001", {\\\\n    "name": "Xiaoming",\\\\n    "membership": "VIP",\\\\n    "joined": "2024-01-15",\\\\n})\\\\n\\\\n@tool\\\\ndef query_course_info(\\\\n    course_name: str,\\\\n    store: Annotated[BaseStore, InjectedStore()],\\\\n) -> str:\\\\n    """Query detailed information about courses in TUTORIAL.\\\\n    Args:\\\\n        course_name: Course name\\\\n    """\\\\n    item = store.get(("tutorial", "courses"), "catalog")\\\\n    catalog = item.value if item else {}\\\\n    if course_name in catalog:\\\\n        info = catalog\\\\n        return (\\\\n            f"γ€Š{course_name}》- Price:{info['price']},"\\\\n            f"Duration:{info['hours']}hours, difficulty:{info['level']}"\\\\n        )\\\\n    return f"Course not found: "{course_name}》"\\\\n\\\\n@tool\\\\ndef get_user_membership(\\\\n    user_id: str,\\\\n    store: Annotated[BaseStore, InjectedStore()],\\\\n) -> str:\\\\n    """Query user membership information.\\\\n    Args:\\\\n        user_id: User ID\\\\n    """\\\\n    item = store.get(("tutorial", "users"), user_id)\\\\n    if item is None:\\\\n        return f"User not found {user_id}"\\\\n    user = item.value\\\\n    return (\\\\n        f"User {user['name']},{user['membership']} Member,"\\\\n        f"Registration Date {user['joined']}"\\\\n    )\\\\n\\\\nmodel = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)\\\\n\\\\nagent = create_agent(\\\\n    model=model,\\\\n    tools=[query_course_info, get_user_membership],\\\\n    store=store,\\\\n    system_prompt="You are the course advisor for TUTORIAL.",\\\\n)\\\\n\\\\n# Query course information (data from Store)\\\\nresult = agent.invoke({\\\\n    "messages": [HumanMessage(content="Python3 BasicsHow much is the tutorial?")]\\\\n})\\\\nprint(f"Query Course: {result['messages'].content}")\\\\n\\\\n# Query user information (data from Store)\\\\nresult = agent.invoke({\\\\n    "messages": [HumanMessage(content="Help me query the information for User user_vip_001")]\\\\n})\\\\nprint(f"Query User: {result['messages'].content}")
\\\\n\\\\n

Running result:

\\\\n\\\\n
Query Course: γ€ŠPython3 BasicsTutorial》It is free, with a learning duration of about 20 hours, and a Getting Started difficulty level.\\\\nQuery User: UserXiaoMingis VIP Member,Registration Date for 2024Year1Month15Day。
\\\\n\\\\n
\\\\n\\\\n

Store Persistence

\\\\n\\\\n

InMemoryStore data is lost after program restart. For production environments, you can use persistent solutions like PostgresStore:

\\\\n\\\\n

Example

\\\\n\\\\n
# Development stage\\\\nfrom langgraph.store.memory import InMemoryStore\\\\nstore = InMemoryStore()\\\\n\\\\n# Production environment (requires PostgreSQL)\\\\n# from langgraph.store.postgres import PostgresStore\\\\n# store = PostgresStore.from_conn_string("postgresql://...")
\\\\n\\\\n
\\\\n\\\\n

Store Usage Recommendations

\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n
Scenarionamespace Examplekey ExampleDescription
User Preferences("users", user_id)preferencesTheme, language, notification settings
Learning Progress("users", user_id)progressCompleted courses, learning hours
Knowledge Base("kb", collection)doc_idDocuments, FAQ, product information
Session Summary("sessions", thread_id)summarySummary of long conversations, for scenarios beyond Checkpointer
\\\\n\\\\n
\\\\n

Checkpointer is responsible for "where the conversation is at", while Store is responsible for "who the user is, what they know, what they like". Only by using both together can you build intelligent Agents with persistent memory.

\\\\n
← Langchain Multi AgentLangchain Before After Agent β†’