langchainmemorysearch

LangChain Memory Is Stale Without Live Search

Memanto adds memory to LangGraph but memory records what WAS true, not what IS true. Pattern: memory for preferences, search for current facts.

8 min

LangChain memory systems like Memanto add long-term memory to LangGraph agents, but memory records what WAS true, not what IS true. An agent that remembers "Product X costs $49/month" from three months ago will confidently give outdated pricing. The fix: use memory for user preferences and context, use live search for facts that change. Memory plus search, not memory instead of search.

What memory does well

Long-term memory is excellent for: user preferences ("I prefer Python over JavaScript"), past interactions ("last time we discussed migrating from Postgres to Supabase"), project context ("the client uses Next.js 14 with App Router"), and personal details ("budget is $500/month for tooling"). These are facts about the user and the relationship. They change slowly or not at all. Memory is the right tool for them.

What memory gets wrong

Memory is dangerous for: pricing ("Vercel Pro costs $20/month"), API endpoints ("the auth endpoint is /api/v2/login"), availability ("GPT-4 Turbo supports 128K context"), and current events ("React 19 just released"). These facts change without the agent knowing. The memory has no expiration mechanism, no way to detect staleness. The agent will serve three-month-old data with full confidence.

The stale memory problem in practice

Python
# What happens with memory alone (dangerous pattern)
from langgraph.memory import MemoryStore

memory = MemoryStore()

# Three months ago, agent stored this:
# memory.store("scavio_pricing", "Scavio costs $25/month for 5000 credits")

# Today, user asks: "How much does Scavio cost?"
# Agent retrieves from memory: "$25/month for 5000 credits"
# Agent responds confidently with WRONG info
# Actual current pricing: $30/month for 7000 credits

# The agent has no way to know the memory is stale

The fix: memory for preferences, search for facts

Python
import requests, os

H = {"x-api-key": os.environ["SCAVIO_API_KEY"]}

def answer_with_memory_and_search(query: str, memory_store, agent_id: str) -> dict:
    """Route to memory or search based on query type."""

    # Check if this is a preference/context question (use memory)
    preference_signals = ["prefer", "like", "usually", "my", "our", "last time"]
    is_preference = any(s in query.lower() for s in preference_signals)

    # Check if this is a factual/current question (use search)
    factual_signals = ["cost", "price", "latest", "current", "how to", "does it support"]
    is_factual = any(s in query.lower() for s in factual_signals)

    result = {"query": query, "sources": []}

    if is_preference:
        mem = memory_store.retrieve(query, agent_id=agent_id)
        if mem:
            result["sources"].append({"type": "memory", "data": mem})

    if is_factual or not result["sources"]:
        search_resp = requests.post("https://api.scavio.dev/api/v1/search",
            headers=H,
            json={"platform": "google", "query": query},
            timeout=10)
        if search_resp.status_code == 200:
            organic = search_resp.json().get("organic", [])[:3]
            result["sources"].append({"type": "live_search", "data": organic})

    return result

LangGraph integration pattern

Python
from langgraph.graph import StateGraph

def classify_node(state):
    """Classify whether query needs memory, search, or both."""
    query = state["query"]

    # Facts that change: always search
    volatile_topics = ["pricing", "version", "release", "availability", "status"]
    needs_search = any(t in query.lower() for t in volatile_topics)

    # User context: always check memory
    needs_memory = "my" in query.lower() or "our" in query.lower()

    state["needs_search"] = needs_search
    state["needs_memory"] = needs_memory or not needs_search
    return state

def search_node(state):
    """Fetch live data for factual queries."""
    if not state.get("needs_search"):
        return state
    resp = requests.post("https://api.scavio.dev/api/v1/search",
        headers=H,
        json={"platform": "google", "query": state["query"]},
        timeout=10)
    state["search_results"] = resp.json().get("organic", [])[:5]
    return state

def memory_node(state):
    """Retrieve from long-term memory for context queries."""
    if not state.get("needs_memory"):
        return state
    state["memory_results"] = memory_store.retrieve(state["query"])
    return state

The rule of thumb

If the fact could change in a month, verify with search before responding. If the fact is about the user and their preferences, trust memory. When in doubt, search. A search query costs $0.005. Giving a user wrong pricing or outdated API information costs trust. The hybrid approach gives you persistent context from memory with factual accuracy from live search. Neither alone is sufficient for a production agent in 2026.