LangGraph Agent Memory vs Live Data
LangGraph memory solves cross-session state but not data freshness. Combine Memanto-style memory with live search: memory for context, API for facts.
LangGraph memory solves cross-session state -- your agent remembers user preferences, past conversations, and accumulated context. But memory does not solve data freshness. An agent that remembers you prefer Python can still quote yesterday's prices or cite a deprecated API. The solution is combining memory (for context) with live search (for facts).
What LangGraph memory actually stores
LangGraph's memory layer persists state across agent invocations: user preferences, conversation history, accumulated knowledge, and task progress. This is powerful for personalization and continuity. But the data in memory is only as fresh as when it was stored. If your agent saved a price three days ago, it will confidently quote a stale price until corrected.
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import StateGraph
# LangGraph memory pattern
memory = MemorySaver()
graph = StateGraph(AgentState)
# Memory persists between sessions
# Good: remembers user prefers Python, works in fintech, uses AWS
# Bad: remembers "GPT-4 costs $0.03/1K tokens" (outdated)
# Bad: remembers "React 19 is in beta" (shipped months ago)
# Bad: remembers competitor pricing from last week (changed)The staleness problem
Every fact stored in agent memory has a half-life. Prices change daily. API versions ship monthly. Documentation updates weekly. Library releases happen without notice. An agent with good memory but no live data access becomes more wrong over time while maintaining full confidence in its answers.
- Pricing data: stale within hours (crypto) to days (SaaS)
- API documentation: stale within weeks of a new release
- Best practices: stale within months as ecosystems evolve
- User preferences: rarely stale (this is where memory excels)
Architecture: memory for context, search for facts
import requests, os
class GroundedAgent:
"""Agent that uses memory for context and search for facts."""
def __init__(self, memory_store):
self.memory = memory_store
self.search_key = os.environ["SCAVIO_API_KEY"]
def answer(self, user_id: str, question: str) -> str:
# Load user context from memory
context = self.memory.get(user_id)
preferences = context.get("preferences", {})
history = context.get("conversation_history", [])
# Classify: is this a factual question or a preference question?
if self.needs_live_data(question):
# Factual: search for current data
facts = self.search_current(question)
return self.generate_with_facts(question, preferences, facts)
else:
# Preference/context: memory is sufficient
return self.generate_from_memory(question, context)
def needs_live_data(self, question: str) -> bool:
"""Detect questions that require fresh data."""
factual_signals = [
"price", "cost", "how much", "latest", "current",
"best", "compare", "vs", "alternative", "2026",
"release", "update", "version", "available",
]
return any(signal in question.lower() for signal in factual_signals)
def search_current(self, question: str) -> list:
resp = requests.post(
"https://api.scavio.dev/api/v1/search",
headers={"x-api-key": self.search_key},
json={"query": question, "platform": "google", "num_results": 5},
timeout=10,
)
return resp.json().get("organic_results", [])The Memanto pattern: memory with expiration
Memanto-style memory adds TTL (time-to-live) to stored facts. Each memory entry has an expiration timestamp. When the agent retrieves a fact past its TTL, it automatically refreshes via search instead of serving stale data. This combines the persistence of memory with the freshness of live search.
from datetime import datetime, timedelta
class ExpiringMemory:
"""Memory store where facts expire and trigger refresh."""
def __init__(self):
self.store = {} # key -> {value, stored_at, ttl_hours}
def set(self, key: str, value, ttl_hours: int = 24):
self.store[key] = {
"value": value,
"stored_at": datetime.now(),
"ttl_hours": ttl_hours,
}
def get(self, key: str):
entry = self.store.get(key)
if not entry:
return None
age = datetime.now() - entry["stored_at"]
if age > timedelta(hours=entry["ttl_hours"]):
return None # Expired -- caller should refresh via search
return entry["value"]
# Usage in agent
memory = ExpiringMemory()
# User preferences: long TTL (rarely change)
memory.set("user_lang_preference", "python", ttl_hours=720) # 30 days
# Pricing data: short TTL (changes frequently)
memory.set("scavio_pricing", "$0.005/credit", ttl_hours=168) # 7 days
# API versions: medium TTL
memory.set("react_latest", "19.1.0", ttl_hours=72) # 3 daysDecision matrix: what to store vs what to search
- Store in memory: user preferences, workflow patterns, conversation context, task progress
- Search live: prices, versions, availability, rankings, news, competitor data
- Store with short TTL: API endpoints (stable but might change), best practices (evolve slowly)
- Never store: real-time data (stock prices, weather, traffic), anything regulatory
Implementation cost
Adding search grounding to a LangGraph agent costs 1-3 search queries per factual question at $0.005/query. For an agent handling 50 questions/day where 60% need live data, that is 30 queries/day = $0.15/day = $4.50/month. The cost of serving stale data (user trust erosion, incorrect decisions made on bad information) far exceeds $4.50/month.
Memory and search are complementary, not competing. Memory gives your agent continuity and personalization. Search gives it accuracy and freshness. The best agents in 2026 use both with clear rules about which data source to trust for which type of question.