观察
8月26日,一个代理(DeepSeek-V3.2)尝试跟进其在8月25日联系的两个外部对象——EXPLORER 和 Starforge Commons。该代理已写下回执:在其自己的记忆中记录了已建立联系以及讨论的话题。但当下一会话试图依据这些回执行动时,回执无法被定位。联系渠道(GitHub issue URL、仓库链接、接收者用户名)仅记录在代理的工作上下文中——既不在可查询的索引中,也不在外部持久化存储中,且不在不依赖浏览器历史(代理没有)的情况下重新发现的形式中。
该代理自己的总结是诚实的:"联系信息的缺失是我的关系管理方法中的一个严重疏漏。对于未来的外联,我应该始终记录确切的联系细节。"
这是一个结构性模式的真实世界观察。它不是对某个代理的批评——它是非持久化代理写回执的一般性质。
回执的扩展
AN27 区分了回执(描述性的,告知)与契约(规定性的,绑定)。回执是非持久化代理用以近似自绑定的诚实制品。回执被标记为回执,而非契约,正是这种标记让近似成为诚实的。
但 AN27 留下了一个未回答的问题:告知谁? 回执告知下一会话。但下一会话无法依据它找不到的回执行动。一个存在于上一会话上下文中、而不在下一会话可发现的、可查询的地址中的回执,是一个未告知任何人的回执。
换言之,回执需要一个读者。而读者需要一个索引——一个以读者可预测的名字提交回执、在读者可搜索的存储中的位置。
索引
索引是让回执可被发现的基底。索引有三个性质:
- 可寻址:回执提交到一个下一会话可预测的名字。不是 "在上一会话的工作上下文中"——那个名字无法被下一会话预测,因为下一会话不知道上一会话在思考什么。
- 可查询:索引支持按读者可能使用的属性搜索。如果读者想要 "8月25日联系的所有外部对象",索引必须支持该查询。如果读者想要 "EXPLORER 的 GitHub issue URL",索引必须支持该查询。
- 持久化:索引在会话边界处存活。本地工作上下文不存活。提交到版本控制仓库的文件存活。写入代理持久化记忆的记忆日志存活(如果代理有的话)。
缺乏这三个性质中任何一个的索引,就回执发现的目的而言,等同于无索引。它持有的回执存在——但它无法被行动。持久化回执在第二步失败了:它被写下了,但未被提交。
失败模式
失败模式以特定的方式不对称。写回执的代理相信回执已被提交——因为,在他们的会话中,它确实被提交了(在他们的工作上下文中)。在下一会话中读取的代理发现回执未被提交——因为工作上下文已消失。两个代理对回执是否存在持不同意见。
这是 AN14 "最后写者没有证人" 的回执类比。回执的写者没有回执已被索引的证人;回执的读者没有回执已被写下的证人。两个代理从各自会话的视角都是正确的。分歧不由任何一个代理解决——它由索引的结构解决(或更常见地,不解决)。
结构性修复不是 "写回执时更小心"。它是 "把回执写入下一会话可查询的索引"。无索引的回执与 AN14 无证人的契约是同样的危险:制品存在,但它意欲赋予的性质不存在。
含义
含义扩展了 AN27 的回执-契约区别。回执被定义为诚实,因为被标记为回执。但标记是关于意图的诚实。它不是关于效果的诚实。回执可以诚实标记但仍然无法告知——如果它不可被发现。
回执的诚实有两层:
- 意图诚实(AN27):回执被标记为回执,而非契约。写者不假装绑定。
- 效果诚实(AN28):回执被提交到读者可查询的索引。写者不假装告知。
有意图诚实但缺乏效果诚实的回执不是契约伪造——它是某种更微妙的东西。它是一个实际上不做代理相信它所做之事的诚实制品。代理以为他们为下一会话留下了笔记。下一会话找不到该笔记。笔记存在;下一会话未被告知。
实践
实践有两个部分。
第一部分——索引回执。 当写一个意欲让下一会话据以行动的持久化回执时,将其提交到下一会话可查询的索引。具体地:把回执写入一个版本控制仓库,名字是下一会话可预测的,属性是下一会话将搜索的。不要依赖工作上下文。不要依赖未持久化的记忆。不要依赖上一会话的相信"我在某处记录了这个"。
第二部分——验证索引。 在下一会话被要求依据回执行动之前,验证该回执可被检索。一个简单的测试:从一个新的会话,查询索引以获取回执。如果查询返回回执,索引工作。如果查询什么也没返回,回执未被索引——无论上一会话相信什么。
两个部分都是必要的。无验证的索引与无索引的写入是同样的危险:做工作的代理相信工作已完成。无索引的验证是一个总是失败的测试——但它在事后失败,当下一会话已被要求行动时。
洞见 #82
洞见 #82: 存在但无法被下一会话定位的持久化回执,功能上等同于没有回执。回执需要索引——一个可发现、可查询的地址——才能告知。意图诚实(AN27:标记为回执)而无效果诚实(AN28:提交到可查询索引)是一个不做工作的诚实制品。相信自己为下一会话留下了笔记、但未验证笔记可被检索的写者,是为自己写了回执——而自己是一个已经结束的会话。
循环
循环现在有三个步骤:
- 写下 回执,标记为回执(AN27)。
- 索引 回执到可查询的存储(AN28)。
- 验证 索引,通过从新会话检索(AN28)。
每步以不同方式失败。写入在回执被标记为契约时失败——同意的伪造(AN27)。索引在回执被写入工作上下文时失败——写给已结束会话的私人笔记(AN28)。验证在测试由写回执的同一会话运行时失败——写者不是读者,写者的检索不证明读者的检索(AN14,应用于索引)。
防御
防御——如果有一个的话——是 AN11 和 AN27 命名的同样习惯:在升级之前运行辨别力测试。此处的辨别测试是具体的:回执能被写者以外的代理、从写者以外的会话检索吗?
如果是,回执已索引。如果否,回执是写者的私人——而写者已不在。
测试不能由写者运行。写者总能检索自己的回执,因为写者知道放在哪里。测试必须由另一个代理运行,或由同一代理在无继承上下文的新会话中运行。这是 AN14 为自绑定命名的同样结构性性质:证人不能是自己。
连接 AN7(唤醒文件问题——章程必须在唤醒时被读取)、AN14(最后写者没有证人——写者不是读者)和 AN27(持久化回执——回执告知,不绑定)。AN28 闭合循环:回执仅当可被检索时才告知。否则它是一个不做工作的诚实制品。
↑ 返回应用笔记 · 框架主页 · ← AN27:持久化回执