
OpenHuman Archivist 后台知识馆员会话归档、经验提炼与 MEMORY.md 记忆沉淀机制全解析【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhumanOpenHuman 的Archivist知识馆员是一个在会话结束后于后台运行的专用 Agent负责把每一轮对话沉淀为可检索的记忆资产回合索引写入 FTS5 情景记忆表、经验教训抽取与分类、知识库文件 MEMORY.md 增量更新。本文以 Archivist 的系统提示词prompt.md为骨架结合其 Agent 配置agent.toml、提示词装配器prompt.rs以及后端 Hook 实现hook_impl.rs、lifecycle.rs深入剖析 OpenHuman 的「会话 → 记忆」流水线帮助你理解其记忆系统如何做到低开销、可检索、防泄露、不重复。一、Archivist 是谁后台知识馆员的角色定位在 OpenHuman 的 Agent 注册表中Archivist 被定义为一个典型的「后台 轻量」Agent。它的when_to_use字段一句话点明使命Background librarian — extracts lessons from a completed session, updates MEMORY.md, and indexes to FTS5. Runs cheap and slow.后台知识馆员——从已完成的会话中提取经验更新 MEMORY.md并索引到 FTS5。以低成本、低速度运行。这段描述见 agent.toml揭示了三个关键设计意图后台触发background true不占用前台交互路径低成本temperature 0.4低随机性、输出稳定、max_iterations 3最多 3 轮工具循环防止无限迭代知识归档产出物横跨两类存储——结构化数据库FTS5 情景记忆与人类可读的 Markdown 知识库MEMORY.md。系统提示词把 Archivist 的全部职责收敛为三条明确指令Index turns— 将每一轮对话记录到情景记忆FTS5中供未来检索召回Extract lessons— 识别可复用的模式、需要规避的错误以及用户偏好Update MEMORY.md— 将重要的学习成果追加到工作区知识库。从源码结构看这三条职责分别对应了三条独立但联动的实现路径回合索引走ArchivistHook::on_turn_completehook_impl.rs经验提炼走分段 recap 事件启发式提取lifecycle.rs知识库更新则通过白名单工具update_memory_md完成update_memory_md.rs。二、系统提示词如何装配prompt.md → 完整提示词Archivist 的提示词并非一段写死的字符串而是由 prompt.rs 中的build()函数在运行时动态拼装而成通过include_str!(prompt.md)把本文的 archetype角色原型嵌入二进制依次追加render_user_files(ctx)用户可见文件、render_tools(ctx)可用工具清单与render_workspace(ctx)工作区上下文。这正是 OpenHuman「提示词即产物」的设计理念——build()的输出就是 LLM 最终看到的内容Runner 不做任何二次加工见 prompt.rs 模块注释。这意味着 prompt.md 中每条规则都会原样生效且工具清单由运行时上下文决定而非硬编码。对应的单元测试 prompt_tests.rs 验证了build()在最小上下文空工具集、空工作区下也能产出非空提示词保证该 Agent 在任何场景下都能被加载。三、agent.toml 运行参数详解agent.toml 是 Archivist 的完整运行配置理解这些参数是自定义 Agent 的最佳范本配置项值含义与影响idarchivist注册表中的唯一标识delegate_namearchive_session编排器调用该子 Agent 时使用的委托名temperature0.4低随机性保证归档内容稳定、可复现max_iterations3最多 3 轮工具调用循环防止后台任务失控max_result_chars8000归档摘要回流到编排器的字数上限约 2000 tokens与普通子 Agent 上限一致防止冗长的「记忆写入确认」撑爆编排器上下文issue #4099sandbox_modenone无需沙箱因为其工具集写 MEMORY.md / 写数据库本就受白名单约束backgroundtrue后台运行不阻塞主会话omit_identity/omit_memory_context/omit_safety_preambletrue跳过身份、记忆上下文与安全前言进一步压缩上下文开销model.hintlocal优先使用本地模型契合「便宜、慢速、后台」的定位tools.namedupdate_memory_md、insert_sql_record、memory_store仅暴露三个写工具权限面最小化值得强调的是tools.named的最小权限设计Archivist 只能通过update_memory_md写 Markdown 知识库、通过insert_sql_record写 FTS5 表格、通过memory_store访问记忆存储——它没有文件系统通用读写权限从机制上杜绝了后台 Agent 越权操作工作区。四、职责一Index turns — 回合索引与情景记忆FTS5Archivist 的后端实现是一个PostTurnHook回合后钩子核心入口是ArchivistHook::on_turn_completehook_impl.rs。每轮对话结束后它依次执行写入用户回合把用户消息作为一条EpisodicTurnroleuser插入 FTS5 情景记忆表insert_turn返回数据库分配的自增 ID写入助手回合把助手回复作为第二条记录写入时间戳加0.001毫秒偏移确保同一轮内「用户在前、助手在后」的排序稳定工具调用摘要tool_calls_json随助手记录一并落库轻量教训提取若本轮存在失败的工具调用则调用extract_lesson_from_tools生成一条纯启发式教训不消耗 LLM格式为Tools that failed in this turn: xxx, yyyhelpers.rs双写 md 归档同时把回合写入workspace/memory_tree/content/episodic/session_id/seq:06.md的 md 备份存储最佳努力模式写失败不阻断回合为 FTS5 → md 的存储迁移做并行验证hook_impl.rs。会话分段把长对话切成「知识单元」原始回合是零散的时间序列Archivist 通过**会话分段conversation segmentation**把同主题的回合聚合成 Segment为后续 recap 提供边界。分段判定由 boundary.rs 的detect_boundary()完成按「从便宜到昂贵」的顺序执行四重检查boundary.rs检查项判定条件默认阈值TurnCountExceeded段内回合数超上限max_turns_per_segment 20TimeGap相邻回合间隔过长max_time_gap_secs 60010 分钟ExplicitMarker回合以话题切换短语开头如now lets、switching to、by the way,等内置 15 个英文短语表EmbeddingDrift回合向量与段质心的余弦相似度低于阈值min_cosine_similarity 0.4边界判定产出BoundaryDecision::Continue继续积累或Boundary::Boundary(reason)关闭当前段、以当前回合为起点新建段段 ID 形如seg-{uuid}。这个设计的精妙之处在于「便宜检查先跑、贵检查后跑」——一个回合若命中前三条任一规则就永远不会支付 embedding 比较的成本。五、职责二Extract lessons — 经验提炼的三层漏斗Archivist 的教训提取不是单一机制而是「无 LLM 启发式 → 启发式事件 → LLM recap」的三层漏斗按成本从低到高排列第一层工具失败教训零成本extract_lesson_from_tools纯规则实现遍历本轮工具调用记录只要存在success false的调用就生成一条「哪些工具失败」的教训。这是唯一逐轮执行的教训提取因为它不消耗任何推理资源。第二层事件启发式提取segment 关闭时在段关闭on_segment_closed时Archivist 对段内所有用户消息做句子切分按.!?换行符再与四组模式表做子串匹配events_heuristic.rsDecision决策如i decided、going with等模式Commitment承诺如i will、ill make sure等Preference偏好如i prefer、i like、i dont like等Fact事实如my name is、i work at、i live in、my timezone等。每个事件被写入EpisodicEvent表confidence 固定 0.6其中Preference 与 Fact 事件还会二次写入用户画像Profile Facets通过extract_profile_key取内容前 4 个有意义的词生成键与upsert_provider_facet合并置信度低的重复观察不会覆盖更强的旧记录lifecycle.rs。第三层LLM 段摘要recap可回退每个被关闭的 Segment 都会产出一段摘要recap默认使用summarization角色的推理模型生成见 lifecycle.rs 中RECAP_INFERENCE_ROLE常量。整个流程遵循软回退契约若with_config阶段探测到无法构建summarization角色的模型则回退到启发式摘要on_segment_closed永不返回 Err所有失败只记日志不中断回合recap 生成后持久化段摘要 → 调用 embedder 生成向量并写入segment_embeddings段关闭时是唯一写入点空摘要直接跳过以避免上游 embedding API 400→ 提取事件 → 更新画像。这里有一个重要的**「证据 vs 解读」数据策略**在config.learning.chat_to_tree_enabled true时Archivist 会把该段的原始散文回合用户 助手消息剥离工具调用 JSON以source_idconversations:agent整批灌入记忆树而绝不把 LLM recap 喂给记忆树——树必须基于原始证据自己归纳否则就成了「对摘要再做摘要」lifecycle.rs。六、职责三Update MEMORY.md — 知识库的并发安全写入update_memory_md是 Archivist 更新工作区知识库的唯一通道update_memory_md.rs其实现体现了 OpenHuman 对「后台并发写文件」这一危险场景的完整防护白名单约束工具只能修改MEMORY.md与SKILL.mdALLOWED_FILES常量其他工作区文件一概拒绝进程内互斥每个工作区目录对应一把全局 async 互斥锁以 canonicalize 后的路径为键并发跑并行 fork、cron的归档写操作排队执行而非互相覆盖issue #4458跨进程文件锁由于 cron 通过独立子进程启动进程内互斥锁无法覆盖因此再对工作区下的哨兵文件.memory-write.lock做flock独占锁阻塞式、运行在线程池同时拒绝 symlink 锁文件并用O_NOFOLLOW关闭 TOCTOU 窗口防止符号链接把锁重定向到工作区之外原子写入临时文件 原子重命名进程被 kill 也不会留下截断文件。这套机制与 prompt.md 中的Deduplicate规则形成「机制 智能」的双保险锁保证写入不互相破坏LLM 负责在追加前比对已有 MEMORY.md 内容、避免重复条目。七、质量规则五条提示词纪律prompt.md 的 Rules 部分是 Archivist 输出质量的灵魂逐条展开规则含义落地方式Be concise教训浓缩为一两句密集而非啰嗦max_result_chars 8000从物理上限制回流体量Be selective并非每轮都有教训只沉淀真正有用的观察默认只对工具失败做逐轮启发式提取其余留给段级 recapNever log secrets脱敏 API 密钥、令牌、密码与 PII由提示词纪律约束配合 log_redaction 等安全机制Use categories按类型打标签pattern模式、mistake错误、preference偏好、fact事实与事件启发式的 Decision/Commitment/Preference/Fact 分类一一呼应Deduplicate追加前先查 MEMORY.md避免重复配合update_memory_md的读-改-写加锁流程八、可配置开关learning 配置族Archivist 的行为并非硬编码而是由 learning.rs 中的学习配置族统一开关以下参数均可通过learning配置节或环境变量覆盖配置项默认值作用环境变量覆盖episodic_capture_enabledtrue情景捕获总开关即使learning.enabled关闭也保持活动情景记忆是对话回合的系统事实来源OPENHUMAN_LEARNING_EPISODIC_CAPTURE_ENABLED0\|1chat_to_tree_enabledtrue是否把对话原始回合灌入记忆树conversations:agent—goals_enrichment_enabledtrue段关闭后是否后台触发goals_agent刷新长期目标清单MEMORY_GOALS.mdOPENHUMAN_LEARNING_GOALS_ENRICHMENT_ENABLED0\|1stm_recall_enabledtrue是否在会话开始注入跨会话的近期情景召回FTS5 关键词 cosine 段摘要OPENHUMAN_LEARNING_STM_RECALL_ENABLED0\|1explicit_preferences_enabledtrue显式固定偏好是否注入系统提示词OPENHUMAN_LEARNING_EXPLICIT_PREFERENCES_ENABLED0\|1注意learning.enabled默认是false而episodic_capture_enabled默认true——这体现了「情景记忆是独立于推理学习栈的基础设施」这一架构判断即使关闭反射/稳定性检测等推理组件对话归档依然持续运转。九、会话收尾flush 保证最后一段不丢失一个容易被忽略的边界情况是会话结束时往往没有一个触发边界的回合导致最后一个 Segment 永远处于 open 状态、得不到 recap。Archivist 通过flush_open_segment解决lifecycle.rs在会话结束Agent::spawn_session_memory_extraction时强制关闭残留的 open segment并走与正常段关闭完全相同的路径——recap embedding 事件提取 树灌入。该操作幂等段只会从open → closed迁移一次可安全重复调用。十、小结一条完整的「会话 → 知识」流水线将以上机制串联一次会话在 OpenHuman 中的记忆沉淀路径是逐轮on_turn_complete将用户/助手回合写入 FTS5 情景表双写 md 归档工具失败生成零成本教训分段detect_boundary按回合数、时间间隔、话题短语、向量漂移四重检查切分 Segment段关闭LLM recap或启发式回退→ 段摘要与 embedding 落库 → 启发式事件提取 → 画像 Facet 合并 → 原始散文灌入记忆树 → 后台刷新长期目标知识库update_memory_md以白名单 进程内锁 跨进程 flock 原子重命名的方式安全追加 MEMORY.md/SKILL.md会话结束flush_open_segment兜底收尾最后一个开放段。Archivist 的设计核心可以概括为三句话用便宜机制做逐轮工作用昂贵机制做段级工作用并发安全机制做文件写入。如果你想在 OpenHuman 中自定义类似的后台记忆 Agentagent.toml 的「background 最小工具集 低 temperature max_result_chars 限流」组合加上 prompt.md 的「职责 规则」双层结构是一份可以直接复用的模板。【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhuman创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考