AI & LLM APIs cookbook · Intermediate
Store and trim chat history in a database
Keep multi-turn conversations across requests and servers without sending ever-growing histories.
Approach
Store every turn in a table keyed by conversation. On each request, load the latest N turns, prepend a stored summary of older turns, and periodically refresh that summary with a small model.
Solution
import anthropic
client = anthropic.Anthropic()
KEEP_TURNS = 12
def load_context(db, conversation_id: str) -> tuple[str, list[dict]]:
summary = db.scalar("SELECT summary FROM conversations WHERE id = %s", conversation_id) or ""
rows = db.fetch("SELECT role, content FROM turns WHERE conversation_id = %s ORDER BY id DESC LIMIT %s",
conversation_id, KEEP_TURNS)
turns = [{"role": r.role, "content": r.content} for r in reversed(rows)]
while turns and turns[0]["role"] != "user": # history must start with a user turn
turns.pop(0)
return summary, turns
def chat(db, conversation_id: str, user_text: str) -> str:
summary, turns = load_context(db, conversation_id)
system = "You are a helpful assistant." + (f"\n<earlier_conversation>{summary}</earlier_conversation>" if summary else "")
turns.append({"role": "user", "content": user_text})
response = client.messages.create(model="claude-sonnet-5-5", max_tokens=800, system=system, messages=turns)
reply = response.content[0].text
db.execute("INSERT INTO turns (conversation_id, role, content) VALUES (%s, 'user', %s), (%s, 'assistant', %s)",
conversation_id, user_text, conversation_id, reply)
return reply
def refresh_summary(db, conversation_id: str, older_text: str) -> None:
response = client.messages.create(
model="claude-haiku-5-5", max_tokens=300,
messages=[{"role": "user", "content": f"Summarise the key facts and decisions:\n{older_text}"}])
db.execute("UPDATE conversations SET summary = %s WHERE id = %s", response.content[0].text, conversation_id)
Pitfalls
- Starting the message list with an assistant turn after trimming.
- Summaries that drop facts the user will ask about (names, numbers); test them.
- Keeping conversations forever with personal data; set retention.
Variations
- Let users pin facts ("my company is Northwind") into a separate memory table.
- Put the summary after a cached stable system prompt so caching still works.
Further reading: Context windows
Reference: https://docs.anthropic.com/en/docs/build-with-claude/context-windows
More AI & LLM APIs recipes
- Answer with citations that point at the source text
- Build hybrid RAG search on PostgreSQL with pgvector
- Cache a long system prompt and documents
- Cache answers to frequent questions safely
- Classify thousands of items with the Batch API
- Compare two prompt versions with an unbiased model judge
- Expose an internal API as an MCP server
- Extract structured data with a schema