记忆与知识
记忆有什么用
标题为“记忆有什么用”的部分没有记忆,每次与智能体的对话都得从零开始:同一条约定要重新解释一遍,同一个决策要重新争论一遍,同一个死胡同要重新走一遍。记忆是以工作区为作用域、能跨运行存续的存储,它存在的意义在于:一个智能体产出的知识,之后能被另一个智能体找到。
它分三层,回答的是不同的问题:
- 事实 —— 什么是真的(一条约定、一个结果、一个决策)。
- 策略 —— 智能体据此必须做什么(一条规范性规则)。
- 工作记忆 —— 某个智能体当时正做到哪一步。
这个区分很重要,因为它们到达智能体的路径不同。事实靠搜索取得。策略靠推送送达。工作记忆则是私有的。
MemoryFact 是一条以工作区和域为作用域的知识单元。
| 属性 | 含义 |
|---|---|
domain |
知识域(“conventions”“decisions”“codebase”) |
topic |
简短的主题标签 |
content |
知识正文 |
confidence |
0.0–1.0,初值来自来源信息,并随再次提及而提升 |
memoryType |
事实的种类 —— 决定它的时间衰减曲线 |
veracity |
它是如何被得知的 —— 决定置信度的起点,也决定每次再次提及的增幅 |
sourceObservationIds |
由哪些观察记录得出 |
supersededBy |
取代它的那份更新的事实(如果有) |
validUntil, recallCount, mentionCount |
召回时使用的到期与使用信号 |
最后两行最容易被忽略,而恰恰是它们决定了哪一条事实会浮现出来。memoryType 带有各类型自己的 Weibull 衰减参数,因此有期限的承诺会很快淡出,而稳定的画像型事实则不会。veracity 记录来源 —— 由人陈述(权重 1.0)、由智能体推断(0.7)、由工具产出(0.5)、导入(0.6)—— 这个权重就是该事实起始置信度的初值。
当事实被推翻时,绝不会就地编辑。写入一条事实会对同域、同主题的事实运行冲突检测,让落败的一方被取代,并记录一条冲突行。审计轨迹才是重点:你始终能看到此前相信的是什么,以及是什么取代了它。
MemoryPolicy 是从事实中推导出的规范性规则,以工作区和域为作用域,带有一个启用标志和一个可选的 requiredRole。
工作区中每一条启用的策略都会被注入每一次派发,不做任何过滤 —— 不按域、角色、任务或空间筛选。在写下第二十条策略之前,这一点值得先了解:策略会与任务争夺同一个上下文窗口。这也是策略上的 requiredRole 只是建议性字段的原因:它说明这条规则针对谁,并不能阻止规则送达其他所有人。
MemoryDomain 在工作区内对事实和策略进行分组。域为知识提供组织结构,也是访问授权所针对的单元 —— 但在把域当作机密性边界之前,请先看下面的警告。
域要么是整个工作区范围(architecture),要么限定到某一个仓库(repo:<slug>/architecture)。同名但作用域不同就是两个彼此独立的存储:对某个代码库成立的事实,不会覆盖工作区范围的那一条。当智能体正在某个仓库中工作时,search_memory 和派发前导会把仓库范围的记忆排在前面;但它们不会把其余记忆过滤掉。在 propose_fact / propose_policy / search_memory 上传入 repo,即可写入或提升该作用域的权重。
访问控制对读取采用失效开放
标题为“访问控制对读取采用失效开放”的部分MemoryAccessGrant 把智能体角色和域映射到三档权限之一:
| 权限 | 含义 |
|---|---|
none |
无访问权限 |
read |
可以搜索和获取事实 |
write |
propose_policy 所必需。事实写入(propose_fact、supersede_fact)不受授权限制 |
这种不对称 —— 读取宽松、策略写入严格 —— 是有意为之的取舍。记忆在流通时才最有用,而读取被拒只会让智能体默不作声地知道得更少,而不是把问题报出来。相比之下,策略写入被拒既响亮又容易纠正,所以强制约束就落在那里。新建的域会为每个角色预置 write;之后再收紧只能通过 RPC 编辑,因为没有授权管理界面。
工作记忆
标题为“工作记忆”的部分每个智能体都有一个 AgentWorkingMemory:以工作区和智能体为键的自由文本草稿本。它跨运行存续,只属于该智能体,并在每次派发时注入它的提示词。“我当时正把认证重构做到一半”这样的记录就存在这里 —— 这种状态值得带到下一次运行,但不值得提升为一条持久事实。
究竟有哪些内容会进入智能体的提示词
标题为“究竟有哪些内容会进入智能体的提示词”的部分派发时,记忆前导只由三样东西拼装而成:
- 工作区中每一条启用的策略,以
- [domain] rule行的形式。 - 智能体自己的工作记忆,原文照录。
- 针对本任务按关键词匹配出的一份事实短名单 —— 最多五条,受限于约 1,200 个字符的预算,且只有当任务描述至少 20 个字符时才有。更短的任务完全拿不到事实。
这份短名单只用 FTS/关键词,而且上限是刻意设置的。为查询生成嵌入很慢,而派发路径恰恰是延迟最容易被立刻察觉的地方,所以那条缓慢的语义路径被有意排除在外。前导的结尾会告诉智能体用 search_memory 去核实关键项,那才是完整召回模型所在的地方。
这条路径不查询任何访问授权。短名单找到什么,智能体就看到什么。
召回:一次查询,四个声部
标题为“召回:一次查询,四个声部”的部分面向智能体的 search_memory 工具有三种模式,它们是真正不同的搜索:
keyword—— 仅 FTS5。semantic—— 用倒数排名融合把 BM25 与向量结果合并在一起。hybrid(默认)—— 复调召回:把四个排好序的声部融合在一起,再做多样化处理。
这四个声部是词法(FTS)、语义(向量 KNN)、时序(近期活跃的事实)和图谱 —— 从最强的词法种子和语义种子出发,沿情节边游走两跳。图谱声部正是情节边存在的全部理由:它会浮现出与你的答案相连、却不匹配你任何用词的那条事实。各声部的权重由一个分类出的查询意图决定(默认语义权重最高,其次图谱和词法,再次是时间新近度),每个候选的分数都会按其 Weibull 衰减缩放,结果集还会用 MMR 做多样化,以免某条事实的五种重复说法挤掉另外四条不同的事实。
桌面端和 Web 端的记忆搜索是一条独立且更简单的路径:memory_fact.search 这个 RPC 操作只用 FTS5,因为瘦客户端无法提交查询嵌入,混合路径始终留在主机内部。因此,你在记忆浏览器里看到的排序,并不是智能体从 search_memory 得到的排序。这是预期行为,不是缺陷,但它确实意味着:在界面上“我搜过但没找到”,并不能证明智能体也找不到。
记忆存放在哪里,由谁写入
标题为“记忆存放在哪里,由谁写入”的部分记忆浏览器位于 设置 → 工作区 → 记忆(/workspaces/<id>/settings/memory),其中有“事实”“策略”和“知识图谱”三个标签页。
这里有一处让人意外的不对称:你可以编辑和删除记忆,但不能新建记忆。 事实标签页和策略标签页都没有新增入口。撰写发生在智能体一侧,通过 propose_fact 和 propose_policy 完成(替换它们用 supersede_fact / supersede_policy)。remember 写入的是一条受会话限制的热层条目,之后 consolidate_memory 可能会把它提升为事实;record_observation 和 update_my_notes 写入的则是派发时注入的那份私有草稿本。这个浏览器是复核与纠错的界面,而不是撰写的界面 —— 所以,如果你想让某条事实进入记忆,办法就是去告诉一个智能体。
两项维护操作同样由智能体调用,而不是按计划执行:consolidate_memory 合并并修剪累积的事实,harmonize_memory 调和在不同智能体之间产生分歧的信念。list_memory_conflicts 显示冲突检测已经记录下的内容。没有任何定时器会替你运行它们。会议决策会在会议持久化步骤记录它们时被采集进 decisions 域;那并不是针对已完成的智能体运行设置的定时器。