Reflection: From Experiences to Beliefs
Memory reflection that derives evidence-linked beliefs from episodic records.
A coding agent has been working with the same user for three months. The long-term episodic store holds 4,200 segmented episodes; each one a clean, salience-scored unit, every one of them admitted through a strict write-policy gate. Retrieval works. Recall is high. The agent can find the right episode for almost any query. And yet the agent feels flat. It remembers that the user reverted three pull requests last month, but it never noticed that all three reverts touched the auth subsystem and that the user has stopped trusting the auth refactor; it remembers eleven separate conversations about deploy retries, but it never abstracted “this user always wants to see logs before retrying”; it remembers each individual debugging session but doesn’t recognize the pattern in how this particular user debugs. The episodes are individually intact. The understanding is missing. The layer that turns raw observations into beliefs is the operation cognitive scientists call consolidation and the agent-memory literature, following Park et al. (2023), calls reflection.
Reflection as a materialized view
The cleanest distributed-systems parallel is the materialized view in a transactional database. In Postgres, a MATERIALIZED VIEW is a precomputed query result stored as a table; reads against the view are O(1) instead of O(table-scan); writes to the underlying tables don’t update the view automatically; a REFRESH MATERIALIZED VIEW has to be triggered. The trade-off is canonical: stale-but-fast reads for free, fresh reads cost a refresh. Production systems live on this trade-off; every analytics dashboard, every “top-K customers by revenue last month” query, every leaderboard, is the same shape.
Agent reflection recapitulates this exactly. The episodic store is the underlying table (every meaningful turn, append-only, expensive to aggregate). The reflection table is the materialized view (one row per derived belief, indexed for retrieval, fast to query). The reflection pass is the refresh operation; it reads from the episodic table, computes the aggregate, and writes to the view. Reads on the hot path query the view, not the underlying table; the cost of the higher-order answer is amortized over many reads. Three further parallels worth naming.
Refresh policy is the design surface, just like in databases. Postgres ships REFRESH MATERIALIZED VIEW CONCURRENTLY (locks the old version until the new one is built, then atomic swap) for live-traffic systems and REFRESH MATERIALIZED VIEW (blocks reads until done) for simpler workloads. The same trade-off shows up in reflection: reflect-on-trigger-with-concurrent-reads keeps the agent responsive while the reflection runs in the background; reflect-on-trigger-with-blocking-reads is simpler but means the next call after a trigger pays the reflection latency. Generative Agents implemented the latter (reflection runs inline at the importance-threshold breach); production systems lean toward the former.
View invalidation is the conflict-resolution problem. When a new episode contradicts a fact a reflection depends on, the view is stale. Postgres handles this manually; you have to REFRESH or set up triggers. Agent memory has to handle it more carefully because reflections aren’t typed enough to mechanically invalidate; the production answer in A-MEM and Memory-R1 is to keep a reflection’s evidence_ids as back-references to source episodes and run a background invalidation pass. A provenance walk and bi-temporal staleness gate can then walk dependents to a bounded depth and revalidate or mark them stale when a source becomes invalid.
Cascading materialized views; reflection on reflections. Generative Agents introduced a reflection tree: the leaves are episodes, the next layer is reflections over episodes, the next is reflections over reflections. The same shape exists in database systems (a materialized view over another materialized view), and the same caveat holds: the deeper the tree, the more compounded the staleness. The depth-2 reflection in Generative Agents is the canonical example; “I’m a researcher who values cleanliness” is a belief derived from beliefs (“I clean my workspace daily,” “I publish frequently,” “I attend conferences regularly”) that were themselves derived from raw episodes. Production reflection systems rarely go beyond depth-2 because each layer multiplies the invalidation surface.
Reflection loop
The mechanism Park et al. (2023) introduced is the canonical reference for every production reflection pass; knowing it by its components is what makes the implementations downstream legible.
Step 1; Trigger. Maintain a running sum of importance scores for every episode admitted since the last reflection. When the sum crosses a threshold (the paper uses 150 with their 1-10 scale, so roughly 15-20 high-importance episodes worth of accumulated signal), fire a reflection. The threshold is the consolidation analogue: not enough new signal, no reflection; enough new signal, refresh the view. Agents in the paper reflect about two-to-three times per simulated day under realistic interaction load.
Step 2; Salient question generation. Pull the 100 most recent records from the episodic store and prompt a large model: “Given only the information above, what are the 3 most salient high-level questions we can answer about the subjects in the statements?” This is the consolidation analogue of “what would be worth knowing about this period?”; the agent is generating its own retrieval queries against its own recent experience. The questions are not the output of reflection; they’re the index into the next step.
Step 3; Evidence retrieval per question. For each generated question, run a retrieval pass against the full episodic store (not just the recent window) and pull the top relevant episodes. This is the consolidation analogue of “what specific memories does this generalization rest on?”; the reflection process has to ground itself in concrete evidence, not in pure model intuition. The retrieval pass is the standard recency × importance × similarity rerank, scoped to the question.
Step 4; Insight generation with evidence references. Prompt the model: “What 5 high-level insights can you infer from the above statements? (example format: insight (because of 1, 5, 3)).” The output is a list of insights, each with explicit citation back to the source-episode IDs. This is the load-bearing structural pattern; every insight is anchored to its evidence, and the evidence IDs are stored alongside the insight. Without the citations, the insight is a free-floating claim; with them, it’s an audit-trail-bearing belief.
Step 5; Persist as a memory. The insights are written into the same episodic store, with a type=reflection tag, an evidence_ids field listing the source episodes, and a normal salience/importance score (often higher than typical raw episodes, since reflections are derived from many evidence pieces). On future retrieval, reflections are returned alongside raw episodes; the agent’s read path doesn’t have to know whether a returned memory is a raw observation or a reflection over many observations. The structural property: reflections sit in the same address space as the episodes they were derived from, which means recency × importance × similarity reranking works on both transparently.
The implementation is a five-step pipeline with explicit handoffs, not a single “summarize my recent memories” call.
Threshold-triggered reflection in Python
The smallest interesting build: an importance-sum-triggered reflector that runs the five-step Generative Agents loop against an existing Chroma-backed episodic store. Writes reflections back into the same store with the type=reflection tag and an evidence_ids field. Uses the Anthropic SDK for the question-generation and insight-generation calls. Install: pip install anthropic chromadb.
| |
the citation floor is structural, not stylistic; insights that cite fewer than two evidence IDs are dropped. This is the most-important quality-control knob in a reflection pipeline; without it, the model will emit free-floating claims (closer to a generic “the user seems thoughtful” than to a grounded “the user prioritizes API stability across these three PRs”). The renumber-then-remap pattern is what makes citations reliable; the model sees local 1-N integers that are easy to reference; the persistence layer remaps to real episode IDs that survive future store rewrites. The accumulator resets unconditionally after a cycle runs; even if zero insights are emitted, the cycle has consumed compute and the policy says “we tried.” Without the reset, a perpetual-fail state can spin the reflection pass in a tight loop and burn the budget; the unconditional reset is the circuit-breaker pattern for the reflection layer.
When reflection helps
Reflection is not always the right read-time substrate. The three regimes where it pays off, and the two where raw episodic recall wins.
Reflection wins when the query is about a pattern, not an instance. “What does this user usually want at deploy time?” is a pattern question; the right answer is a generalization over many past deploys, and surfacing one specific deploy episode misses the point. A reflection that says “this user wants logs and a manual approval gate before any deploy” is the right answer; the eight raw episodes that grounded it are noise on the read path. Pattern queries are the canonical reflection workload, and they’re also the queries where pure cosine recall over raw episodes underperforms most dramatically; the right answer is a synthesis, not a single hit.
Reflection wins when the working set of beliefs is small and the underlying episode set is large. A user who has 5,000 episodes in their long-term store probably has 30-50 stable beliefs the agent should know about them; preferences, recurring patterns, durable identity facts. The compression ratio is two orders of magnitude. Pre-paging the 30-50 beliefs into the system prompt is feasible; pre-paging the 5,000 episodes is not. Reflection is what makes the pinned-belief tier in hierarchical memory operationally tractable.
Reflection wins when the read path is latency-sensitive and the consolidation can run in the background. The cost of computing “what does this user usually want at deploy time?” from raw episodes is a multi-hop retrieval + summarization at read time; 1-3 seconds and a non-trivial token budget. The cost of reading a pre-computed reflection is one vector lookup; sub-50ms and a single short token block. For interactive agents where p95 latency matters, the only practical answer is to compute the higher-order answer once, materialize it, and serve it cheaply forever after.
Raw recall wins when the query is about a specific event. “When did the user mention they were vegetarian?” is an instance query; the right answer is a specific date and turn. A reflection that says “this user is vegetarian” is technically true but misses the actual question; the raw episode with the original turn and timestamp is the right answer. Mixing the two layers; surfacing a reflection when the user wanted the source episode; is a common production failure mode, and the fix is to type the read path: instance queries route to raw episodes, pattern queries route to reflections (with raw episodes as fallback or evidence).
Raw recall wins when the underlying episodes are still in flux. A user the agent has been working with for one week has too few episodes to consolidate from; the reflections that fire will be over-confident generalizations from too little evidence. The cognitive analogy is the same; systems consolidation is a slow process precisely because the brain doesn’t generalize from a single experience. Set a floor: the user has to have at least N high-salience episodes (50 is a defensible starting point) before reflection fires at all, or the early reflections will pollute the belief tier with shaky claims that have to be invalidated later.