跳转到内容

记忆与知识

没有记忆,每次与智能体的对话都得从零开始:同一条约定要重新解释一遍,同一个决策要重新争论一遍,同一个死胡同要重新走一遍。记忆是以工作区为作用域、能跨运行存续的存储,它存在的意义在于:一个智能体产出的知识,之后能被另一个智能体找到。

它分三层,回答的是不同的问题:

  1. 事实 —— 什么是真的(一条约定、一个结果、一个决策)。
  2. 策略 —— 智能体据此必须做什么(一条规范性规则)。
  3. 工作记忆 —— 某个智能体当时正做到哪一步。

这个区分很重要,因为它们到达智能体的路径不同。事实靠搜索取得。策略靠推送送达。工作记忆则是私有的。

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 域;那并不是针对已完成的智能体运行设置的定时器。