Security

When an Agent Reads Its Own Memory: Preventing Feedback Loops

Antonio Evans10 min read

A close-up of a laptop screen showing a memory log with entries tagged 'agent-written' and a red loop icon connecting two such entries.
Key points

Key points

  1. 1Every memory write should record its author, so you can separate facts a human confirmed from summaries the agent wrote to itself.
  2. 2Feedback loops become visible when you trace which agent-written entries were later retrieved to justify the agent's next action.
  3. 3Cap the share of agent-authored memory that can be read back without review, and expire unreviewed entries so they cannot accumulate silently.
  4. 4Require a named human to approve any self-authored entry before the agent reuses it in a decision that touches money, customers or credentials.

Why agent-written memory turns into a loop

Persistent memory changes what an agent is. A stateless model answers within one context window and forgets; an agent with memory carries its past into every future session, and that is exactly where the risk concentrates the AI agent memory design guide. The design guide frames memory as three deliberate decisions (what to store, when to load, when to forget), and each one has failure modes that look like "the agent is unreliable" when they are really cases of nobody owning the memory layer.

The loop appears when the agent writes to that layer itself. An agent summarizes a tool output, stores the summary as a fact, retrieves it next week, and treats it as its own learned knowledge. The memory poisoning literature calls this the write-back loop: untrusted input flows in, gets stored as the agent's own recollection, and returns later as trusted context memory poisoning exploits that wait. That post notes OWASP added memory and context poisoning to its Top 10 for agentic applications, precisely because the attack and its effect are temporally decoupled.

You do not need an attacker for the loop to close. Self-summarization is enough. A retrieval agent reads a document, writes "the customer's contract renews in March" into memory, and three months later cites that memory to justify a renewal reminder. If the original document said April and the agent misread it, every downstream step now rests on the agent's own error, with no external check. Research on stale memory found that even the best evaluated model reached only 55.2% overall accuracy on tasks that required recognizing when a stored belief had been invalidated by later evidence the STALE benchmark. An agent is measurably bad at noticing that its own stored facts have gone out of date.

There is a second, subtler mechanism. A systematic study of memory poisoning identified four write channels into long-term memory, including system-prompt-driven writes and compaction-driven writes, where the agent condenses a long conversation and stores the summary From Untrusted Input to Trusted Memory. Compaction is the most dangerous channel for self-reinforcing loops because it is invisible: nobody asked the agent to remember anything, the runtime just trimmed context and kept the result. The same study found that agents designed to write and retrieve memory more aggressively are more exploitable, and that existing prompt injection defenses fail to cover this class of attack. Your eager memory configuration is a risk multiplier.

Detect the loop by tracing author and reuse

You cannot fix what you cannot see, so the first control is a schema change. Every memory entry gets an author field, a source reference, a write timestamp and a trust tier. Provenance tracking means every read can identify the exact payload behind a fact, not just a pointer to a document, because one extracted fact often draws on several sources at once how Zep models provenance. That analysis is worth reading even if you never use the product: it shows why a single source_id breaks when an LLM merges entities and invalidates facts.

A practical entry schema looks like this:

{
  "id": "mem_01J8XK",
  "author": "agent:retrieval-worker",
  "author_type": "agent",
  "derived_from": ["doc_4471", "mem_01J7QQ"],
  "trust_tier": "unverified",
  "written_at": "2026-03-04T09:12:00Z",
  "expires_at": "2026-04-03T09:12:00Z",
  "approved_by": null,
  "text": "Customer contract renews in March."
}

Two fields do most of the work. derived_from lets you walk backwards from any reused entry to the raw sources, including other memory entries, which is how you spot chains. author_type lets you run a query that counts how often agent-authored entries appear in retrieved context versus human-authored ones.

Then instrument the reuse side. Log, for every retrieval that fed a decision, the IDs of the entries returned and their author_type. A loop shows up as a rising ratio of agent-authored entries in retrieved context over successive sessions, and as chains where derived_from points to other agent-authored entries two or more hops deep. That chain depth is your single best metric. A fact derived from a document is depth 1. A summary of a summary of an agent's own earlier note is depth 3, and by then nobody can audit the origin without effort.

Here is a decision table you can hand to an engineer on day one:

SignalWhat it suggestsFirst action
Agent-authored share of retrieved context above your capLoop forming, review bypassFreeze new agent writes to that namespace
Derived-from chain depth of 2 or moreSelf-referential reasoningQuarantine the entry, re-derive from raw source
An entry retrieved to justify an action with no human approverReview bypassBlock the action, page the owner
Same entry retrieved across 3 or more unrelated tasksOver-broad influenceScope it to a single workflow or delete
Human override rate rising on tasks that cite memoryStale or wrong memoryRun a staleness audit on the cited entries

The MITRE ATLAS technique for memory manipulation is a useful shared reference when you write this up for security reviewers MITRE ATLAS reference in the memory defense walkthrough. That walkthrough also names the five-step workflow many teams adopt (authorize, tag, quarantine, audit, canary), which maps cleanly onto the schema above.

Cap self-authored entries with numbers, not intentions

Detection without limits is a monitoring exercise, not a control. Set concrete caps and put them in code where the memory write path can enforce them.

Start with a share cap. Decide what fraction of retrieved context may be agent-authored on a given task class. For low-stakes internal drafting, a generous cap is defensible. For anything that touches money, customer data or credentials, a tighter cap is the right call, and the honest starting point is zero unreviewed agent memory. Write the cap as a policy the retrieval layer enforces, not as a guideline in a wiki.

Then add count and depth limits. A per-namespace limit on unverified agent entries, a maximum derived_from chain depth of 1 for unreviewed entries, and a hard rule that an agent-authored entry can never be used to justify an action whose risk tier is above your threshold. The portable agent memory protocol makes a related point in its design: capability-scoped access tokens let you share specific knowledge subsets rather than all or nothing, and its re-hydration pipeline adds structural framing so recalled text cannot hijack the agent the Portable Agent Memory protocol. Borrow the idea even if you build your own store: scoped access, structural framing on read.

Expiry is the cheapest control and the one teams skip. Treat forgetting as a feature, with TTLs, freshness metadata and staleness detection built in from the start the memory design guide. A practical default: unverified agent entries expire in 30 days, reviewed entries in 180, and human-authored policy facts never expire but carry a review date. When an entry expires, do not delete it silently. Move it to a quarantine namespace, let the next retrieval treat it as untrusted, and record the expiry in your audit log so you can answer "why did the agent stop knowing this" later.

A worked example makes the arithmetic concrete. Suppose a support agent handles 1,000 tasks a day and retrieves 8 memory entries per task, for 8,000 retrievals. If its unverified agent-written share is 15%, that is 1,200 retrievals a day resting on entries no human has read. At that volume, a review queue cannot keep up, which is why caps must be enforced at read time rather than fixed by reviewing everything. Set the cap at 5% for the high-risk task class, route the overflow to a human-approvable draft, and the queue you actually have to staff becomes the small subset of writes the agent tried to make, not the full retrieval volume.

The self-improving agent literature makes the same distinction in workflow terms: a controlled feedback loop keeps the captured lesson separate from the live workflow, and only an approved update reaches deployment patterns for a safe feedback loop. That separation is the whole game. The agent may propose a memory write, but the write does not become retrievable context until it clears a gate.

Put a human gate in front of reuse

The gate belongs at reuse, not only at write. Agents write a lot; most writes are harmless. The expensive mistake is reusing an unverified entry to justify an action. So block on use.

A workable flow: the agent proposes a memory write with a rationale and its derived_from chain. The write lands in trust_tier: unverified and is retrievable only for read-only drafting. If the agent wants to cite that entry in a decision, the runtime creates an approval request containing the text, the raw source excerpt, and the chain, and assigns it to a named owner with a deadline. Until approved, the entry cannot be retrieved for any task above your risk threshold, and the agent receives an explicit instruction to proceed without it or stop.

The approval UI matters more than the policy. Show the reviewer the raw source next to the derived fact, because the whole failure mode is that the two read identically when provenance is dropped provenance in agent memory. A reviewer who sees only "Customer contract renews in March" will approve it. A reviewer who sees the source paragraph, the agent's diff, and the chain depth can catch the error in seconds.

Two more rules keep the gate honest. First, approval is per entry and per scope, not per agent: approving a fact for a read-only summary does not approve it for an outbound email. Second, any human override of an agent decision invalidates the entries that fed it, returning them to unverified and forcing the agent to re-derive. Without that rule, overrides are free lessons the agent never learns, and the same error returns next week.

If your retrieval layer has become the thing everyone debugs, and the memory writes are the part nobody owns, a structured review helps. A free 30 minute AI discovery call Quanta Consulting is a reasonable place to walk through your write paths, your current caps and the gate you want, and leave with a recommendation you can hand to engineering.

Test the loop before you trust the agent

Build a regression test that attempts the loop on purpose. Seed memory with an agent-authored entry that is subtly wrong, run the task that would retrieve it, and assert that the action is blocked or that the entry is flagged for review. This is the retrieval-side equivalent of a canary in the five-step memory defense workflow.

Then test the harder case: an entry that is correct when written and wrong later. New evidence invalidates an older belief without explicit negation, and models accept outdated assumptions embedded in a prompt the STALE benchmark. Write a test where a later document contradicts an approved memory fact, and check whether the agent resolves the conflict or keeps citing the old entry. If it cites the old entry, you need a write-time revision step, not just a read-time filter.

Measure three numbers and put them on a dashboard: agent-authored share of retrieved context, maximum derived-from depth in retrieved context, and median time from unverified write to human decision. The third one tells you whether your gate is real. A gate with a two-week backlog is a gate that the agent will route around, because the agent's task still has to complete.

Finally, keep a replay log. The agent evaluation community treats tracing as the entry point for debugging agent systems, precisely because a single agent run fans out into many distributed calls AI agent evaluation frameworks and feedback loops. Your memory retrievals belong in that trace alongside tool calls, so a postmortem can answer "which memory entry drove this decision" in one query rather than a forensic project.

A rollout sequence that survives audit

Sequence the work so each step is independently useful. Start with the schema change and author tagging, because without it nothing else can be measured. Then turn on logging of retrieved entry IDs and author types; run it for two weeks to establish a baseline share before you set any cap. Only then enforce caps, and only after that install the approval gate. Teams that install the gate first usually end up with a backlog and a frustrated agent, and they disable it.

Governance fits in the same sequence. Write down who owns each memory namespace, what the cap is per task class, and what the expiry defaults are. Keep the raw source excerpt for every approved fact for as long as the fact can be retrieved, so an audit can reconstruct the decision. If you run several agents against one shared store, give each agent its own write scope and a per-person API key model, so an incident review can attribute a bad write to a specific agent and person. Shared credit pools and per-person keys are what a team plan is for Quanta for Teams, and per-person keys are worth insisting on regardless of vendor.

One last discipline: review the caps quarterly against override rates. If your human override rate on memory-citing tasks is rising, your cap is too loose or your approval step is too shallow. If overrides are near zero, you may be paying for a gate that adds latency without catching anything, and the honest move is to widen the cap for that task class and spend the review effort where the errors actually occur.

FAQ

FAQ

How is this different from prompt injection?

Prompt injection manipulates a single interaction, and the effect ends when the session closes. Agent-written memory persists across sessions and influences decisions weeks later, so a single successful write can affect many future actions until it is detected and removed memory poisoning defenses. Input-level defenses do not cover it, which is why the controls in this article live at the memory write and reuse layer.

Can I just disable agent memory writes entirely?

You can, and for high-risk workflows an unreviewed-write cap of zero is a defensible starting point. The cost is that the agent stops improving from experience, and you lose the operational context that makes long-running agents useful the memory design guide. A better default is to allow writes but require human approval before reuse, so the agent keeps proposing lessons while a person controls which ones become policy.

How many entries can one agent safely write?

There is no universal number, so set it relative to retrieval volume rather than raw write count. A support agent retrieving roughly 8 entries per task across 1,000 tasks a day sees 8,000 retrievals, so a 5% unverified agent-authored share still puts about 400 decisions a day on unreviewed memory. Pick the share cap your reviewers can actually clear, then size the queue from that.

What do I do when I find a poisoned or wrong entry?

Quarantine first, then trace. Pull every entry whose derived_from chain includes the bad entry, move them all to unverified, and re-derive from raw sources. The 2025 MemoryGraft and MINJA work showed that poisoned memories get reused as if they were the agent's own proven playbook, so a single deletion is rarely enough; the derived entries carry the error forward memory poisoning across sessions.

Does a human gate make the agent too slow?

It only slows the paths that need it. Read-only drafting can proceed on unverified memory, while actions touching money, customers or credentials wait for approval. Because the gate is scoped to per-entry, per-scope reuse rather than every write, the queue stays small, and the agent's ordinary work continues without interruption.

Sources

Sources

  1. AI Agent Memory Design Guide - Working, Long-Term, and ...
  2. Memory poisoning in AI agents: exploits that wait
  3. STALE: Can LLM Agents Know When Their Memories Are ...
  4. A Systematic Study of Memory Poisoning Attacks in LLM ...
  5. How Zep tracks provenance in agent memory
  6. AI Agent Memory Poisoning Explained for Teams - YouTube
  7. Portable Agent Memory: A Protocol for Provenance ...
  8. How to Build Self-Improving AI Agents through Feedback ...
  9. AI Agent Evaluation Frameworks & Feedback Loops for ...
  10. https://www.trussed.ai/resources/ai-agent-memory-poisoning-risks-and-runtime-defenses
  11. Memory and context poisoning: Don't let attackers rewrite your AI agent's ...
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles