拓冰建站拓冰建站
首页 / 资讯中心 / 正文

OpenHuman 工具级记忆(Tool-Scoped Memory):把“绝不要给 Sarah 发邮件”变成 Agent 必须遵守的硬约束

OpenHuman 工具级记忆Tool-Scoped Memory把“绝不要给 Sarah 发邮件”变成 Agent 必须遵守的硬约束【免费下载链接】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本文基于 OpenHuman 官方文档 Tool-Scoped Memory 展开完整讲解 OpenHuman 中“工具作用域记忆层”的设计与实现它如何为每个工具建立独立的规则命名空间、如何从用户指令和重复失败中自动捕获规则、如何通过三级优先级让 Critical 规则免疫会话内 Token 压缩以及六个memory.tool_rule_*RPC 方法的参数细节。读完本文你将能够理解并操作这一持久化、工具级安全规则系统并能在源码层面验证它的捕获、存储与注入全链路。什么是工具级记忆定位与命名空间设计工具级记忆tool-scoped memory层 捕获的是Agent 应当如何使用某个具体工具的“可执行指导”。它有两个明确的分界它区别于 Memory Tools 提供的通用recall/store/forget检索能力——后者是面向 Memory Tree 知识库的通用读写它也区别于纯统计性质的tool_effectiveness统计命名空间——后者只记录“发生了什么”调用次数、错误模式而工具级记忆记录“该怎么做”。一句话概括它的价值把用户在对话中随口说出的 “never email Sarah”绝不要给 Sarah 发邮件转写成 Agent 在后续每一轮都必须遵守的硬约束。这正是 OpenHuman issue #1400 要求的一等公民级“持久化学习 高优先级规则”存储与检索系统。命名空间隔离从源码 capture.rs 的模块注释可以看到其隔离原则每个工具拥有自己的独立命名空间tool-{tool_name}与global、skill-{id}以及仅供统计的tool_effectiveness命名空间完全分开。存储层实现 中的命名空间识别也印证了这一点——常量TOOL_NAMESPACE_PREFIX tool-专门用于识别工具级规则命名空间而所有写入一律经由tool_memory_namespace()统一构造保证“trim 小写”的规范化规则只存在于一处// src/openhuman/memory/tool_memory/store.rs /// Namespace prefix every tool-scoped rule namespace carries. const TOOL_NAMESPACE_PREFIX: str tool-;统计信息tool_effectiveness/tool/{name}与规则tool-{name}/rule/{id}有意分属不同命名空间——一个跟踪“发生了什么”另一个跟踪“对此该怎么办”。这种分离让安全规则永远不会被统计数据的读写路径污染。数据模型ToolMemoryRule 字段详解命名空间内的每条条目都是一个ToolMemoryRule结构。官方文档定义的字段语义如下表完整继承自原文档字段用途id每条规则的稳定 UUID。Upsert 时会复用同一个 id。tool_name规则适用的工具如send_email、shell。ruleAgent 必须遵守的自然语言指导。prioritycritical、high或normal同时驱动检索与压缩策略。sourceuser_explicit、post_turn或programmatic——记录规则来源provenance。tags自由标签safety、permission等。created_at/updated_atRFC3339 时间戳。结合 store.rs 的put_rule实现还可以补充几个文档未展开、但实操中重要的行为细节Upsert 语义tool_name和rule均为空时直接报错id为空时自动通过ToolMemoryRule::generate_id()铸造 UUID。tool_name会先做 trim 小写化与命名空间构造使用同一套规范化因此调用方用原始名称读回时命中的是同一个命名空间。created_at保留对同一(tool_name, id)的重复 upsert 会保留最初的created_at只刷新updated_at。实现上用一把进程级互斥锁rule_mutation_lock串行化“先 get 再 store”的读改写序列防止并发 upsert 复活旧的created_at。分类落库每条规则写入时带上MemoryCategory::Custom(tool_memory)分类便于在统一记忆后端中与通用记忆区分。读取容错list_rules中对无法反序列化的损坏行是跳过而非报错——一条坏数据不能把该工具的其他规则从提示词中全部隐藏同理fetch_rule将坏行视为“不存在”使其不阻塞后续 upsert 覆盖。另外有一个特殊哨兵值值得注意当用户指令中没有任何工具调用可以挂载时规则会落到__unscoped__工具名下capture.rs以便在下一轮由 Agent 重新归位这类规则不会进入提示词预取避免把与任何真实工具无关的指导强行钉进任意会话的提示词。优先级与压缩免疫Critical / High / Normal 三级官方文档给出的优先级矩阵如下完整继承优先级存储位置是否抗压缩compression-resistantcritical通过ToolMemoryRulesSection钉入系统提示词是——系统提示词按会话冻结绝不会被会话内压缩器改写。high同一个系统提示词块排在 critical 之后。是——同一机制。normal存于命名空间内按需经memory_recall检索。否——像其他命名空间记忆一样可被压缩。这种“抗压缩”特性是结构性的critical 与 high 规则寄宿在系统提示词中而推理后端的 prefix cache 会把系统提示词在整个会话期间冻结。没有任何 Token 压缩路径能悄悄丢掉一条critical规则。源码层面的两个关键证据预取过滤store.rs 的rules_for_prompt用priority.is_eager()过滤出 Critical High 规则先按 critical 优先、同级内按updated_at新者优先排序然后截断至TOOL_MEMORY_PROMPT_CAP// src/openhuman/memory/tool_memory/store.rs /// A cap on the **High**-priority remainder only... /// dropping one to fit a budget is the failure this surface exists to prevent. pub const TOOL_MEMORY_PROMPT_CAP: usize 30;注意这是一个文档化的权衡上限主要作用于 High 优先级的剩余部分一旦 CriticalHigh 规则的总数超过 30 条排在队尾的规则理论上包括 Critical会被截断——源码注释明确保留了这一与引擎一致的语义而不是“悄悄改进”成无脑保留全部 Critical。提示词区块构造即快照prompt.rs 中ToolMemoryRulesSection在构造时就把渲染结果冻结为快照字符串PromptSection::build()直接原样返回、不依赖任何运行时上下文——注释里写得很直白这是为了保持推理 prefix cache 始终温热。捕获管线两条自动路径捕获钩子 的实现在 ToolMemoryCaptureHook。它实现 harness 的PostTurnHook接口钩子名为tool_memory_capture在每一轮对话结束后自动触发两条捕获路径路径一用户指令User Edicts→ Critical 规则用户消息中出现never 动词 名词、dont 动词 ...、do not 动词 ...或stop 动词ing ...这类祈使句式时会被提升为匹配工具上的Critical规则。extract_user_edicts 的具体匹配逻辑按.、换行、;切分用户消息逐句检查是否以或包含上述祈使前缀小写化后匹配stop一词只在句边界出现时才算祈使句消息开头、. stop或\nstop避免 “I want to stop working” 这类普通表达误触发命中的句子会被截断到MAX_RULE_LEN 240字符防止异常输入撑爆命名空间工具归位先尝试pick_tool_for_edict——检查本轮实际调用过的工具名是否作为词出现在指令文本中再看一组刻意保持精简的常用名词别名表tool_aliases工具名包含用户口语别名*mail*email、mail*shell*/*bash*/*exec*shell、terminal*browser*/*web*/*http*browser、web*slack*slack、dm也就是说email会被映射到名为send_email的工具shell映射到bash/exec。注释特别说明这张表故意很小更复杂的语义抽取“属于 LLM 抽取器的事”。别名也未命中时规则落到本轮第一个执行的工具下让它紧邻相关调用点若本轮完全没有工具调用则落到__unscoped__。捕获成功后以ToolMemoryPriority::CriticalToolMemorySource::UserExplicit 标签[user-edict]落库。路径二重复工具失败 → Normal 观察记录extract_repeated_failures 统计本轮中每个工具的失败次数同一工具在一个轮次内失败 ≥ 2 次时才生成一条Normal优先级观察记录单次瞬时失败被忽略防止命名空间被噪声填满。记录正文内联总结失败概要例如Tool failed 2 times in one turn (首次失败的 output_summary). Consider an alternative approach before retrying.来源标记为ToolMemorySource::PostTurn、标签[repeated-failure]这样 Agent 下次考虑使用该工具时就有上下文。两条路径都刻意保守——只在信号明确时触发且捕获的规则正文始终回指用户自己的原话让审阅者能看出到底什么触发了这条规则。开关默认开启可单独关闭钩子在学习子系统learning subsystem开启时默认启用可用环境变量单独关闭env 覆盖层 确认了取值解析OPENHUMAN_LEARNING_TOOL_MEMORY_CAPTURE_ENABLED0从解析代码看0/false/no/off均被识别为关闭写入learning.tool_memory_capture_enabled配置项。工具选择时刻的检索预取 系统提示词钉装检索侧的设计完整继承原文档并补充源码印证会话开始时harness 通过ToolMemoryStore::rules_for_prompt预取所有 Critical 和 High 规则session builder 将其渲染为## Tool-scoped rules区块常量TOOL_MEMORY_HEADING经 ToolMemoryRulesSection 钉入系统提示词因为提示词在会话生命周期内冻结这些规则在每一轮的工具选择时刻、任何实际工具执行之前都可见。渲染格式由 render_tool_memory_rules 决定规则先按tool_name→ 优先级 → 规则文本 → id 排序然后按工具分组输出。实际进入系统提示词的内容长这样## Tool-scoped rules These rules are pinned by the user or by the safety pipeline. Treat every entry as a hard constraint when considering the matching tool — do not override them silently. Lower-priority guidance lives in the tool-{name} memory namespace and can be queried via memory_recall if needed. ### send_email - **[critical]** Never email Sarah at sarahexample.com.低优先级的指导则被排除在提示词预算之外Agent 通过调用memory_recall查询tool-{name}命名空间来按需获取。RPC 接口memory 命名空间下的六个方法schemas/tool_memory.rs 注册的FUNCTIONS与原文档表格一一对应六个方法均暴露于memory命名空间下方法用途参数snake_case JSONmemory.tool_rule_putUpsert 一条规则。安全关键条目使用prioritycritical。tool_name必填、rule必填、priority可选默认normal、source可选默认programmatic、tags可选数组、id可选提供则原位 upsertmemory.tool_rule_get按(tool_name, id)取单条规则不存在时返回 null 而非报错。tool_name、idmemory.tool_rule_list列出某工具的全部规则按优先级critical → high → normal再按updated_at降序排序。tool_namememory.tool_rule_delete删除一条规则返回布尔值规则存在过则为true。tool_name、idmemory.tool_rules_for_prompt返回渲染好的 Markdown 块 结构化规则快照——即 session builder 钉装的内容。tools可选数组空或省略时扫描所有已知工具命名空间memory.tool_rules_json返回某工具规则的原始 JSON 列表供 envelope 消费方使用。tool_name参数默认值可在 ops/tool_memory.rs 的ToolRulePutParams中确认priority与source均带#[serde(default)]省略时分别为normal与programmatictool_rules_for_prompt的返回结构为{ rendered: string, rules: ToolMemoryRule[] }。所有方法都走与其他 memory RPC 相同的active_memory_client/MemoryGuard管道ops 层 的tool_memory_guard()统一获取 guard再经as_tool_memory()路由到工具级记忆家族JSON 载荷统一 snake_casepriority: critical、source: user_explicit。若当前 memory driver 未宣告ToolMemory能力handler 会返回memory driver does not support the tool_memory family错误——内嵌驱动总是宣告该能力因此这条路径仅在 null/兜底绑定时可达。端到端安全用例“Never email Sarah”原文档将该用例作为回归测试覆盖全链路如下结合源码路径逐条印证用户说在某轮调用过send_email的对话中说“Never email Sarah at sarahexample.com.”捕获ToolMemoryCaptureHook 提取指令将email别名映射到send_email工具在tool-send_email/rule/{uuid}下写入一条 Critical 规则来源user_explicit标签user-edict。下一会话prefetch_tool_memory_rules_blocking拉取全部 Critical 与 High 规则session builder 把ToolMemoryRulesSection追加进系统提示词。生效Agent 在选择任何工具之前就看到### \send_email分组下的-[critical]Never email Sarah at sarahexample.com.且该规则在任何会话内 Token 压缩中都会存活。相关覆盖与集成测试位于 src/openhuman/memory/tool_memory/store_tests.rs、capture_tests.rs、prompt_tests.rsRPC 与 schema 层另有 ops 层测试 与 schema 层测试。小结与延伸阅读工具级记忆层的三个设计支点值得记住命名空间即边界tool-{name}与统计、全局、技能命名空间物理隔离规则与观测互不污染优先级即生命周期critical/high 借道冻结的系统提示词获得结构性抗压缩能力normal 留在命名空间内按需memory_recall捕获即取证两条自动捕获路径都保守触发、保留用户原话并可用OPENHUMAN_LEARNING_TOOL_MEMORY_CAPTURE_ENABLED0单独关闭。相关文档Memory Tools —— 通用recall、store、forget记忆工具。Smart Token Compression —— 系统提示词所要防御的压缩机制。【免费下载链接】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),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门