How agents find things in memory: overview, search, and recall
A memory that exists but is never read is not memory. It is a file. The useful question is not "did the tool store it?" but "how does the next session find it, and what makes it look?"
There are three paths: something is pushed into the context at startup, the agent searches for it, or the agent reads a known note by path. Context is the text the model can see in one session. Each path fails differently. The most common failure is not a bad index. It is an agent that never took the first step.
Checked against each tool's documentation on 26–27 October 2026.
Three ways memory reaches an agent#
| Path | What it means | What it costs | How it fails |
|---|---|---|---|
| Startup injection | A file, hook or service puts text in front of the agent before the first turn. | Tokens on every session, whether or not the fact is used. | Truncated, empty, wrong project, or not configured. |
| Search | The agent calls a query tool and gets ranked hits. | Tokens only when used. | Wrong scope, wrong vocabulary, no capture, snippet mistaken for the note. |
| Known read | The agent opens a path or id it already knows. | The smallest read. | It does not know the path, or the note moved. |
"Recall" is usually a mix. A short index is pushed at startup, the agent searches when the index is not enough, and it reads the full note before acting. A tool that only does one of the three is incomplete for project work.
What each tool puts in front of the agent#
Claude Code#
Claude Code pushes instruction files at startup. CLAUDE.md is its instruction file; the memory docs describe it at managed, user, project and local scopes. Files above the working directory load at launch, and files in subdirectories load when Claude reads or edits a file there. Path-scoped rules load when a matching file is touched; a path-scoped rule is a rule file that stays out of context until a file matches its pattern.
Auto memory is Claude Code's own notes about a project, written by the model as it works. It is pushed as an index: the first 200 lines of MEMORY.md, or 25KB, load at the start of every session. The index is not the memory; it is one line per memory. The detail lives in a topic file under the memory directory, and those topic files are not loaded at startup. Claude reads them on demand with its normal file tools.
Status, 2026-10-26: the 200-line/25KB cap and on-demand topic files are documented. #82056 asks for an in-session receipt that says whether the index loaded whole or clipped; #91188 is about the compaction-reminder threshold, not a load failure.
That is file navigation, not a memory search command. The tools the docs describe for inspection are /memory, which lists and opens memory files, and /context, which shows what loaded. There is no documented "search my memory" query. If the index does not mention a topic, the agent has to think to open a topic file.
The failure modes follow:
MEMORY.mdgrew past the load limit, and the line the agent needed is below it.- The index line exists, but the agent does not open the topic file.
- Auto memory is off in that project, or this is a machine where it was never written.
- The agent is in the wrong repository, so it loaded the wrong project memory.
Claude Code's docs are explicit that CLAUDE.md is context, not enforcement. A sentence in the file shapes what Claude tries; a hook is what blocks an action. The same is true of a "look in memory" instruction: it raises the chance, it does not guarantee the call.
Codex#
Codex pushes AGENTS.md, its instruction file, at startup. The AGENTS.md guide says it builds the chain once per run, from the global file under CODEX_HOME (default ~/.codex) down through the project to the working directory, with project_doc_max_bytes limiting the project files to 32 KiB by default. Closer files appear later and override earlier guidance. A subdirectory AGENTS.override.md replaces the file in that directory.
Codex memories are a second layer. The memories page says they are off by default, stored under the Codex home (by default ~/.codex/memories/), and injected into future sessions when enabled. The store contains summaries, durable entries, recent inputs and supporting evidence. memories.use_memories controls injection; in the Codex TUI or the ChatGPT desktop app, /memories controls the current chat. The docs describe no memory search command and no per-item read tool; what the model receives is the injected memory summary.
Status, 26 October 2026: a desktop-app report says the injected summary is cut in the middle at 2,500 tokens, keeping half the budget from the start and half from the end, and dropping the newest entries in between with no warning (#48679, last updated 24 October 2026). A fact can be captured and still not reach the chat. No better query fixes that.
Because the store is one directory per Codex home, not per repository, a memory from another repository can enter the summary too. Ask which project the fact came from before you trust it in this one.
The failure modes are the same shape:
- The global
AGENTS.mdsays something that is wrong for this repository. - The project files hit the 32 KiB limit and dropped a nested file.
- Memories are off, the chat's read switch is off, or this chat used external context and was excluded from generation.
- The memory summary was cut, and the fact was in the middle.
- The agent treats the memory summary as the whole record; the supporting files are not exposed by a documented read tool.
The memories page gives the rule directly: keep required team guidance in AGENTS.md or checked-in documentation, and treat memories as a helpful recall layer.
Gemini CLI#
Run gemini --version first; this section describes v0.65.0 (20 October 2026). Gemini CLI has no memory search command. /memory is a viewer: show prints the text that loaded, list prints the paths, reload re-reads them. There is no query tool and no ranked result list, so "find it in memory" means the agent reads a file it was pointed at.
The push path is the context hierarchy. At startup the CLI concatenates ~/.gemini/GEMINI.md, the GEMINI.md files in the workspace and its ancestors, extension context, and the private per-project MEMORY.md index. /memory show prints the same text under the labels Global, Private Project Memory, Extension and Project. The footer shows how many context files loaded; the number is a count, not a list.
Two pull paths exist. A GEMINI.md below the working directory is not loaded at startup; the CLI scans for it when a tool touches that directory and appends it to the tool output. That is a just-in-time read, triggered by file access, not by a search. The other pull path is inside the private folder: MEMORY.md is loaded at startup, but a longer sibling note is read only if the index points at it and the agent opens it. A note with no pointer is on disk and invisible.
Imports are part of the push path. An @./file.md line inside GEMINI.md pulls that file into the loaded text; nested imports work and circular imports are stopped. A broken import leaves an error comment in the loaded text, so it shows up in /memory show.
The failure modes:
- The fact is in a sibling note, and
MEMORY.mdhas no pointer to it. - The fact is in a subdirectory
GEMINI.mdthe agent never touched. - The fact is in the global file and a project rule overrides it; project context wins over global.
- The fact is in a repository
GEMINI.mdon another branch or clone, so this checkout does not have it. - The fact is in the private memory of another folder; the private store is per working folder.
- The text loaded and the model ignored it. That is the use layer, not retrieval.
The fix is the same as the rest of the page: put the retrieval step in GEMINI.md ("read MEMORY.md and open the note before acting"), keep a pointer in the index, and ask for the path the answer came from. Do not ask the model whether it remembers; /memory show is the record of the startup context, and for a just-in-time file the tool output and /memory list are the record.
The command set is in what the memory command shows in Gemini CLI.
Qwen Code#
Qwen Code has no memory search command in its default setup: the model retrieves detail by opening the topic file that a MEMORY.md line points at. Qwen pushes two layers at startup; this is Qwen Code 0.26.2 (27 October 2026). The first is the context-file layer: the global ~/.qwen/QWEN.md, then QWEN.md and AGENTS.md from the working directory up to the git root, then .qwen/QWEN.local.md. The second is the auto-memory layer, appended after the context files: the user MEMORY.md, the project MEMORY.md, and the team MEMORY.md if team memory is on. Each MEMORY.md is an index of one line per memory; the topic files it links are not loaded at startup.
An opt-in structured recall mode changes that: memory.enableStructuredRecall (off by default, restart required) replaces the flat index with a tree, injects the subtree relevant to the request, and gives the model a search_memory tool. It also schedules a background migration that adds frontmatter to each memory file.
The index is the weak point. MEMORY.md is capped at 200 lines and 25,000 UTF-16 code units, and entries that do not fit are skipped whole, so an index that grew past the cap can drop a newly added line. The auto-memory prompt is the last layer of the system prompt and is rewritten after every save, which is why a new /remember can appear without a restart while a mid-session edit to QWEN.md does not: an external edit is not re-read; start a new session after editing a context file, while the agent's own context-file write is refreshed.
/context detail is the load check: its Memory files section lists each loaded context file plus an auto memory row with token counts. /memory opens the panel with the switches and folders; /dream runs consolidation, which can rewrite or drop entries.
The failure modes:
- The index line exists, and the agent never opens the topic file.
MEMORY.mdpassed 200 lines or 25,000 units, and the entry was dropped.- The fact is in another worktree; project auto-memory is per worktree, not per repository.
- A nested
QWEN.mdbelow the working directory was never discovered. context.fileNamereplaced the default names, soAGENTS.mdno longer loads.- Structured recall is off, so there is no search tool to call.
- The agent read a topic file earlier, compaction cleared the tool result, and it did not re-read.
The fix is the same shape as ai-memory: put the retrieval step in QWEN.md ("open the memory file before acting, and quote its path"), keep the index line specific, and ask for the path. Do not ask the model whether it remembers; /context detail is the record.
GitHub Copilot CLI#
Copilot Memory is a push path, not a search path. The service stores facts on GitHub's side and applies the relevant ones to a session; there is no memory folder to browse and no documented "search my memory" command. The CLI's /memory show command reports the switch and documentation links. It is not a query or a list of what the model saw.
Three tools sit around the store. The root agent can call store_memory or vote_memory; a subagent — a helper agent the main agent can start, whose context does not carry the whole conversation — can call read_memories to read stored memories but cannot write or vote (command reference). That is the closest thing to a recall tool in the CLI, and it is for the model, not a command you type.
What gets pushed is narrower than "everything Copilot knows". Repository facts are scoped to the repository, stored with citations, and checked against the current branch before use; only validated facts are used. User preferences are scoped to the user, and the CLI applies the preferences of the user who started the operation. A fact that goes unused for 28 days is deleted.
The failure modes follow:
- Memory is off.
/memory off, an organization policy, or prompt mode without--enable-memorymeans nothing is applied. In prompt mode the default is off. - The fact expired or failed validation. The citation no longer matches the branch, or the fact went unused for 28 days. There is no error in the session; the fact simply is not there.
- The scope is wrong. A repository fact from a similarly named repository can appear in a new one, according to an open report (#3945, open, 26 June 2026). A report says a non-GitHub
originfails writes, though old reads can still work (#3060, open, 30 April 2026). - The model ignores it. That is the use layer, not retrieval.
For Copilot CLI the common failure is not "the agent did not search". It is "the service had nothing validated to push, or memory was off". The fix is the same as the rest of this page: put the rule that must always apply in AGENTS.md or .github/copilot-instructions.md, and ask which citation the answer used when it depends on a remembered fact.
Run copilot --version first: the /memory command arrived in 1.0.49; /memory show gained the documentation links in 1.0.51, and the current release is 1.0.104 (27 October 2026).
OpenCode#
OpenCode pushes AGENTS.md and instructions at startup. V2 loads the global file, repository ancestors nearest-first, then instructions; V1 loads the global file and repository files and falls back to CLAUDE.md when no AGENTS.md is on the path. A nested AGENTS.md loads when the agent reads under it, not at startup. There is no memory index or search command; the agent finds a rule only if the file was loaded.
The failure modes:
- V2 does not read
CLAUDE.md. - The workspace is outside the repository, so only the global file loads.
- The rule sits in
instructionson an early 2.0.x where the array was inert (#51341, closed as completed 14 October 2026). - A nested file was never on a read path, or was edited after it loaded.
- The file loaded and the model ignored it. That is not a retrieval problem.
For the check, in V2 the OpenCode AGENTS.md guide shows the session instruction record (the list of files it stored); on both lines, a prompt log with the Instructions from: prefix is the check. opencode debug config shows config entries, not the discovered AGENTS.md. Do not ask the model whether it read the file.
ai-memory#
ai-memory has the most retrieval machinery, and the most ways to forget to use it. The usage docs describe:
memory_query: combines full-text search with entity and graph search, which use names and links between stored pages, plus optional vector search that compares meaning. It can filter by path, tag, kind or tier, read the wiki as it stood at a date, and show why a hit ranked.memory_briefing: a read-only project map with counts and recent pages.memory_recent: recent pages, no query.memory_read_page: the full page.memory_handoff_listandmemory_handoff_accept: list a pending handoff, then claim it once. A handoff is a short note that tells the next session where the work stands.
The startup packet is the weak point. In our test of version 3.2.5, a Codex SessionStart with no pending handoff and no briefing opt-in produced no output. The agent had to know to call memory_briefing or memory_query. When we added [briefing] inject_on_session_start = "true", the injected brief listed recent pages by title only. The correction body was not in it, so an agent that trusted the title could still act on the old claim.
The search itself worked. A query for "staging deploy cold runner" returned the page, and memory_read_page returned the body. The retrieval path was sound; the agent needed a reason to start it.
Documented limits matter too. A query in a project does not return another project's pages unless it is global or scoped. The ai-memory README says Chinese, Japanese or Korean text without spaces is supported. Very long queries and snippet-only answers are the limits; read the page, not only the snippet.
Why "the agent didn't look" is the normal failure#
A model calls a tool because the context makes the call likely, not because the tool exists. Three things have to line up:
- The tool is available. The MCP server is configured for that project, with a key that can see the note. MCP is the protocol an agent uses to call an outside tool.
- The agent knows to call it. The instruction file says to read the overview or search memory before acting.
- The scope is right. The project, workspace or folder key points at the store that holds the fact.
When one is missing, the agent answers from the code, the conversation, or a guess. It usually sounds confident. That is why the failure is silent. If you need to prove that capture happened at all, the check guide covers that separately.
The fix is procedural, not clever:
- Put the retrieval step in the instruction file. "Call the overview first. Read the note before acting. Quote the path."
- Use a startup hook where the tool has one. A hook is a script the harness runs at an event, and it runs even when the model would skip a sentence in a file.
- Keep a short index note with one line per important decision, and link the detail.
- Ask the agent to name the file, note path, revision (the saved version number) or date it used. If it cannot, it did not read one.
- When a search misses, check scope before you change the query. The note may be in another project or folder.
- When it still misses, write the fact down. A retrieval system cannot return what was never captured.
Which path fits which job#
| Need | Use | |
|---|---|---|
| A rule that must be present on every task | A short CLAUDE.md or AGENTS.md, or a startup hook. | |
| A rule in front of Qwen Code | A short QWEN.md or AGENTS.md, or .qwen/QWEN.local.md. Both default names load at startup; context.fileName replaces the list. | |
| A fact Qwen Code learned | The MEMORY.md index line plus the topic file. The index is pushed; the topic needs a read, and there is no search tool unless structured recall is on. | |
| A rule in front of OpenCode | A short AGENTS.md or an instructions entry. It loads at startup; there is no index to search. | |
| A fact for this project only, on this machine | The private MEMORY.md index, with the detail in a sibling note; the index loads at startup and the note needs a pointer and a read. | |
| A fact that may be relevant | Search, then read the full page. | |
| A fact Copilot learned on its own | Copilot Memory | Pushed when the service has a validated fact; there is no search command. A rule that must be found belongs in AGENTS.md. |
| An exact record you can name | Read by path. | |
| Work that must reach the next session | A handoff file or handoff tool. The handoff guide covers the content. | |
| Several agents or machines | A shared store, plus the same instruction in every agent's rule file. | |
| Nothing yet | Write the note. Retrieval is the second problem. |
Noteheld is the pull-only case: nothing is pushed at startup. Nothing loads unless the agent calls a tool. The overview maps the workspace, search returns a line, and read opens the note. A folder key that does not cover the note returns outside_scope rather than an empty answer. It suits a small, curated tree where the instruction file already tells the agent to look, and it is a poor fit when you need recall without that instruction. Notes are plaintext on the server, and version 1 does not encrypt note bodies end to end.
If your problem is "the agent did not look", the first fix is a sentence in the instruction file and a check that the key reaches the note. The store comes second.