claude-mem Knowledge Agent 实战:把历史观察编译成可对话的专属"记忆大脑"
claude-mem 的 Knowledge Agent 是一个将大量历史观察(observations)编译成可查询的知识语料库、并加载进一个带上下文的 AI 会话进行对话式问答的能力模块。它的典型应用场景是:当你想围绕"hooks 生命周期""worker 服务的全部 bugfix""过去一个月的所有决策"这类主题提炼规律、做总结、回答跨记录的综合问题时,用它替代逐条翻看原始搜索记录。读完本文,你将掌握从语料构建(build)、加载(prime)到提问(query)的完整工作流,了解每个过滤参数的含义,并借助源码理解其内部实现机制。
Knowledge Agent 是什么
Knowledge Agent 本质上是从观察历史中筛选出的一段"语料"(corpus)被整体加载进一个 AI 会话后形成的自定义"大脑"。它的核心心智模型是一条流水线:
观察历史 → 筛选(语料) → 加载(会话) → 问答
对应到实操就是三个动作:
- 构建语料:从观察历史中按条件筛选出记录集合,保存为语料文件;
- 加载语料(prime):把整份语料写入一个 AI 会话的上下文窗口;
- 提问(query):以自然语言向这个会话提问,得到基于语料的、综合提炼后的答案。
你可以把语料想象成三种典型形态——"关于 hooks 的一切"、"最近一个月的所有决策"、"worker 服务的全部 bugfix"。每条语料都像为一个特定主题定制的私人记忆库。
需要特别注意的是,Knowledge Agent 返回的不是原始检索记录,而是综合后的对话式回答。这与 mem-search 的"返回原始记录"形成互补(详见文末对比)。
完整工作流:Build → Prime → Query
关联技能文档 plugin/skills/knowledge-agent/SKILL.md 定义的四步流程如下。
Step 1:构建语料(Build a corpus)
build_corpus name="hooks-expertise" description="Everything about the hooks lifecycle" project="claude-mem" concepts="hooks" limit=500
此命令会搜索观察历史、收集匹配记录并写入语料文件。支持的过滤选项如下:
| 参数 | 含义 | 说明 |
|---|---|---|
project |
按项目名过滤 | 只收录指定项目的观察 |
types |
观察类型,逗号分隔 | 可选:decision、bugfix、feature、refactor、discovery、change |
concepts |
概念标签,逗号分隔 | 按打标的概念过滤 |
files |
文件路径,逗号分隔 | 前缀匹配读取/修改过的文件 |
query |
语义搜索查询 | 全文搜索式过滤 |
dateStart / dateEnd |
ISO 日期范围 | 限定时间窗 |
limit |
最大观察条数 | 默认 500,文档示例多用 200 |
Step 2:加载语料(Prime the corpus)
prime_corpus name="hooks-expertise"
这一步会创建一个 AI 会话,将整份语料写入其上下文窗口,即"加载记忆"。大语料加载需要一定时间。加载完成后返回的 session_id 就是这个 Knowledge Agent——一个内置了你项目历史的 Claude 会话。
Step 3:提问(Query)
query_corpus name="hooks-expertise" question="What are the 5 lifecycle hooks and when does each fire?"
Knowledge Agent 会基于自己的语料作答。后续追问会自然保持上下文(每次追问都叠加在前面的对话之上),例如:
query_corpus name="hooks-expertise" question="Which hook handles context injection?"
Step 4:查看语料列表(List corpora)
list_corpora
展示所有已建语料,含统计数据与加载(priming)状态。
从筛选到落盘:CorpusBuilder 如何构建语料
理解底层实现有助于用好过滤参数。语料构建的核心类是 CorpusBuilder(源码见 src/services/worker/knowledge/CorpusBuilder.ts),构建流程是一条清晰的调用链:
- 搜索:把项目名、类型、概念、文件、查询词、日期与条数上限拼装成
SearchOrchestrator.search(searchArgs)的检索参数,取出匹配观察的 ID 列表; - 回填(hydrate):通过
sessionStore.getObservationsByIds(observationIds, ...)取回完整记录,解析出结构化字段(facts、concepts、files_read、files_modified等),并把 JSON 字符串字段安全解析为数组(见safeParseJsonArray); - 统计:
calculateStats汇总观察条数、类型分布type_breakdown、时间跨度date_range(取最早/最晚created_at_epoch); - 渲染与落盘:
CorpusRenderer生成系统提示词system_prompt、将语料渲染为完整文本并估算 token(token_estimate),最终由CorpusStore.write写入语料文件。
从源码可见两个值得注意的细节:
- 观察条数是"软上限":搜索先按
limit拿 ID 列表,回填时还会再次携带orderBy: 'date_asc'与limit等选项,因此最终入库条数以实际搜索命中为准。 - 文件存储位置固定:语料以 JSON 落盘为
~/.claude-mem/corpora/<name>.corpus.json(目录常量来自 src/shared/paths.ts 的paths.corpora())。
语料文件的字段结构
CorpusFile(见 src/services/worker/knowledge/types.ts)约定了语料文件的完整结构:
| 字段 | 含义 |
|---|---|
version |
文件版本(当前为 1) |
name / description |
语料名与描述 |
created_at / updated_at |
创建/更新时间戳 |
filter |
构建时使用的过滤条件(重建时复用) |
stats |
统计信息(条数、token 估算、时间范围、类型分布) |
system_prompt |
渲染生成的系统提示词 |
session_id |
加载后的会话 ID(未加载为 null) |
observations |
观察记录本体(每条含类型、标题、叙述、facts、概念、读写文件等) |
语料命名的约束
语料名不是随意字符串。CorpusStore 中定义了命名正则 CORPUS_NAME_PATTERN = /^[a-zA-Z0-9._-]+$/(见 src/services/worker/knowledge/CorpusStore.ts),只允许字母数字、点、连字符与下划线;含空格等非法字符会直接返回 400 INVALID_CORPUS_NAME 错误,而非静默截断——注释里特别强调"不要先 trim 再校验,否则 " bad " 会被悄悄归一化后放行"。同时 getFilePath 还会做路径穿越防护,确保解析后的路径始终位于 corpora 目录内。
Prime 的底层原理:为什么语料能"常驻上下文"
加载(prime)看似只是"把语料塞进会话",但能长期稳定问答的关键在于 Agent SDK 的 resume 机制。从 src/services/worker/knowledge/KnowledgeAgent.ts 可看到其实现思路:
Prime 阶段(prime()):将语料渲染为完整文本,与 system_prompt 拼接成初始提示,其中固定追加一段"请确认你收到了哪些内容,并总结你能回答的主题"的引导语。随后通过 query() 启动一次 Claude Agent SDK 会话,从返回流中捕获 session_id 写回语料文件。
Query 阶段(query() / executeQuery()):每一次提问其实都是对同一条会话的 resume(resume: corpus.session_id),因此整份语料始终停留在该会话的上下文里——无需每次重新上传语料,也不需要任何"提示词缓存技巧"。1M token 的上下文窗口让这种方案成立:按每条约 300 token 估算,2000 条观察可以轻松容纳。
关键代码路径上还有一层失败兜底:
- 若会话已过期或
resume失败(isSessionResumeError通过/session|resume|expired|invalid.*session|not found/i匹配错误信息),query()会自动prime()重新加载语料并重试一次,对上层完全透明; - 若 SDK 子进程在产出答案后才退出,只要
session_id或答案已经捕获,就视为成功继续; - 空语料(0 条观察)是合法状态,只是内容为空。
模型选择也并非硬编码:getModelId() 从用户设置读取 CLAUDE_MEM_MODEL,并通过 resolveTierAlias 解析 $TIER:<fast|smart|simple|summary> 这类别名,确保加载与问答始终使用用户配置的模型。
HTTP API 与 MCP 工具的对应关系
SKILL.md 中的命令背后是 MCP 工具与 worker HTTP API 两层通道。工具定义与参数描述在 src/servers/mcp-server.ts(build_corpus、list_corpora、prime_corpus、query_corpus、rebuild_corpus、reprime_corpus 六个工具均通过 callWorker() 转发到 worker);路由实现集中在 src/services/worker/http/routes/CorpusRoutes.ts,共 8 个端点:
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/corpus |
按过滤条件构建新语料 |
| GET | /api/corpus |
列出全部语料及统计 |
| GET | /api/corpus/:name |
获取语料元数据 |
| DELETE | /api/corpus/:name |
删除语料 |
| POST | /api/corpus/:name/rebuild |
用存储的过滤条件重建语料 |
| POST | /api/corpus/:name/prime |
创建加载语料的 AI 会话 |
| POST | /api/corpus/:name/query |
向 Knowledge Agent 提问 |
| POST | /api/corpus/:name/reprime |
开启全新会话(清空此前问答上下文) |
MCP 工具名与 HTTP 端点一一对应:工具调用的参数在路由层先经 Zod schema 校验(见 buildCorpusSchema),其中 types 会被白名单校验(decision, bugfix, feature, refactor, discovery, change 及若干安全相关类型),name 做正则校验,limit 必须是正整数;而 stringArrayLike 预处理允许调用方用 ["decision","discovery"] 数组或 "decision,discovery" 逗号分隔字符串两种形式传参。
如果你需要绕过 MCP 直接以 HTTP 方式驱动,可以先取 worker 端口再调用(以下为官方文档 docs/public/usage/knowledge-agents.mdx 给出的 curl 示例):
WORKER_PORT=$(jq -r .CLAUDE_MEM_WORKER_PORT ~/.claude-mem/settings.json)
# 构建语料
curl -X POST http://127.0.0.1:$WORKER_PORT/api/corpus \
-H "Content-Type: application/json" \
-d '{
"name": "hooks-expertise",
"query": "hooks architecture",
"project": "claude-mem",
"types": ["decision", "discovery"],
"limit": 200
}'
# 加载语料(返回 session_id)
curl -X POST http://127.0.0.1:$WORKER_PORT/api/corpus/hooks-expertise/prime
# 提问
curl -X POST http://127.0.0.1:$WORKER_PORT/api/corpus/hooks-expertise/query \
-H "Content-Type: application/json" \
-d '{ "question": "What are the 5 lifecycle hooks?" }'
保持语料新鲜:Rebuild 与 Reprime
观察是持续新增的,语料却是构建时刻的快照。当项目产生了新的观察后,需要两步刷新:
- 重建语料(Rebuild)——重跑最初存储的过滤条件(
CorpusBuilder.build复用了existingCorpus.filter,见handleRebuildCorpus),把新观察拉进来:
rebuild_corpus name="hooks-expertise"
- 重新加载(Reprime)——重建后需要加载进一个全新会话(旧会话里仍是旧内容):
reprime_corpus name="hooks-expertise"
如果对话跑偏,或想在同一份语料上换一个毫不相干的话题,也可以直接用 reprime_corpus 开新会话。实现上 reprime() 只是把 session_id 置空再重新 prime()(见 KnowledgeAgent.reprime),handleReprimeCorpus 返回新 session_id。重建只刷新数据、不会自动重载会话;重新加载只开新会话、不会拉新数据——这两者要按需配合使用。
使用技巧与注意事项
根据官方技能文档与实现细节,实践中最有效的几个原则:
- 聚焦的语料效果最好:
"hooks architecture"胜过"everything ever";语料越聚焦,回答越贴合主题,也越节省上下文空间; - 一次加载,多次提问:会话在多次查询间持续存在,不必反复 prime;
- 跑偏就 reprime:对话漂移或需要无偏提问时,重载即获得干净上下文;
- 有新观察就 rebuild + reprime:保持语料与最新历史同步;
- 数据新鲜度是快照语义:语料在构建时刻固化,需要与 mem-search 的"实时查询数据库"区分。
什么时候用 Knowledge Agent,什么时候用 mem-search
| 维度 | mem-search | Knowledge Agent |
|---|---|---|
| 返回内容 | 原始观察记录 | 综合后的对话式答案 |
| 适用场景 | 查找特定观察、ID、时间线 | 追问规律、决策、架构层面的问题 |
| Token 模型 | 按次付费(三层渐进披露) | 加载时一次付费,追问成本低 |
| 交互方式 | 搜索、过滤、拉取 | 自然语言提问 |
| 数据新鲜度 | 始终最新(实时查库) | 构建时快照(重建才刷新) |
| 前置步骤 | 无,即开即用 | 首次查询前需 build + prime |
一句话经验法则:要找某个具体的东西用 mem-search,想从整体上理解某个主题用 Knowledge Agent。
已知的边界情况
- 会话过期时,
query会自动从语料文件重新 prime 并重试; - Claude 进程在产出全部消息后退出,只要
session_id或答案已被捕获,即视为成功; - 0 条观察的空语料合法存在,只是没有内容可答;
- 语料名非法(含空白/斜杠/非 ASCII)会得到明确的 400 错误而非静默修复。
延伸阅读
若想深入这套机制的上层设计,可继续在仓库中探索:语料渲染与 token 估算在 CorpusRenderer(位于 src/services/worker/knowledge/),构建输入校验与路由编排见 src/services/worker/http/routes/CorpusRoutes.ts,完整的架构图与 FAQ 记录于官方使用文档 docs/public/usage/knowledge-agents.mdx,相关测试覆盖见 tests/worker/http/routes/corpus-routes-coercion.test.ts 与 tests/worker/knowledge/corpus-store-name-validation.test.ts。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00