Anthropic's memory API has no ranked retrieval
Anthropic's memory surfaces are complete in four of the five layers a memory system usually has. Storage, versioning, consolidation and forgetting are all there, documented, with limits and audit trails. The fifth layer, retrieval, is ls and grep.
That is not a slip. On the same platform, for tools, Anthropic ships a ranked retriever with BM25. Two surfaces, the same overflow problem, two opposite answers. The asymmetry is the interesting part, and it tells you something specific about what you have to build yourself.
TL;DR
- The memory tool has six commands:
view,create,str_replace,insert,delete,rename. No search, no query, no find.- The Managed Agents memory API has no search endpoint. Listing accepts exactly two filters,
path_prefixanddepth, anddepthhas exactly two legal values. Results arrive in "a stable, server-defined order".- Search does exist in the sandbox, because the store mounts as a directory and the agent holds
grepandglob. It is lexical and unranked. Nothing scores.- Ranked retrieval ships on the same platform, for tools, out of the box, with BM25.
- The path name is the index, and at the documented ceiling of 10,000 memories per store, enumerating one takes at least 100 paginated requests.
Quotes below come from live vendor pages fetched on 2026-09-03; each source page is linked in the section that introduces it.
Say precisely what is missing
Ranked retrieval, as used here, means selecting candidate memories and ordering them by an explicit relevance signal for the current request. BM25 does it lexically. An embedding index does it semantically. Either way something computes a score, and the top of the list is the answer to a question.
This is not the claim that Anthropic shipped a memory system you cannot search. You can. The narrower point is the one that matters: the documented retrieval path has no relevance-ranking layer. Search is there in the form Unix has had since the 1970s, and stops there.
The five-layer frame in this piece is a lens for reading the surfaces, not a universal taxonomy of memory systems.
The two surfaces
The memory tool is a client-side file abstraction that lets Claude keep information across conversations in a directory of memory files. Its reference documents six commands: view, create, str_replace, insert, delete, rename. There is no search, grep, query or find command in the tool. Execution is yours: "Memory lives entirely in your application."
When the tool is present, the API adds an instruction to the system prompt: "IMPORTANT: ALWAYS VIEW YOUR MEMORY DIRECTORY BEFORE DOING ANYTHING ELSE." Read that for what it is. Finding the right memory is advisory context asking the model to look, not a runtime guarantee that it did. The API cannot refuse to proceed until view has run.
The Managed Agents memory API is "a workspace-scoped collection of text documents optimized for Claude". Under the agent-memory-2026-07-22 beta, its endpoints cover memories (create, retrieve, update, delete, list), versions (list, retrieve, redact) and stores (create, retrieve, update, list, archive, delete). No search endpoint appears in that surface.
Attaching a store to a session mounts it "as a directory inside the session's sandbox", where "the agent reads and writes it with the same file tools it uses for the rest of the filesystem". Those file tools include grep, described as "Text search using regex patterns", alongside glob and bash. So the agent can search a memory store. Lexically, over paths and file text, with no ordering by relevance to anything.
Listing is a directory walk, and says so
The listing reference is the part that states the design out loud. It documents two filters and no query parameter. path_prefix must end with a slash and matches whole path segments, so /notes/ returns /notes/todo.md and not /notes-archive/todo.md. depth accepts 0 or 1; anything else returns a 400.
Then it names the ancestry itself:
depth=1behaves likels; omittingdepthbehaves likefind.
Ordering is settled the same way: "Items are returned in a stable, server-defined order." Stable means repeatable across requests. It does not mean relevant to the request. Two different properties, and only one of them is on offer.
The rest is paging: limit runs 1 to 100 and defaults to 20, capped at 20 when view=full, with an opaque cursor for the next page. Paths cap at 1,024 bytes, content at 100 kB.
The memory tool's own view behaves the same in miniature. It lists files "up to 2 levels deep" with sizes, truncates a text view past 16,000 characters, and hands you view_range to page through the remainder.
The other four layers are all there
The absent relevance model is not a symptom of an unfinished product. The neighbouring layers are built out with a care that makes the contrast sharper.
Versioning. "Every change to a memory creates an immutable memory version, giving you an audit trail and point-in-time recovery for everything the agent writes." Versions are retained for 30 days, with the recent versions of a live memory kept regardless of age, and redact scrubs content from history while preserving who did what and when.
Consolidation. A dreaming session "consolidates fragmented content into a separate new output store rather than modifying the original".
Forgetting. Two forms, both by hand. Prune before the store fills, deleting stale or redundant memories, and "periodically delete memory files that haven't been accessed in a long time".
Storage. Documented all the way to its edges: 100 kB per memory, 10,000 memories per store, 8 stores per session, and the instruction to "structure memory as many small focused files, not a few large ones". At the ceiling, "writes to new memories fail", while existing memories stay readable and editable.
Read that last pair together. You are told to produce many small files, and given no ranked way to find one of them again.
BM25 for tools, grep for memories
Anthropic does ship ranked retrieval, on the same developer platform, for a neighbouring problem. From the advanced tool use guide:
The Claude Developer Platform provides regex-based and BM25-based search tools out of the box, but you can also implement custom search tools using embeddings or other strategies.
Tool search matches against names and descriptions; the regex variant is tool_search_tool_regex_20251119. The problem it solves is context overflow. A large tool library does not fit in the window, so the agent retrieves the few tools it needs.
A memory store at 10,000 documents poses the same core question: pick a small subset out of a corpus too large for the window. The analogy stops there, and it is worth being honest about where. Memory also carries lifecycle, freshness and trust, which a tool catalogue does not, and those are arguments for a richer retrieval layer rather than a thinner one. What memory gets instead is a mounted directory and a prompt asking the agent to look first.
This is evidence of a product boundary, not of an engineering limitation. The capability plainly exists on the platform. It is not pointed at memory.
The index you maintain by hand
Claude Code's auto memory shows the pattern in miniature, and shows what it costs. Its documentation describes a MEMORY.md index plus one topic file per memory. "The first 200 lines of MEMORY.md, or the first 25KB, whichever comes first, are loaded at the start of every conversation." Topic files are not loaded at startup; Claude "reads them on demand using its standard file tools when it needs the information".
So the index is loaded and the corpus is not. The index has a hard budget, and going over it is an error: "the write still succeeds, but Claude Code returns an error telling Claude to rewrite the index, because everything past the limit is dropped on the next load." The instruction that follows is to keep one line per entry, move detail into topic files, and merge or drop stale entries.
That is a catalogue, written and pruned by hand, whose job is to route a reader to the right file. A search engine builds and maintains exactly that artefact, automatically, and does not cap it at 200 lines.
What it costs to walk the whole store
At the documented ceiling of 10,000 memories, and the documented maximum page size of 100, enumerating a store takes at least 100 paginated requests. With view=full, where the page size is capped at 20, reading every memory takes at least 500. Those are boundary arithmetic on published limits, not performance measurements; the assumptions are printed so you can redo them.
One field softens the sync problem and not the discovery one. content_size_bytes and content_sha256 are, in the vendor's words, "always populated so sync clients can diff without fetching content". That is thoughtful, and it helps a synchroniser rather than an agent trying to find something it has not already located by path.
Your path names are the index
With nothing scoring anywhere in the stack, the path is the retrieval key, and the naming scheme is the retrieval strategy.
A memory at /projects/acme/decisions/authentication.md offers several handles: a prefix to list, a segment to match, words to grep. A memory at /notes/item-47.md offers almost none. Both are stored equally well. Only one is reachable by an agent that does not already know it exists, and a memory nobody can address can stay unused indefinitely while looking perfectly healthy in the store.
Segment matching is the one indexing primitive you are given, and it is worth designing against deliberately: path_prefix=/notes/ returns /notes/todo.md but not /notes-archive/todo.md. Prefixes you can guess from the task, at a depth you can walk with depth=1, are worth more than a tidy taxonomy nobody queries.
The same fact has a security edge, and it is not the obvious one. The docs warn that a successful prompt injection "could write malicious content into the store", and "Later sessions then read that content as trusted memory.". Ranking would not save you there: a relevance model is not a trust boundary, and a planted file written to look exactly like what the agent is looking for scores well by construction. The controls that actually exist here are the ones the platform gives you at write time. Mount reference material read_only, since access "is enforced at the filesystem level". Keep untrusted input and trusted memory in separate stores. Use the version trail, which records who wrote what and when, and redact when something has to come out of history.
Decide the namespace up front. Every segment is a retrieval decision you are making by hand, because the platform is not making it for you.
Common questions
Does Anthropic's memory API have a search endpoint? No. The memory tool exposes six commands, and the Managed Agents memory API exposes create, retrieve, update, delete and list. Neither has a search endpoint or a query parameter. An agent can still run grep and glob against a mounted memory directory, but that search is lexical and unranked.
How does an agent find a memory in an Anthropic memory store? The store is mounted as a directory in the session sandbox, and the agent uses the same file tools it uses elsewhere: grep for regex text search, glob for patterns, and the list API filtered by path_prefix and depth. Nothing in that path applies a relevance score.
What is ranked retrieval, and why does its absence matter? Ranked retrieval selects candidates and orders them by an explicit relevance signal for the current request, the way BM25 or an embedding index does. Without it, an agent that cannot guess the right path or regex has no fallback, and the ordering it does get is stable rather than relevant.
What are the documented limits of an Anthropic memory store? 100 kB per memory, about 25k tokens, with paths up to 1,024 bytes; at most 10,000 memories per store and 8 stores per session. At the memory limit, writes to new memories fail while existing memories stay readable and editable.
Does Anthropic ship ranked search anywhere on the same platform? Yes, for tools: regex-based and BM25-based search tools out of the box, so an agent can find the few tools it needs inside a large library. That retriever is applied to tool names and descriptions, not to memories.
How many requests does enumerating a full memory store take? At 10,000 memories and a maximum page size of 100, at least 100 paginated requests; at view=full, capped at 20 per page, at least 500 to read every memory. Boundary arithmetic on published limits, not a measurement.
What happens when MEMORY.md exceeds its limit in Claude Code? The first 200 lines or 25KB are loaded at session start. Over that, the write still succeeds, but Claude Code returns an error telling Claude to rewrite the index, because everything past the limit is dropped on the next load.
Related
- What is an MCP memory server? makes the neighbouring argument one layer down: the MCP protocol itself defines no relevance model, so every server invents one.
- Memory API response shape asks what a ranked list cannot express even when you have one: supersession, retraction, authority.
- CLAUDE.md, AGENTS.md and Cursor rules do not enforce works the same context-versus-enforcement distinction that separates a prompt instruction from an API guarantee.
- Our own memory API takes the other road, ranking the read path rather than leaving it to path names.
Written by Edward Izgorodin. Sources fetched and quoted on 2026-09-03.
