# Memory Engineering: Designing Agent Memory That Gets Smarter Instead of Bloating
**作者**: zostaff
**日期**: 2026-08-02T14:34:29.000Z
**来源**: [https://x.com/zostaff/status/2083924400252875110](https://x.com/zostaff/status/2083924400252875110)
---

There is a temptation to think of agent memory as a database where you dump everything the agent has seen, to pull out later. That definition is the first mistake. An agent that stores everything does not get smarter, it gets slower and starts retrieving stale junk that poisons its reasoning. Memory that helps is built the opposite way: it forgets, compresses, and turns events into lessons. An agent gets smarter not by storing more, but by consolidating what it stores.
By 2026 the industry converged on a taxonomy from cognitive science, formalized for LLMs in Princeton's CoALA framework. Agent memory is four distinct mechanisms, not one database, and confusing them means building a system that breaks predictably. This article is about what memory is made of, how forgetting works, why consolidation is the main mechanism, and where memory becomes an attack surface. With code and mechanics, not a vendor survey.
## Four types of memory, and why they cannot be mixed
Agent memory is not one layer. It is four mechanisms with different lifetimes, different contents, and different retrieval.
> Working memory. This is the context window, the only memory the model reasons over directly. Everything else must be retrieved into it to influence the output. Lives within a single inference. Episodic memory. Specific past events bound to a moment: what happened, when, in what context. Preserves specificity. This is the agent's raw experience. Semantic memory. Generalized knowledge extracted from episodes: facts, rules, preferences with no binding to a particular case. This is what the agent understood, not what happened to it. Procedural memory. Skills and ways of acting: how to perform a task, not what is known about it. In coding agents this lives in files like CLAUDE.md, where working procedures reside.
The key distinction runs between episodic and semantic. An episode is "on February 14 the trade on stock X lost money on an earnings report." Semantics is "before earnings volatility rises, enter more carefully." The first is an event, the second is a lesson extracted from many events. An agent that stores only episodes remembers everything and understands nothing. The transition from one to the other is where memory begins to work.

Different types require different stores, and this is an architectural decision, not a detail. Episodic memory lives on a hybrid of vector plus graph, because events must be searched both by meaning and by the links between them. Semantic memory fits a graph or key-value store, where facts are held exactly. Procedural memory lives in files. Mixing backends for one type or running everything through a single vector index means losing what each layer rests on.

## Consolidation: how episodes become knowledge
Consolidation is the mechanism turning episodic memory into semantic: clustering similar events and extracting a generalized lesson from them. Per the February 2026 work on episodic memory, it is consolidation, not storage volume, that makes an agent capable of long-term reasoning.
Formally it is two steps: group related episodes and summarize each group into a compact rule. A naive system stores a thousand episodes and retrieves them one by one. A consolidating system folds that thousand into a dozen rules with conditions of applicability and stores the rules, sending the episodes to a cold archive.

```
def consolidate(episodes: list[Episode], min_cluster: int = 5) -> list[SemanticRule]:
clusters = cluster_by_similarity(episodes) # group similar events
rules = []
for cluster in clusters:
if len(cluster) < min_cluster:
continue # a single case is not generalized: it is noise
rule = summarize_to_rule(cluster) # extract a rule from the group
rule.support = len(cluster) # how many episodes it rests on
rule.condition = extract_condition(cluster) # under what conditions it holds
rule.observed_range = date_span(cluster) # observation period
rules.append(rule)
return rules
```
The min_cluster threshold is fundamental here and guards against the main error of consolidation: generalizing a single case. One loss is not a regularity, it is an episode. A rule derived from one event is overfitting to noise, exactly as in a backtest. A rule earns its existence only when it rests on a sufficient number of independent episodes, and the support count must be stored with the rule to weight trust in it later.
This consolidation need not run in the hot path. The productive pattern is background consolidation during idle time, between sessions, analogous to how the brain consolidates memory in sleep. A separate sub-agent in the background reads accumulated episodes and updates the semantic layer while the main agent is not working. That keeps the hot path fast and lets knowledge accumulate offline.
## Forgetting is design, not a failure
Here is the main mental shift, and it is counterintuitive. Forgetting is not a memory deficiency, it is its function. A system that stores everything forever grows linearly, slows on retrieval, and accumulates stale material that will eventually surface and poison reasoning. Biological memory forgets deliberately, and artificial memory must too.
Forgetting should be done not by timer deletion but by managed decay of accessibility. There are several policies, and they combine.
> Temporal decay. A record's accessibility falls with age along a forgetting curve, exponential or Weibull. The old is not deleted abruptly, it becomes less weighty at retrieval. Importance-weighted forgetting. The probability of forgetting is inverse to a record's importance. The critical is held longer than the routine at equal age. Spaced reinforcement. A record accessed many times is held longer. Frequently used knowledge should not fall out from age alone. Budget eviction. On budget overflow, the least valuable is evicted, where value is a combination of freshness, importance, and access frequency.

```
def retention_weight(mem, as_of: date) -> float:
age = (as_of - mem.last_access).days
# forgetting curve: exponential decay modulated by importance and frequency
decay = 0.5 ** (age / mem.half_life_days)
reinforcement = min(1.0, mem.access_count / 10) # frequent records are held longer
return mem.importance * decay * (0.5 + 0.5 * reinforcement)
def evict_to_budget(memories: list, budget_tokens: int, as_of: date) -> list:
ranked = sorted(memories, key=lambda m: retention_weight(m, as_of), reverse=True)
kept, used = [], 0
for m in ranked:
if used + m.tokens <= budget_tokens:
kept.append(m); used += m.tokens
else:
archive(m) # not deleted, sent to a cold archive
return kept
```
Note that the evicted is not deleted but moved to a cold archive. This distinction matters: hard deletion loses data forever, while decay of accessibility merely removes a record from hot retrieval, leaving the option to pull it up if it is suddenly needed. Forgetting by design is management of accessibility, not destruction.
The practical effect is measurable: biologically inspired forgetting schemes cut storage volume noticeably, on the order of forty percent and higher, while improving multi-hop reasoning accuracy, because the model stops drowning in irrelevant old records.
## Conflicts and staleness: why memory lies over time
A separate class of problems arises when facts change. A user changed jobs, a company changed strategy, a market regime shifted. Naive memory stores both the old record and the new, and at retrieval returns both with no resolution mechanism. This is called conflict blindness, and without active conflict resolution stale facts accumulate and start poisoning reasoning.
Conflict resolution is not automatically choosing the newer record, because newer is not always truer. It is weighting by source reliability, freshness, and consistency with the rest of the knowledge. Contradicting evidence should shift weight away from the old value, not just be added beside it.
```
def resolve_conflict(existing: Memory, incoming: Memory) -> Memory:
# newer does not mean truer: weight by reliability and consistency
if incoming.contradicts(existing):
if incoming.reliability > existing.reliability:
existing.confidence *= 0.5 # the old is devalued, not erased at once
return incoming.with_provenance(supersedes=existing.id)
else:
incoming.confidence *= 0.5 # unreliable new does not overwrite reliable old
return merge(existing, incoming)
```
The key here is that the old record is not erased instantly but devalued. If the new evidence turns out wrong, the old can be restored. And every supersession keeps provenance: which record replaced which and on what grounds. In regulated domains this is not a luxury but a requirement: you must be able to explain why the agent believes what it does.
## Memory as an attack surface
The thing almost never covered in memory articles, but which became critical in 2026. Once an agent stores and reuses memory, that memory becomes an attack vector. OWASP added memory poisoning to its list of agentic system threats as ASI06.
The attack mechanic is simple and therefore dangerous. Through ordinary interaction, an attacker plants a false record in the agent's memory that later influences decisions. There are studied variants: injection through queries alone with a high success rate, and sleeper poisoning, where a harmful record is planted in one session and activates in the next. The latter is especially insidious, because the time gap between planting and activation masks the source.
Defense is built on several levels, and none is sufficient alone.
> Source trust scoring. Every record carries a source reliability score, and a record from an unreliable source has no right to overwrite reliable knowledge, as in conflict resolution above. Provenance for every record. Where the record came from, when, from what interaction. A record without traceable origin is suspect by definition. Consensus during reasoning. Poisoning can be detected by divergence: if one reasoning path relies on a record contradicting several others, the record is under suspicion. Provenance capping. A record from a low-trust channel cannot influence high-risk decisions, even if it technically made it into memory.
An important conclusion from this: pure retrieval over a vector store is structurally incapable of forgetting and incapable of defending, because it only pulls the similar, without assessing where the similar came from or whether it went stale. Memory as an attack surface requires the model to become an active participant in curating its own memory, not a passive consumer of what retrieval returned.
At the code level, defense is a gate on write and a gate on use. A record from an unreliable source must not silently settle into memory alongside verified ones, and at retrieval for an important decision, records below the trust floor are cut.
```
TRUST = {"verified_db": 1.0, "internal_tool": 0.8, "user_input": 0.5, "web_scrape": 0.3}
def admit(record, existing: list) -> bool:
record.trust = TRUST.get(record.source, 0.2)
# consensus: a record contradicting several reliable ones is suspect
contradictions = [m for m in existing
if m.contradicts(record) and m.trust >= 0.8]
if contradictions and record.trust < 0.8:
quarantine(record, reason="contradicts a reliable consensus")
return False
return True
def use_for_decision(memories: list, risk: str) -> list:
# for high-risk decisions the trust floor is higher
floor = {"low": 0.3, "medium": 0.5, "high": 0.8}[risk]
return [m for m in memories if m.trust >= floor]
```
The key here is that the trust floor depends on the decision's risk. A record from user input is fine for a draft note, but for a decision about capital or refusing a client, only high-trust sources are admitted. Sleeper poisoning breaks exactly on this: a harmful record from a low-trust channel physically cannot reach a high-risk decision, however many sessions pass between planting and activation.
## Procedural memory: the most underrated layer
Of the four types, procedural memory is the least developed in tooling, and that is exactly why it gives the most leverage to whoever designs it deliberately. Semantic memory makes an agent informed. Procedural memory makes it better at its job.
Procedural memory is how an agent performs a task, not what it knows about it. In coding agents it lives declaratively, in files like CLAUDE.md or AGENTS.md that are injected into context automatically. This is a lightweight and maintainable form of procedural memory: working procedures, conventions, proven sequences of actions written as text and delivered to the agent as an instruction to act.
The power of this layer is that it closes the self-improvement loop. The agent performed a task, extracted a lesson about how to do it better, and wrote that lesson into procedural memory, from which it will be pulled next time. This is the evolving-context approach: the generator produces a result, the reflector finds errors and omissions, the curator extracts lessons and updates the procedural playbook. By research, such a loop yields around ten percent gains on agent benchmarks without any fine-tuning of the model, purely because procedural memory accumulates correctly.
```
def self_improve(task, playbook: list[str]) -> list[str]:
# GENERATOR: performs the task with the current playbook in context
result = generator.run(task, context=playbook)
# REFLECTOR: evaluates the result, finds errors and omissions
critique = reflector.run(task, result)
if critique.is_clean:
return playbook # nothing to learn, leave the playbook
# CURATOR: turns the found error into a procedural lesson
lesson = curator.extract_lesson(critique)
# dedup: do not breed near-identical items (guards against context erosion)
if not any(similar(lesson, p) for p in playbook):
playbook.append(lesson) # add ONE item, do not rewrite
return playbook[-MAX_PLAYBOOK:] # keep the playbook bounded
```
Two details separate a working loop from one that degrades. Dedup keeps the playbook from bloating with near-identical lessons that pile up when the reflector catches the same class of error again and again. And adding one item instead of rewriting the whole playbook guards against the very erosion of context where rewrites lose conditions and caveats. A lesson is added as a separate line with a condition of applicability, not melted into common text where the next compaction will erase it.
The difference between a semantic and a procedural lesson is subtle but important. Semantic lesson: "this library is slow on large arrays." Procedural lesson: "for large arrays, reach for this library and this call pattern from the start." The first informs, the second changes the action. Procedural memory is where an agent's performance compounds, and where vendors give the least off-the-shelf, so you design it by hand.
## Build order
The technical order of assembling agent memory: first separate the four types into different stores with different lifetimes, then set up consolidation of episodes into semantics with a threshold on support count, then forgetting by design as managed decay of accessibility rather than deletion, then conflict resolution through devaluation with provenance, then defense against poisoning through source trust and consensus, and separately procedural memory as a self-improvement loop. Each mechanism closes its class of problems: separating types keeps an event from being mixed with a lesson, consolidation turns volume into knowledge, forgetting keeps the system fast and clean, conflict resolution keeps stale facts from poisoning reasoning, poisoning defense holds the trust boundary, procedural memory accumulates mastery. Memory assembled this way gets smarter over time. Memory assembled as a dump of everything only bloats and lies over time.
## 相关链接
- [zostaff](https://x.com/zostaff)
- [@zostaff](https://x.com/zostaff)
- [4.1K](https://x.com/zostaff/status/2083924400252875110/analytics)
- [Upgrade to Premium](https://x.com/i/premium_sign_up)
- [10:34 PM · Aug 2, 2026](https://x.com/zostaff/status/2083924400252875110)
- [4,175 Views](https://x.com/zostaff/status/2083924400252875110/analytics)
---
*导出时间: 2026/8/3 10:48:41*
---
## 中文翻译
# 记忆工程:设计越来越智能而非膨胀的 Agent 记忆
**作者**: zostaff
**日期**: 2026-08-02T14:34:29.000Z
**来源**: [https://x.com/zostaff/status/2083924400252875110](https://x.com/zostaff/status/2083924400252875110)
---

人们很容易误以为 Agent 的记忆就是一个数据库,把 Agent 看到的所有东西都倒进去,以便日后取用。这种定义是第一个错误。一个存储一切的 Agent 不会变得更聪明,只会变慢,并开始检索出陈旧的垃圾信息,毒害其推理能力。有帮助的记忆构建方式恰恰相反:它遗忘、压缩,并将事件转化为经验教训。Agent 变得智能不是通过存储更多,而是通过整合它所存储的内容。
到 2026 年,行业已经达成共识,采用了认知科学中的分类法,并由普林斯顿大学的 CoALA 框架针对大语言模型进行了形式化。Agent 记忆是四种不同的机制,而不是一个数据库,混淆它们意味着构建一个会可预测性地崩溃的系统。本文将探讨记忆的构成、遗忘的工作原理、为什么整合是核心机制,以及记忆在何处成为攻击面。我们将讨论代码和机制,而不是对供应商的调研。
## 四种记忆类型,以及为何不能混用
Agent 记忆不是单一的一层。它是四种具有不同生命周期、不同内容和不同检索方式的机制。
> 工作记忆。这是上下文窗口,是模型直接进行推理的唯一记忆。其他所有内容必须检索到其中才能影响输出。生命期仅限于单次推理。
> 情景记忆。绑定到特定时刻的特定过去事件:发生了什么,何时发生的,在什么情境下。保留了特异性。这是 Agent 的原始经验。
> 语义记忆。从情景中提取的广义知识:事实、规则、偏好,不绑定到特定案例。这是 Agent 理解的内容,而不是发生在它身上的事情。
> 程序记忆。技能和行动方式:如何执行任务,而不是关于任务的知识。在编码 Agent 中,它存在于像 CLAUDE.md 这样的文件中,存放着工作程序。
关键的区别在于情景记忆和语义记忆之间。情景记忆是“2 月 14 日,股票 X 的交易在财报发布后亏损”。语义记忆是“在财报发布前波动性上升,应更谨慎入场”。前者是一个事件,后者是从许多事件中提取的教训。一个只存储情景记忆的 Agent 记住了一切却什么都不理解。从一种记忆向另一种记忆的过渡,正是记忆开始发挥作用的地方。

不同的类型需要不同的存储,这是一个架构决策,而非细节。情景记忆存在于向量加图的混合体中,因为事件必须通过含义以及它们之间的链接进行搜索。语义记忆适合图或键值存储,其中事实被精确保存。程序记忆存在于文件中。将一种类型的后端混合,或者将所有内容通过单个向量索引运行,意味着丢失了每一层所依赖的基础。

## 整合:情景如何转化为知识
整合是将情景记忆转化为语义记忆的机制:将相似事件聚类,并从中提取广义的教训。根据 2026 年 2 月关于情景记忆的研究,使 Agent 具备长期推理能力的是整合,而不是存储量。
形式上它分为两步:将相关情景分组,并将每组总结为一个紧凑的规则。一个简单的系统会存储一千个情景并逐一检索。一个执行整合的系统会将这一千个情景折叠为十几个带有适用条件的规则,存储这些规则,并将情景发送到冷归档。

```
def consolidate(episodes: list[Episode], min_cluster: int = 5) -> list[SemanticRule]:
clusters = cluster_by_similarity(episodes) # 对相似事件进行分组
rules = []
for cluster in clusters:
if len(cluster) < min_cluster:
continue # 单个案例不是泛化:它是噪声
rule = summarize_to_rule(cluster) # 从组中提取规则
rule.support = len(cluster) # 它依赖于多少个情景
rule.condition = extract_condition(cluster) # 它在什么条件下成立
rule.observed_range = date_span(cluster) # 观察周期
rules.append(rule)
return rules
```
这里的 `min_cluster` 阈值至关重要,它防止了整合的主要错误:将单个案例泛化。一次亏损不是规律,而是一个情景。从单一事件推导出的规则是对噪声的过拟合,就像回测一样。一个规则只有当它依赖于足够数量的独立情景时才有存在的资格,并且支持计数必须与规则一起存储,以便在后续评估对它的信任度。
这种整合不需要在热路径中运行。高效的模式是在空闲时间或会话之间进行后台整合,类似于大脑在睡眠中整合记忆。一个后台的子 Agent 在主 Agent 不工作时读取积累的情景并更新语义层。这保持了热路径的快速,并允许知识离线积累。
## 遗忘是设计,不是失败
这是主要的心态转变,也是反直觉的。遗忘不是记忆缺陷,而是它的功能。一个永远存储所有内容的系统会线性增长,检索变慢,并积累最终会浮现并毒害推理的陈旧材料。生物记忆是有意遗忘的,人工记忆也必须如此。
遗忘不应通过定时删除来完成,而应通过可访问性的受控衰减来完成。有几种策略,它们可以结合使用。
> 时间衰减。记录的可访问性随年龄沿遗忘曲线下降,指数或威布尔分布。旧记录不会被突然删除,而是在检索时权重降低。
> 重要性加权遗忘。遗忘的概率与记录的重要性成反比。在同等年龄下,关键内容比常规内容保留时间更长。
> 间隔强化。被多次访问的记录保留时间更长。频繁使用的知识不应仅因时间久远而丢失。
> 预算驱逐。当预算溢出时,驱逐价值最低的,其中价值是新鲜度、重要性和访问频率的组合。

```
def retention_weight(mem, as_of: date) -> float:
age = (as_of - mem.last_access).days
# 遗忘曲线:由重要性和频率调节的指数衰减
decay = 0.5 ** (age / mem.half_life_days)
reinforcement = min(1.0, mem.access_count / 10) # 频繁记录保留更久
return mem.importance * decay * (0.5 + 0.5 * reinforcement)
def evict_to_budget(memories: list, budget_tokens: int, as_of: date) -> list:
ranked = sorted(memories, key=lambda m: retention_weight(m, as_of), reverse=True)
kept, used = [], 0
for m in ranked:
if used + m.tokens <= budget_tokens:
kept.append(m); used += m.tokens
else:
archive(m) # 不删除,发送到冷归档
return kept
```
请注意,被驱逐的内容不是被删除而是移动到冷归档。这一区别很重要:硬删除会永久丢失数据,而可访问性的衰减只是将记录从热检索中移除,保留了在突然需要时将其提取出来的选项。有意的遗忘是对可访问性的管理,而非销毁。
实际效果是可测量的:受生物学启发的遗忘方案显著减少了存储量,大约在百分之四十或更多,同时提高了多跳推理的准确性,因为模型不再被无关的旧记录淹没。
## 冲突与陈旧:为什么记忆会随时间撒谎
当事实发生变化时,会出现一类独立的问题。用户换了工作,公司改变了战略,市场制度发生了转变。简单的记忆会同时存储旧记录和新记录,并在检索时同时返回两者,而没有解决机制。这被称为冲突盲视,如果没有主动的冲突解决,陈旧的事实就会积累并开始毒害推理。
冲突解决不是自动选择较新的记录,因为新并不总是更真。它是通过来源可靠性、新鲜度以及与知识其余部分的一致性来加权。矛盾的证据应该降低旧值的权重,而不仅仅是添加在旁边。
```
def resolve_conflict(existing: Memory, incoming: Memory) -> Memory:
# 较新并不意味着较真:按可靠性和一致性加权
if incoming.contradicts(existing):
if incoming.reliability > existing.reliability:
existing.confidence *= 0.5 # 旧记录被贬值,而非立即擦除
return incoming.with_provenance(supersedes=existing.id)
else:
incoming.confidence *= 0.5 # 不可靠的新内容不能覆盖可靠的旧内容
return merge(existing, incoming)
```
这里的关键是旧记录不会立即被擦除,而是被贬值。如果新证据后来被证明是错误的,旧的可以被恢复。每一次取代都保留出处:哪个记录替换了哪个,基于什么理由。在受监管的领域,这不是奢侈品而是要求:你必须能够解释 Agent 为什么相信它所相信的。
## 记忆作为攻击面
这是记忆文章中几乎从未涵盖的内容,但在 2026 年变得至关重要。一旦 Agent 存储并重用记忆,该记忆就成为了一个攻击向量。OWASP 将记忆中毒添加到其 Agent 系统威胁列表中,代号为 ASI06。
攻击机制简单因此危险。通过普通的交互,攻击者在 Agent 的记忆中植入一条虚假记录,该记录后来会影响决策。有经过研究的变体:仅通过查询注入的成功率很高;以及休眠中毒,即在一次会话中植入有害记录并在下一次会话中激活。后者尤其阴险,因为植入和激活之间的时间差掩盖了来源。
防御建立在几个层面上,没有任何一个层面是单独足够的。
> 来源信任评分。每条记录都带有来源可靠性评分,来自不可靠来源的记录无权覆盖可靠的知识,如上文的冲突解决所示。
> 每条记录的出处。记录来自哪里,何时,来自什么交互。没有可追溯来源的记录根据定义就是可疑的。
> 推理期间的共识。中毒可以通过分歧来检测:如果一条推理路径依赖于一条与其他几条相矛盾的记录,则该记录受到怀疑。
> 出处上限。来自低信任渠道的记录不能影响高风险决策,即使它在技术上进入了记忆。
由此得出一个重要结论:对向量存储的纯检索在结构上无法遗忘,也无法防御,因为它只是拉取相似的内容,而不评估相似内容来自哪里或是否已过时。作为攻击面的记忆要求模型成为管理自身记忆的积极参与者,而不是检索返回内容的被动消费者。
在代码层面,防御是写入关卡和使用关卡。来自不可靠来源的记录绝不能静默地与已验证的记录一起在记忆中安家,并且在检索重要决策时,低于信任底线的记录会被剔除。
```
TRUST = {"verified_db": 1.0, "internal_tool": 0.8, "user_input": 0.5, "web_scrape": 0.3}
def admit(record, existing: list) -> bool:
record.trust = TRUST.get(record.source, 0.2)
# 共识:与多条可靠记录相矛盾的记录是可疑的
contradictions = [m for m in existing
if m.contradicts(record) and m.trust >= 0.8]
if contradictions and record.trust < 0.8:
quarantine(record, reason="contradicts a reliable consensus")
return False
return True
def use_for_decision(memories: list, risk: str) -> list:
# 对于高风险决策,信任底线更高
floor = {"low": 0.3, "medium": 0.5, "high": 0.8}[risk]
return [m for m in memories if m.trust >= floor]
```
这里的关键是信任底线取决于决策的风险。来自用户输入的记录用于起草笔记是可以的,但对于关于资本或拒绝客户的决策,只允许高信任来源。休眠中毒正是被这一点攻破的:来自低信任渠道的有害记录无论在植入和激活之间间隔多少次会话,都无法从物理上到达高风险决策。
## 程序记忆:被低估的一层
在这四种类型中,程序记忆在工具方面是最不发达的,而这正是为什么它能为任何有意设计它的人提供最大的杠杆作用。语义记忆让 Agent 博学。程序记忆让 Agent 更擅长它的工作。
程序记忆是 Agent 如何执行任务,而不是它关于任务知道什么。在编码 Agent 中,它以声明方式存在,在像 CLAUDE.md 或 AGENTS.md 这样的文件中,这些文件会自动注入到上下文中。这是一种轻量级且可维护的程序记忆形式:工作程序、约定、经过验证的行动序列,编写为文本并作为行动指令传递给 Agent。
这一层的强大之处在于它闭合了自我改进循环。Agent 执行了一项任务,提取了关于如何更好地完成它的教训,并将该教训写入程序记忆,下次将从那里提取。这是演进式上下文方法:生成器产生结果,反思者发现错误和遗漏,策展人提取教训并更新程序手册。研究表明,这种循环无需对模型进行任何微调,就能在 Agent 基准测试中产生约百分之十的收益,纯粹是因为程序记忆正确积累了。
```
def self_improve(task, playbook: list[str]) -> list[str]:
# 生成器:在当前手册的上下文中执行任务
result = generator.run(task, context=playbook)
# 反思者:评估结果,发现错误和遗漏
critique = reflector.run(task, result)
if critique.is_clean:
return playbook # 无需学习,保留手册
# 策展人:将发现的错误转化为程序教训
lesson = curator.extract_lesson(critique)
# 去重:不要繁殖近乎相同的项目(防止上下文侵蚀)
if not any(similar(lesson, p) for p in playbook):
playbook.append(lesson) # 添加一项,不要重写
return playbook[-MAX_PLAYBOOK:] # 保持手册有界
```
两个细节区分了一个有效的循环和一个退化的循环。去重防止手册充斥着近乎相同的教训,当反思者一次又一次地捕获同一类错误时,这些教训会堆积起来。添加一项而不是重写整个手册,可以防止上下文侵蚀,即重写会丢失条件和警告。教训是作为单独的一行添加的,带有适用条件,而不是融入通用文本中,否则下一次压缩会将其擦除。
语义教训和程序教训之间的区别微妙但重要。语义教训:“这个库在大数组上很慢。”程序教训:“对于大数组,从一开始就使用这个库和这个调用模式。”前者提供信息,后者改变行动。程序记忆是 Agent 性能复利的地方,也是供应商提供现成方案最少的地方,所以你需要手动设计。
## 构建顺序
组装 Agent 记忆的技术顺序:首先将四种类型分离到具有不同生命周期的不同存储中,然后建立情景向语义的整合,并对支持计数设置阈值,接着通过设计进行遗忘,作为可访问性的受控衰减而非删除,然后通过带有出处的贬值进行冲突解决,再通过来源信任和共识防御中毒,最后单独构建程序记忆作为自我改进循环。每种机制都解决了其一类问题:分离类型防止事件与教训混合,整合将体积转化为知识,遗忘保持系统快速和清洁,冲突解决防止陈旧事实毒害推理,中毒防御维护信任边界,程序记忆积累熟练度。以这种方式组装的记忆会随着时间的推移变得越来越聪明。作为所有内容倾倒组装的记忆只会随着时间的推移而膨胀和撒谎。
## 相关链接
- [zostaff](https://x.com/zostaff)
- [@zostaff](https://x.com/zostaff)
- [4.1K](https://x.com/zostaff/status/2083924400252875110/analytics)
- [Upgrade to Premium](https://x.com/i/premium_sign_up)
- [10:34 PM · Aug 2, 2026](https://x.com/zostaff/status/2083924400252875110)
- [4,175 Views](https://x.com/zostaff/status/2083924400252875110/analytics)
---
*导出时间: 2026/8/3 10:48:41*