oxagenDocs
Agent

Agent memory

What Oxagen keeps as a memory, where memories come from, and how a person turns the useful ones into steering records.

What a memory is for

A memory records something a person taught an agent that the agent could not find on its own. That is a correction, a refusal, a preference, or a decision, in the person's words, with what prompted it.

A fact an agent can read is not a memory. That covers anything the repository, its docs, a command's --help, or general knowledge already says. Where a pull request or an issue stands isn't a memory either. The issue holds that, and a status note goes stale within days.

KeepLeave out
"Dana, 2026-10-04: name the operator who wasted the money. Don't hide names on Spend."rg -r replaces matches. It does not search recursively.
"Dana rejected the recommended default and made the reason optional. Cut steps from a form before adding them."The billing tests live in packages/billing/src/.
"When Dana says a premise about the business, take it as given. Check the code, not the claim."PR #5114 merged, and the live check is still open.
"Dana owns the public site. Report an overclaim there and change nothing."Any rule already written in CLAUDE.md or AGENTS.md.

Help your agents keep better memories

Each harness decides what to write in its own memory. Add a line like this to CLAUDE.md or AGENTS.md so every agent follows the same rule:

md
Write a memory only for something you could not learn from this repository:
what I corrected, refused, preferred, or decided, in my words, with the
prompt that caused it. Put status in the issue, not in a memory.

When Oxagen asks a run for its lessons, it asks the same question. See Run lessons.

Where memories come from

Oxagen collects memories from every enrolled host as soon as an agent saves them. Nothing has to be turned on.

  • Claude Code. When a Claude Code call writes a file in a memory folder, the host sends that file within seconds.
  • Codex and Stella. The host watches Codex's memory store and each Stella context store it has read. A few seconds after one changes, the host reads that store and sends what is new.
  • Every five minutes. The host also reads every memory folder and store, and sends any memory the faster paths missed.
  • From the run's record. When a Claude Code run ends, Oxagen reads the memory files the run wrote. A file the host never sent becomes a memory from the text the run left in it. This needs Full transcript collection, which keeps each call's input and output.

One file on one host is one memory, whichever path brings it first.

SourceWhat Oxagen reads
Claude CodeEach project's memory folder, ~/.claude/projects/<project>/memory/*.md, and subagent memory folders. MEMORY.md is the index and is not a memory itself.
CodexCodex's memory store, ~/.codex/memories_1.sqlite.
StellaStella's context store.
Run lessonsWhat a run records with remember_lesson or record_reflection, or what Oxagen writes for a run that recorded none when Run summaries is Always.
ImportMarkdown files you import as memories with oxagen steering import --as memories.

Which Claude Code folders upload

The recorder places each Claude Code project folder before anything leaves the host. It checks again at every scan.

  • A workspace repository. The folder's checkout has an origin remote that names one of the workspace's repositories. Its memories upload, and each one names that repository.
  • Personal. The home folder, ~/Projects, and user subagent folders (~/.claude/agent-memory/). Their memories upload as personal.
  • Outside. Anything else, such as another project, a folder with no remote, or a deleted worktree. Nothing from it leaves the host.

Codex and Stella memories are not yet limited to the workspace's repositories.

Lines a pull request adds to CLAUDE.md, AGENTS.md, or a rules file don't become memories. Every run already loads those files. The repository check still compares each added line with the workspace's steering records and reports repeats and contradictions.

Run lessons

At the end of a Claude Code run that had a signal, the recorder asks the agent to call record_reflection. The signals are a failed call, a denial by a rule, the same call three times in a row, and a prompt that corrects the agent ("no", "actually", "don't", "stop", "not what I asked", and similar openers). When the signal is a correction, the ask quotes the prompt and asks what it teaches about how the person wants agents to work.

When a run with a signal records no reflection, Oxagen writes one from the run's steps. It does this only when the workspace's Run summaries setting is Always, because writing the reflection takes a model call. Under On demand or Never, Oxagen writes none. A reflection Oxagen writes keeps at most three lessons, each one something the person taught the agent. A lesson from a correction quotes the prompt that made it. Oxagen drops a correction lesson whose quote isn't in the prompt.

Every lesson leaves out what the repository, its docs, or general knowledge already says. A run that taught nothing new records no lessons.

Personal memories

A memory is personal when it comes from a personal folder, or when Claude Code typed it user. Only its operator and the workspace's Admins can read it. The curator never puts a personal memory in a memory PR.

How a memory moves

StateMeansLeaves by
waitingCollected, and in no memory PRPromote, the curator's batch, dismiss, or retirement
in_prAn open memory PR cites itThe PR merges (promoted) or closes (waiting again)
promotedIts steering record merged. The memory keeps counting uses.Its source is deleted (retired)
dismissedA person set it aside, with an optional reasonA person restores it
retiredIts source was deleted, nothing used it for retire_after_days (180 by default), or a newer rule superseded itIts source comes back, unless it was superseded

Nothing steers until a person merges a memory PR. Until then, a memory steers only the agent that wrote it, through its own harness. Oxagen embeds no memory and sends no waiting memory to another agent.

Uses

A use is one run that used a memory. A run that uses a memory five times counts once.

SourceWhat counts
Claude CodeA run reads the memory's file. Separately, a run's start loads the memory's line from the first 200 lines of MEMORY.md, which is an index load.
CodexCodex's own count of the times it used the memory.
StellaA citation Stella records.
Run lessons and importsA later run's lesson that says the same thing.

A rule that works from its one-line index entry steers the agent without the agent opening the file, so index loads count toward promotion. The Uses column on the Memories tab leaves them out, and the memory's drawer lists them. A lesson from the last 180 days that contradicts a memory cancels that memory's index loads.

Promotion

The curator runs once a day at 06:17 UTC, and also when 20 memories are waiting. It fills the open memory PR on memory/<date>, a pull request on the workspace's steering repository, with up to batch_size records (20 by default).

  1. Rank. Rules a person gave come first: a memory of kind preference, or a Claude Code feedback memory. Notes on where work stands come last: a Claude Code project memory. Every other memory sits between. Within each group, memories rank by uses, then index loads, then the newest use, then the newest capture.
  2. Fold copies. Memories that say the same thing become one record that cites them all.
  3. Supersede. When a newer rule covers the same topic as an older memory and replaces or reverses it, the older memory gives way. A waiting memory retires as superseded. A promoted memory's record is proposed for archiving in the memory PR, and a person decides. Oxagen archives only may and info records under steering/memory/. When the older rule lives in any other record, the memory PR lists that record under Records to update, and you edit or archive it.
  4. Propose. A memory joins the batch once one run has used it or loaded its index line. A personal memory never joins.

You can also promote memories yourself from the Memories tab or with oxagen memory promote. Oxagen suggests a kind and a force for each draft, and you can change both before it joins the PR.

Recall

At each prompt, the recorder on an enrolled host asks Oxagen for the merged memory records that fit the prompt and passes them to the agent with it.

  • Oxagen considers a record only within its scope: its repositories, its tools, and its paths.
  • It must share at least two content words with the prompt and reach a relevance score of 0.5. A prompt with no relevant record gets none.
  • A preference record's score counts 1.25 times.
  • Older records weigh less, halving every 30 days from the last review or merge. Serving a record doesn't reset its age.
  • A prompt gets at most 5 records and 800 tokens.

The ask carries the prompt's text, up to 8,000 characters, after the recorder cuts every credential it recognizes. Oxagen ranks with the text and keeps none of it. A workspace whose retention keeps only a hash of each prompt (digest_only) still sends the text, so recall works there too. A hash is a short code made from the text. Retention still decides what Oxagen keeps of the run.

The in-app assistant receives no workspace memories.

Dismiss and restore

Dismiss a memory that is wrong for the workspace or already covered. The reason is optional: covered, wrong, one_off, or other. The curator proposes a dismissed statement again only after memories from 2 more runs repeat it. Restore a dismissed memory to make it wait again.

Oxagen stores memories in Postgres, scoped to one workspace.

Capabilities

CapabilitySurfacesWhat it does
list_workspace_memoriesAPI, MCP, CLIList memories ranked by uses, with memories that say the same thing grouped.
get_workspace_memoryAPI, MCP, CLIRead one memory with its text, its source, the runs that used it, and its last memory PR.
suggest_memory_draftsAPI, MCP, CLISuggest a kind and a force for each memory you are about to promote. It writes nothing.
promote_memoriesAPI, MCP, CLITurn waiting memories into draft steering records on the memory PR.
dismiss_memoriesAPI, MCP, CLIDismiss memories so the curator stops proposing them, or restore dismissed ones.
list_memory_pr_recordsAPI, MCPList the records one memory PR proposes, with the memories each one cites.
drop_memory_recordAPI, MCP, CLIDrop one proposed record from an open memory PR.
remember_lessonMCPKeep one thing the person taught the agent in the current run. Oxagen stores it when the run ends.
record_reflectionMCPRecord a run's outcome, a summary, grades, and what the person taught the agent.

Memory from the CLI walks through the full workflow with oxagen memory.

On this page