Memory & context files¶
By default an agent forgets everything the moment a run ends. This page gives it a memory that survives across sessions — and shows you how to drop a file in your project that every run picks up automatically.
There are two pieces, and they pull in opposite directions:
- Memory — a
MEMORY.mdthe agent writes to. It learns something worth keeping ("you prefer pytest"), saves it, and recalls it next time. - Context files — markdown you write (
AGENTS.md,CLAUDE.md,DEEP.md,SOUL.md). The agent reads them but never edits them. They're how you hand a project its rules without re-explaining them every run.
Let's see memory first, because it's the one with the satisfying payoff.
import asyncio
from pydantic_deep import create_deep_agent, DeepAgentDeps, LocalWorkspace
async def main():
agent = create_deep_agent(
model="anthropic:claude-sonnet-4-6",
instructions="You are a helpful coding assistant.",
# One directory, used by both runs — that's what makes memory persist.
workspace=LocalWorkspace("./project"),
)
# First session: tell it something worth remembering.
await agent.run(
"Remember that I always use pytest, never unittest. Save that to memory.",
deps=DeepAgentDeps(),
)
# Second session: a fresh run, but the same directory.
result = await agent.run("What testing framework do I use?", deps=DeepAgentDeps())
print(result.output)
asyncio.run(main())
Run it¶
Save it to main.py, create the project folder, and run:
The second agent.run() is a brand-new conversation. It has none of the first run's messages. Yet it answers correctly, because between the two runs the agent wrote a note to MEMORY.md and read it straight back out of the workspace.
Check it
Look at the file the agent wrote:
There it is — a markdown bullet the agent saved on its own, in a file on disk that outlives the whole process.
Step by step¶
Memory is already on¶
agent = create_deep_agent(
model="anthropic:claude-sonnet-4-6",
instructions="You are a helpful coding assistant.",
)
You didn't ask for memory — it ships enabled. Memory is the harness's Memory capability: each agent keeps a notebook of Markdown files, MEMORY.md is added to every request, and four tools work on the rest:
| Tool | What it does |
|---|---|
write_memory |
Append to a file, or replace one unique piece of text in it (old_text=) |
read_memory |
Read one memory file |
search_memory |
Search across the notebook's files |
delete_memory |
Delete a file — never MEMORY.md itself |
The agent calls these on its own when it decides something is worth keeping. You can turn the whole thing off with include_memory=False, or move the files with memory_dir= (default: .deep/memory, relative to the workspace's working directory).
The workspace is the persistence¶
This is the load-bearing line. Memory lives at {memory_dir}/{agent_name}/MEMORY.md in the run's workspace — so persistence is exactly as durable as the workspace you choose. Both runs here work in the same directory, so memory carries over.
The default workspace is different: StateWorkspace() keeps files in memory, and each run that starts a new conversation gets a new, empty document. A run that continues one (message_history=result.all_messages()) works in the same document — so in memory, the agent remembers within a conversation, not across them.
Injected, not just available
A bounded excerpt of MEMORY.md — up to 200 lines, about 2,000 tokens — and the names of the other files are added to every request, so the agent often answers from memory without calling read_memory at all. The block goes in as user-role context on the current request only, so copies don't pile up in the history.
Context files: what you hand the agent¶
Memory is the agent's notebook. Context files are yours. Drop an AGENTS.md in the workspace's root and the agent folds it into its prompt on every run — perfect for conventions, architecture, and "always run make test before committing."
from pathlib import Path
from pydantic_deep import create_deep_agent, DeepAgentDeps, LocalWorkspace
Path("project/AGENTS.md").write_text(
"# Project rules\n\n- Use snake_case for Python.\n- Always run `make test` before committing.\n"
)
agent = create_deep_agent(workspace=LocalWorkspace("./project"), context_discovery=True)
result = await agent.run("What's our naming convention?", deps=DeepAgentDeps())
print(result.output) # -> "snake_case for Python"
context_discovery=True scans the workspace's root for known convention files and injects whatever it finds. Missing files are skipped silently, so you only create the ones you want.
| File | Purpose | Seen by subagents? |
|---|---|---|
AGENTS.md |
Project instructions, conventions, architecture | Yes |
CLAUDE.md |
Claude Code project instructions | Yes |
DEEP.md |
pydantic-deep project instructions | Yes |
SOUL.md |
Personality, tone, your preferences | No — main agent only |
Prefer to be explicit? Skip discovery and name the paths yourself with context_files=["/AGENTS.md", "/SOUL.md"].
Memory vs. context, in one line
If the agent should write it, it's memory. If you write it, it's a context file. MEMORY.md has its own tools and per-agent isolation; it is not part of context discovery.
One workspace, one memory — watch multi-user apps
Memory and context both live in the workspace. If several users' runs share one workspace, give each its own notebook with memory_namespace= — a string, or a function of the run such as lambda ctx: ctx.deps.user_id — which files it under {memory_dir}/{namespace}/{agent_name}/. The model never sees or chooses the namespace, which must be letters, digits, _, - and . — hash an e-mail address first. Giving each user their own workspace isolates their files as well. See Multi-user.
Recap¶
- Memory is on by default: the harness
Memorycapability, withwrite_memory/read_memory/search_memory/delete_memoryandMEMORY.mdadded to every request — the agent remembers across runs on its own. - The workspace is the persistence. Memory lives at
{memory_dir}/{agent_name}/MEMORY.md; reuse the workspace and it carries over, swap it and it doesn't. - Context files (
AGENTS.md,CLAUDE.md,DEEP.md,SOUL.md) are project rules you write;context_discovery=Truefinds them, or list them withcontext_files=. - Rule of thumb: the agent owns memory, you own context files — and
SOUL.mdstays with the main agent only.
Both of these survive a single process. To save, label, and rewind whole conversations, that's next.