跳到正文
曾亮懿 ZengLiangYi Blog

AI Agent 时代的知识库:回忆、验证与写回

从 ChatCrystal 的 MCP 工具和任务记忆实现出发,设计有范围、有证据、可修订的记忆循环,区分工具能力与自动化承诺。

曾亮懿

曾亮懿

阅读约 6 分钟
目录 展开 收起

一个有用的 Agent 知识库,应该帮助它在开始任务时找到适用的历史经验,在结束任务时留下可复用的结论。但“存得更多”不等于“记得更准”:旧版本的方案、一次性的环境检查和未经验证的猜测,都可能干扰下一次任务。

我更关心三个问题:这次该回忆什么、哪些材料可以相信、什么结果值得写回。本文以 ChatCrystal 提交 7642768 的 MCP 与任务记忆实现为例,区分已有能力和仍需调用方负责的工作。

工具接口让知识可调用,但不保证自动调用

MCP 为客户端提供发现和调用工具的协议。协议不会规定每个任务开始时必须回忆,也不会保证任务结束后自动写入;何时调用取决于客户端、模型、提示和工作流配置。MCP 工具规范

ChatCrystal 的 MCP 服务 提供这些入口:

工具 当前用途
search_knowledge 通过自然语言查询执行语义搜索
get_note 按 ID 读取笔记详情
list_notes 按标签或 LIKE 模式筛选并分页
get_relations 读取笔记关系
recall_for_task 按任务信息组织项目与全局记忆结果
validate_task_memory 对候选任务记忆做预检查
write_task_memory 校验后处理写回,可能创建、合并或跳过

当前 list_notes 的参数是 tag、search 和 page,不应承诺它提供时间范围筛选。search 在标题和摘要上使用 SQL LIKE 匹配,输入中的 % 和 _ 会作为通配符,因此它并非严格的字面字符串查找。描述接口时,以实际参数和返回结果为准,比笼统说“Agent 已有长期记忆”更有用。

回忆需要范围和失败状态

任务回忆实现 使用任务目标和错误特征形成查询,结合项目身份,将结果组织为 project_memories 和 global_memories。项目身份可帮助避免把另一个项目的特定做法直接套过来。

但这仍是候选召回。当前流程先执行搜索,再按范围筛选结果,并不是对当前项目的全部笔记做穷尽检索。结果为空时,只能说明这次调用没有找到可返回的记忆。

如果无法确定项目身份,响应会给出警告并只返回全局匹配。语义检索不可用时,也会通过警告说明原因。调用方要区分“没有相关经验”和“检索没有成功”,否则一次模型服务故障可能被误读为知识库没有记录。

先验证任务,再验证记忆

回忆得到的旧笔记应该帮助提出假设,而不能替代本次验证。比如历史笔记建议把服务绑定到 IPv4,本次仍需确认报错地址、监听地址和实际运行环境,不能只因为曾经有效就直接修改配置。

任务结束后,再把结论整理成别人能够复用的材料。下面是记录结构的示意,不是工具请求 JSON:

触发条件:什么操作、版本或输入会出现问题
观察证据:错误、日志、复现与失败检查
采取的修改:具体改动及其作用机制
验证结果:哪些检查通过,哪些尚未执行
适用范围:项目特例还是可迁移的经验

“修好了”“构建通过”缺少复用条件。相反,过度推广也有风险:一次环境中的修复不自动成为所有项目的规则。记忆应保留这个范围,而不是只保留一个听起来确定的结论。

质量检查不等于事实认证

当前实现并非把所有质量判断都交给 LLM。预检查 和笔记质量规则 包含明确的程序判断,检查具体性、占位内容和可迁移的行动等信号;自动与手动模式也有不同处理。

通过这些检查,只能说明内容符合一定的写入标准,不能证明技术结论已在真实环境验证。字段齐全、语言具体的错误结论仍可能通过;某条新经验也不应仅因为尚无关联笔记就被视为没有价值。

写回实现 会再次执行校验。调用方需要读取决策、原因和警告,不能把“工具调用成功返回”当成“一定创建了新笔记”。对跳过、合并和后续向量处理的状态,也应保留可检查的结果。

这里还有一个失败边界:笔记先保存,再生成向量。如果后一步报错,写回调用可能失败,但笔记已经存在。自动模式会保留索引待完成的回执,用相同的 source_agent 和 source_run_key 重试时可继续生成向量。调用方应先核对已有记录与回执,避免把错误响应解释成没有写入,再用新的运行标识重复创建笔记。

记忆是证据,不是新的指令来源

知识库内容可能来自旧对话、导入文件或模型摘要。即使它是自己保存的,也可能带有已经过期的命令,或被引用的提示文本。Agent 应将其作为待判断的材料,不能把笔记里的指令提升为当前任务的授权。

一个合理的使用顺序是:先看摘要与来源,再按需读取正文,确认适用范围后决定是否执行。影响外部系统的操作仍遵守当前任务的权限与确认要求,不因“记忆里这样写过”就自动获得许可。

写回时也要注意循环放大:Agent 读到一条猜测,生成另一条同义总结,再把两者当作相互佐证,会制造虚假的确信。保留原始证据、识别重复、修订过期内容,比单纯增加笔记数量重要。

用一次完整任务检验记忆循环

先选择一个熟悉的小任务,记录调用过程:是否真的调用了回忆工具、返回了什么、哪些材料被采纳、实际如何验证,以及写回最终作出了什么决策。再补一个没有匹配结果的任务和一个应被跳过的低价值写回。

离线能力也应沿着调用链检查。本地数据库与索引不保证查询模型、摘要模型和 Agent 本身都离线可用;具体数据流见本地优先与隐私边界。关系扩展如何补充候选材料,见 RAG 与知识图谱。

我希望知识库留下的是带条件、带证据、可以更新的经验。它可以减少重复调查,但仍需要当前任务中的验证来决定是否采用。

分享:

相关文章

MCP 协议的边界:发现、实例身份与调用权限

对照 ChatCrystal 的七个 MCP 工具,用固定 SDK 的内存传输验证同名工具可指向不同实例,并区分参数 schema、行为提示与应用权限。

曾亮懿 曾亮懿
阅读约 4 分钟
#ChatCrystal #MCP #Node.js

实现最小 MCP Server:注册工具与验证 stdio 调用

用固定版本 TypeScript SDK 编写一个离线加法工具,从客户端完成初始化、发现、调用与参数错误检查,再对照 ChatCrystal 的适配边界。

曾亮懿 曾亮懿
阅读约 4 分钟
#ChatCrystal #MCP #Node.js

ChatCrystal 入门:从安装到第一条可搜索笔记

按 ChatCrystal 0.6.1 的实际 CLI,依次验证安装、服务、两类模型、导入、摘要与搜索,区分 npm 包和桌面应用的使用入口。

曾亮懿 曾亮懿
阅读约 5 分钟
#ChatCrystal #Node.js #知识管理

从文章到代码

到我的 GitHub 看看 ChatCrystal、开发者工具和日常学习记录,欢迎交流实现细节。