首页
/ claude-mem Knowledge Agent 实战:把历史观察编译成可对话的专属"记忆大脑"

claude-mem Knowledge Agent 实战:把历史观察编译成可对话的专属"记忆大脑"

2026-09-06 18:25:40作者:侯霆垣

claude-mem 的 Knowledge Agent 是一个将大量历史观察(observations)编译成可查询的知识语料库、并加载进一个带上下文的 AI 会话进行对话式问答的能力模块。它的典型应用场景是:当你想围绕"hooks 生命周期""worker 服务的全部 bugfix""过去一个月的所有决策"这类主题提炼规律、做总结、回答跨记录的综合问题时,用它替代逐条翻看原始搜索记录。读完本文,你将掌握从语料构建(build)、加载(prime)到提问(query)的完整工作流,了解每个过滤参数的含义,并借助源码理解其内部实现机制。

Knowledge Agent 是什么

Knowledge Agent 本质上是从观察历史中筛选出的一段"语料"(corpus)被整体加载进一个 AI 会话后形成的自定义"大脑"。它的核心心智模型是一条流水线:

观察历史 → 筛选(语料) → 加载(会话) → 问答

对应到实操就是三个动作:

  1. 构建语料:从观察历史中按条件筛选出记录集合,保存为语料文件;
  2. 加载语料(prime):把整份语料写入一个 AI 会话的上下文窗口;
  3. 提问(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 观察类型,逗号分隔 可选:decisionbugfixfeaturerefactordiscoverychange
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),构建流程是一条清晰的调用链:

  1. 搜索:把项目名、类型、概念、文件、查询词、日期与条数上限拼装成 SearchOrchestrator.search(searchArgs) 的检索参数,取出匹配观察的 ID 列表;
  2. 回填(hydrate):通过 sessionStore.getObservationsByIds(observationIds, ...) 取回完整记录,解析出结构化字段(factsconceptsfiles_readfiles_modified 等),并把 JSON 字符串字段安全解析为数组(见 safeParseJsonArray);
  3. 统计calculateStats 汇总观察条数、类型分布 type_breakdown、时间跨度 date_range(取最早/最晚 created_at_epoch);
  4. 渲染与落盘CorpusRenderer 生成系统提示词 system_prompt、将语料渲染为完整文本并估算 token(token_estimate),最终由 CorpusStore.write 写入语料文件。

从源码可见两个值得注意的细节:

  • 观察条数是"软上限":搜索先按 limit 拿 ID 列表,回填时还会再次携带 orderBy: 'date_asc'limit 等选项,因此最终入库条数以实际搜索命中为准。
  • 文件存储位置固定:语料以 JSON 落盘为 ~/.claude-mem/corpora/<name>.corpus.json(目录常量来自 src/shared/paths.tspaths.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()):每一次提问其实都是对同一条会话的 resumeresume: 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.tsbuild_corpuslist_corporaprime_corpusquery_corpusrebuild_corpusreprime_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

观察是持续新增的,语料却是构建时刻的快照。当项目产生了新的观察后,需要两步刷新:

  1. 重建语料(Rebuild)——重跑最初存储的过滤条件(CorpusBuilder.build 复用了 existingCorpus.filter,见 handleRebuildCorpus),把新观察拉进来:
rebuild_corpus name="hooks-expertise"
  1. 重新加载(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.tstests/worker/knowledge/corpus-store-name-validation.test.ts

登录后查看全文
热门项目推荐
相关项目推荐