Agentic AI
Building a Claude Agent That Remembers You (Without a Vector Database)
"Does it remember me?" is the first question almost everyone asks about an AI agent, and the first answer they usually get is an explanation of embeddings, vector databases, and semantic retrieval. That's real, and useful at scale — but it's the wrong place to start. Memory, at its simplest, is just: save something to disk, and read it back next time. Let's build that version first.
Why Claude "forgets" by default
Every call to the Claude API is stateless — the model only knows what's in the messages array you send it. Close your terminal, and that conversation is gone. This isn't a limitation to work around with something complicated; it's just the starting point. Memory is simply you deciding what's worth carrying forward, and handing it back in on the next call.
The simplest possible memory: append to a file
Here's the entire idea in code — no database, no embeddings, just a JSON file that grows over time.
import json
import os
from datetime import datetime
MEMORY_FILE = "memory.json"
def load_memory() -> list[dict]:
if not os.path.exists(MEMORY_FILE):
return []
with open(MEMORY_FILE) as f:
return json.load(f)
def save_memory(entries: list[dict]) -> None:
with open(MEMORY_FILE, "w") as f:
json.dump(entries, f, indent=2)
def remember(fact: str) -> None:
entries = load_memory()
entries.append({"fact": fact, "saved_at": datetime.now().isoformat()})
save_memory(entries)That's the whole storage layer. remember("User's name is Pranshu, works at Qualcomm on agentic AI") appends one line to a file. Nothing fancier than that yet.
Using it in a conversation
Now feed those saved facts back into the system prompt on every new session, so Claude starts each conversation already knowing what you told it before.
import anthropic
client = anthropic.Anthropic()
def build_system_prompt() -> str:
entries = load_memory()
if not entries:
return "You are a helpful assistant."
facts = "\n".join(f"- {e['fact']}" for e in entries)
return f"""You are a helpful assistant. Here is what you know about this user from past conversations:
{facts}
Use this naturally in conversation. Don't announce that you're using saved memory."""
def chat(user_message: str) -> str:
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
system=build_system_prompt(),
messages=[{"role": "user", "content": user_message}],
)
return response.content[0].textRun this once, tell it something about yourself, call remember() to save it, and the next time you start the program — a completely fresh session, with no conversation history — Claude already knows it.
Letting Claude decide what's worth remembering
Right now, you're deciding what gets saved. A more agentic version lets Claude call remember() itself, as a tool, whenever it notices something worth keeping — the same tool-use pattern from the first post in this series, just pointed at your memory file instead of a weather API.
tools = [
{
"name": "remember",
"description": "Save an important fact about the user for future conversations.",
"input_schema": {
"type": "object",
"properties": {
"fact": {"type": "string", "description": "The fact to remember, written clearly and in full context."}
},
"required": ["fact"],
},
}
]Wire that into the tool-use loop from the first post, and Claude will save things like "user is building a personal blog about agentic AI" on its own, mid-conversation, without you writing a single explicit save call.
Where this genuinely starts to break down
A flat JSON file works great until you have hundreds of saved facts and need to find the relevant three out of them for a given question — "what do I know about this user's coding preferences" shouldn't require reading every fact ever saved. That's the actual, specific problem embeddings and vector search solve: not "remembering" in general, but efficient retrieval once memory gets large. If you're building a personal assistant with a few dozen facts, a JSON file genuinely is a complete solution. If you're building something with thousands of stored memories across many users, that's when reaching for a vector database earns its complexity.
Reference links
- Claude API — Messages API overview: platform.claude.com/docs/en/api/overview
- Claude's built-in memory tool (server-side, managed for you): platform.claude.com/docs/en/agents-and-tools/tool-use/memory-tool
- Anthropic Python SDK: github.com/anthropics/anthropic-sdk-python
Next in this series: "The Agent Loop — Why Every Claude Agent Is Just a While Loop."
Related articles
Agentic AI
I Gave Claude Hands: My First Tool-Use Agent in 20 Lines
Agents sound complicated until you see the actual request-response loop underneath. Here's the whole thing, stripped down to one tool and 20 lines of Python.
- #claude
- #agentic-ai
- #tool-use
- #python
- #anthropic
Agentic AI
The Agent Loop: Why Every Claude Agent Is Just a While Loop
Strip away the hype and every agentic system — Claude Code, MCP-connected agents, multi-step research bots — is running the same five-line loop underneath. Here it is, in full.
- #claude
- #agentic-ai
- #python
- #anthropic
- #fundamentals
Agentic AI
5 Agent Mistakes I Made So You Don't Have To
Every one of these cost me real debugging time. Each has a one-line fix — here they are, with the code.
- #claude
- #agentic-ai
- #python
- #debugging
- #best-practices