fleet-memory/hindsight-docs/blog/2026-03-03-litellm.md
Ben 0ad6ee3156
Blog: Adding Long-Term Memory to LangGraph and LangChain Agents (#637)
* Add blog post: Adding Long-Term Memory to LangGraph and LangChain Agents

* blog: update langgraph post date to 2026-03-24 and add cover image

* blog: fix claude-code-telegram filename to match frontmatter date (2026-03-25)

* blog: set claude-code-telegram date to 2026-03-23

* blog: fix date timezone offset by adding T12:00 to all post dates

* ci: trigger fresh CI run

* blog: fix broken docs link (routeBasePath is /)
2026-03-24 13:51:27 -04:00

314 lines
9.2 KiB
Markdown

---
title: "I Gave 100+ LLMs a Permanent Memory With One Python Package"
authors: [benfrank241]
date: 2026-03-03T12:00
tags: [litellm, python, memory, openai, anthropic, tutorial]
image: /img/blog/litellm-memory.png
---
`hindsight-litellm` adds persistent memory to any LLM provider via LiteLLM — OpenAI, Anthropic, Groq, Azure, Bedrock, Vertex AI, and 100+ more. Three lines of setup, and every LLM call automatically gets context from past conversations.
<!-- truncate -->
---
## The Problem: Stateless LLM Calls
You build an app with an LLM. User talks to it on Monday. Comes back Tuesday. The LLM has no idea who they are.
This is true for every provider. OpenAI, Anthropic, Groq, Azure — every API call is a blank slate. The LLM doesn't remember preferences, past conversations, or anything you've discussed before.
Most teams work around this by stuffing the last N messages into the context window. But that's not memory — it's a sliding window that drops everything older than your token limit. The user's preferences from last week? Gone. The project context from last month? Gone.
What if every LLM call automatically had the right context from past conversations?
---
## The Fix: Three Lines, Any Provider
`hindsight-litellm` hooks into LiteLLM to intercept every LLM call. Before the call, it retrieves relevant memories from Hindsight and injects them into the prompt. After the call, it stores the conversation for future retrieval.
```
Your code ──→ hindsight_litellm.completion()
├─→ 1. Recall/Reflect from Hindsight (relevant memories)
├─→ 2. Inject memories into prompt
├─→ 3. Forward to LLM (any provider via LiteLLM)
├─→ 4. Store conversation to Hindsight
└─→ 5. Return response
```
Here's the setup:
```python
import hindsight_litellm
hindsight_litellm.configure(
hindsight_api_url="http://localhost:8888",
)
hindsight_litellm.set_defaults(
bank_id="my-agent",
)
hindsight_litellm.enable()
```
That's it. Now every `completion()` call has memory:
```python
response = hindsight_litellm.completion(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Help me with my Python project"}],
hindsight_query="What do I know about the user's Python project?",
)
```
The `hindsight_query` tells Hindsight what to search for in memory. The response comes back with context from past conversations — the LLM knows about the user's project, their preferences, their tech stack.
> **Note:** You can also use [Hindsight Cloud](https://ui.hindsight.vectorize.io/signup) and skip the self-hosted setup entirely.
---
## Any Provider, Same Memory
Because the integration runs through LiteLLM, it works with every provider LiteLLM supports. Switch models freely — memory follows:
```python
messages = [{"role": "user", "content": "What did we discuss last time?"}]
query = "What have I discussed with this user?"
# OpenAI
hindsight_litellm.completion(model="gpt-4o", messages=messages, hindsight_query=query)
# Anthropic
hindsight_litellm.completion(model="claude-sonnet-4-20250514", messages=messages, hindsight_query=query)
# Groq
hindsight_litellm.completion(model="groq/llama-3.1-70b-versatile", messages=messages, hindsight_query=query)
# Azure OpenAI
hindsight_litellm.completion(model="azure/gpt-4", messages=messages, hindsight_query=query)
# AWS Bedrock
hindsight_litellm.completion(model="bedrock/anthropic.claude-3", messages=messages, hindsight_query=query)
# Google Vertex AI
hindsight_litellm.completion(model="vertex_ai/gemini-pro", messages=messages, hindsight_query=query)
```
Same bank, same memories, any model. Migrate from OpenAI to Anthropic and your agent still knows everything.
---
## Two Memory Modes
### Recall: Raw Memories
The default mode retrieves individual memory facts and injects them as a numbered list:
```python
hindsight_litellm.set_defaults(bank_id="my-agent", use_reflect=False)
```
The LLM sees something like:
```
# Relevant Memories
1. [WORLD] User is building a FastAPI application
2. [WORLD] User prefers pytest for testing
3. [OBSERVATION] User likes type hints
```
Best for precise, factual context where the LLM needs individual data points.
### Reflect: Synthesized Context
Reflect mode synthesizes memories into a coherent paragraph instead of raw facts:
```python
hindsight_litellm.set_defaults(
bank_id="my-agent",
use_reflect=True,
reflect_context="I am a coding assistant helping with Python projects.",
)
```
The LLM sees something like:
```
The user is an experienced Python developer working on a FastAPI application.
They prefer pytest for testing and value type hints. In past conversations,
they asked about async patterns and database migrations.
```
Best for natural, conversational context. The `reflect_context` parameter shapes how Hindsight reasons about the memories without affecting what it retrieves.
---
## Direct Memory APIs
Sometimes you want to query memory outside of an LLM call. The direct APIs give you full control:
### Recall — query raw memories
```python
from hindsight_litellm import recall
memories = recall("what projects is the user working on?", budget="mid")
for m in memories:
print(f"- [{m.fact_type}] {m.text}")
```
### Reflect — synthesized context
```python
from hindsight_litellm import reflect
result = reflect(
"what do you know about the user's preferences?",
context="I am a customer support agent.",
)
print(result.text)
```
### Retain — store memories manually
```python
from hindsight_litellm import retain
retain(
content="User mentioned they're switching from Flask to FastAPI",
context="Discussion about web frameworks",
)
```
All three have async variants: `arecall()`, `areflect()`, `aretain()`.
---
## Per-Call Overrides
Defaults are convenient, but sometimes you need per-call control:
```python
response = hindsight_litellm.completion(
model="gpt-4o-mini",
messages=[...],
hindsight_query="What do I know about Alice?",
hindsight_bank_id="other-agent", # Different bank for this call
hindsight_budget="high", # More thorough retrieval
hindsight_reflect_context="Currently helping with onboarding",
)
```
Any default can be overridden with a `hindsight_*` prefix.
---
## Native SDK Wrappers
If you use the OpenAI or Anthropic SDKs directly (without LiteLLM), there are native wrappers:
### OpenAI
```python
from openai import OpenAI
from hindsight_litellm import wrap_openai
client = OpenAI()
wrapped = wrap_openai(
client,
bank_id="my-agent",
hindsight_api_url="http://localhost:8888",
)
response = wrapped.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "What do you know about me?"}]
)
```
### Anthropic
```python
from anthropic import Anthropic
from hindsight_litellm import wrap_anthropic
client = Anthropic()
wrapped = wrap_anthropic(
client,
bank_id="my-agent",
hindsight_api_url="http://localhost:8888",
)
response = wrapped.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}]
)
```
Same memory, no LiteLLM dependency.
---
## Context Manager
For temporary memory integration:
```python
from hindsight_litellm import hindsight_memory
import litellm
with hindsight_memory(
hindsight_api_url="http://localhost:8888",
bank_id="user-123",
):
response = litellm.completion(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello!"}],
hindsight_query="greeting context",
)
# Memory integration automatically disabled after the block
```
---
## Bank Missions
Tell Hindsight what kind of knowledge the bank should build. This shapes how memories are consolidated into mental models. Pass `mission` and `bank_name` to `configure()`:
```python
hindsight_litellm.configure(
hindsight_api_url="http://localhost:8888",
mission="""This agent routes customer support requests.
Remember which issue types go to which teams (billing, technical, sales).
Track customer preferences and past resolutions.""",
bank_name="Customer Support Router",
)
```
---
## Recap
- `hindsight-litellm` gives any LLM persistent memory across conversations
- Works with 100+ providers via LiteLLM, plus native OpenAI and Anthropic wrappers
- Three lines of setup: `configure()`, `set_defaults()`, `enable()`
- Two modes: `recall` for raw facts, `reflect` for synthesized context
- Direct APIs (`recall`, `reflect`, `retain`) for manual memory control
- Per-call overrides, bank missions, async support, and debug mode
The integration handles memory retrieval, prompt injection, and conversation storage automatically. You just call `completion()` as usual — the LLM remembers everything.
---
## Next Steps
- **Try it locally**: `pip install hindsight-all hindsight-litellm` and run the quick start above
- **Use Hindsight Cloud**: Skip self-hosting with a [free account](https://ui.hindsight.vectorize.io/signup)
- **Explore memory modes**: Try `use_reflect=True` for synthesized context vs raw facts
- **Set a bank mission**: Shape what knowledge your agent accumulates
- **Inspect with debug mode**: Set `verbose=True` and call `get_last_injection_debug()` to see exactly what memories are injected