IronClaw 内存原生提供方(memory-native)深度解析:MemoryService 契约实现、双通道召回与提示写入安全
2026/9/23 22:09:33 网站建设 项目流程
  • 人工智能
  • AI 应用
  • 交互助手
  • AI Agent

【免费下载链接】ironclaw

IronClaw is an Agent OS focused on privacy, security and extensibility

项目地址:https://gitcode.com/gh_mirrors/iro/ironclaw
点击查看免费下载

IronClaw 将"持久化记忆"拆分为"provider-neutral 契约"与"可插拔提供方"两层:memory-native(扩展 idironclaw.memory)是随二进制默认捆绑、基于文件系统实现的[memory]提供方,负责记忆文档的读写、搜索、树形浏览、结构化用户档案,以及检索前(retrieve-before)/记录后(record-after)的完整生命周期。本文以 crates/extensions/packages/memory-native/CLAUDE.md 为骨架,结合该包的源码、manifest.toml、prompt 资产与测试套件,讲清它"拥有什么、如何实现、受哪些约束"。

一、包的定位:契约在ironclaw_memory,实现在ironclaw_memory_native

memory-native是一个完整的 self-contained 包,目录本身即"crate + manifest + prompts + schemas"四位一体(CLAUDE.md "Start Here" 一节)。它与mem0包是同一[memory]提供方表面的两个候选实现——每次部署恰好激活一个(README.md),默认就是本包。

# crates/extensions/packages/memory-native/manifest.toml id = "ironclaw.memory" name = "Reborn Memory" trust = "first_party_requested" [runtime] kind = "first_party" service = "native_memory_provider" [memory] lifecycle = ["read_long_term", "read_short_term", "record_interaction", "profile_read"] guidance_doc = "prompts/memory-guidance.md"

关键分层事实:

  • 契约归属MemoryServicetrait、DTO、scope/path/context 值类型、prompt-safety 词汇表、审计/事件契约都定义在 crates/domains/ironclaw_memory,本包只实现并 re-export(lib.rs)。
  • 依赖集非常克制(Cargo.toml):只依赖ironclaw_memoryironclaw_filesystemironclaw_safetyironclaw_host_api四个 crate;不依赖 mem0、任何 HTTP client、ironclaw_extension_host/ironclaw_extension_manager或任何 kernel/product crate。
  • 链接方式:包 crate 只被二进制链接,唯一例外是ironclaw_host_runtime持有普通依赖(其捆绑式内存包构建器见 crates/kernel/ironclaw_host_runtime/src/memory_native_extension.rs),这是契约文档中明确记录的 pending port inversion,而非迁移。

二、本包拥有的功能面(What This Crate Owns)

1. 文档仓储与后端插件契约

MemoryDocumentRepository有两个实现:

  • FilesystemMemoryDocumentRepository生产部署目标,单层叠加在RootFilesystem之上;
  • InMemoryMemoryDocumentRepository仅测试支撑,绝不用于部署(CLAUDE.md "Guardrails")。

后端层MemoryBackend/RepositoryMemoryBackend/MemoryBackendCapabilities(backend.rs)封装"仓储 + 索引器 + 能力声明"。能力声明是强制执行输入:声明不支持的搜索/文件行为会在后端产生任何副作用之前 fail-closed。原生后端默认声明(见 service.rs 的build_native_backend):

file_documents = true, metadata = true, versioning = true, prompt_write_safety = true, full_text_search = true, delete = true, transactions = true

注意:不声明vector_search——本包没有 embedding-provider 端口,向量检索只能针对预先提供的 embeddings 激活,否则在后端 fail-closed 消息中直接拒绝(这正是"无向量、纯 FTS"的设计取舍,mem0 后端则相反)。

2./memory虚拟路径语法与 scope

  • MemoryDocumentPath:以(tenant_id, user_id, agent_id, project_id, relative_path)定位一条记忆文档;
  • MemoryDocumentScope(path.rs):拒绝空字符串作为提供的 id,因此"未指定 agent/project"的存储哨兵必须用空字符串,而_none只是虚拟路径哨兵、永远不得落库。

唯一性约束UNIQUE (tenant_id, user_id, agent_id, project_id, path)。每一条读/列/搜索/写/版本/分块操作都按完整四元组过滤,绝不从路径前缀推断 project scope(CLAUDE.md "Guardrails")。

3. 分块、内容哈希与索引器

ChunkConfigchunk_documentcontent_sha256(chunking.rs)负责把文档切成块并做内容寻址;ChunkingMemoryDocumentIndexer(indexer.rs)把块写入索引。写入提交语义:一旦持久化成功即视为已提交,之后派生索引/embedding 刷新失败不得让写入报告失败(否则会把"持久化已成功"误报为失败)。

4. 混合搜索:FTS + 向量经 RRF 融合

MemorySearchRequest/MemorySearchResult/FusionStrategy(search.rs)实现了混合搜索骨架:全文检索与向量检索各自产生候选集,再通过 RRF(Reciprocal Rank Fusion)融合排序。由于原生后端vector_search=false,实际运行时走纯 FTS 路径——MemorySearchRequest::new(&query).with_limit(...).with_pre_fusion_limit(limit.max(20)).with_vector(false)(service.rs 的search方法)。

5. 文件系统适配器与显著事件 sink

  • MemoryBackendFilesystemAdapter/MemoryDocumentFilesystem(filesystem.rs):把记忆文档映射到虚拟文件系统;
  • 显著事件 sink(events.rs):记忆写入/检索的关键节点产生审计事件。

6. 提示写入安全引擎(PromptWriteSafetyPolicy)

词汇表(operation、source、severity、reason code、事件 payload/sink、policy trait、protected-path registry)在ironclaw_memory强制执行引擎在本包(safety.rs):

  • DefaultPromptWriteSafetyPolicy=PromptProtectedPathRegistry+ironclaw_safety::Sanitizer
  • check_write先做 protected-path 分类,再跑 sanitizer,把Severity映射到契约的PromptSafetySeverity桶(Low/Medium/High/Critical)。

三、模型面记忆指引(guidance_doc):提供方自带的"什么该记"

prompts/memory-guidance.md[memory].guidance_doc声明的模型面指引(service.rs 通过MEMORY_GUIDANCE/MEMORY_GUIDANCE_DOC_REF常量 +MEMORY_ASSETS资产表捆绑),要点:

  • 保存时机:用户给出持久偏好、事实、决定或纠正时,主动用ironclaw.memory.write保存(targetmemoryappend: true、一行自包含简洁事实),不要等被要求
  • 措辞纪律:写成关于用户的陈述句("User prefers concise responses"),绝不写成给自己的指令("Always respond concisely")——因为保存的文本会在每个后续回合作为上下文被重新读取,祈使句会变成一条覆盖用户当前请求的常驻指令;
  • 不保存清单:任务进度、会话结果、已完成工作日志、临时 TODO、PR 号/issue 号/commit SHA 等短期工件;一两周内会过时的事实不进持久记忆;绝不保存 secrets、凭据、token
  • 去重更新:写入前先 search/read,更新已有条目而非追加近似重复;显式"忘记"用append: false重写文档(追加式纠错会让原始条目仍然留在原地,记忆块会同时携带两者)。

这一指引属于提供方自有资产,因为它点名本提供方的工具、描述本提供方的召回行为;host 只把绑定提供方声明的指引拼进 system prompt,自己不写任何一句。mem0 故意不提供 guidance(无追加)。

四、五个模型工具面:read / write / search / tree / profile_set

manifest.toml[[tools]]数组声明了 5 个工具,input/output schema 由schemas/memory/*.v1.json资产内联提供(单一事实源),prompt 文档在prompts/memory-native/

工具 id行为effects默认权限origin gate(loop_run)
ironclaw.memory.read读当前 scope 的持久记忆文档read_filesystemallowungated
ironclaw.memory.write写/追加/补丁记忆文档read_filesystem+write_filesystemallowgated_unless_granted
ironclaw.memory.search仅搜索内部持久记忆read_filesystemallowungated
ironclaw.memory.tree以紧凑树列出记忆文档read_filesystemallowungated
ironclaw.memory.profile_set记录 timezone/locale/location 结构化档案read_filesystem+write_filesystemallowungated

安全要点(manifest 注释明确):origin_gate_matrix缺失不等于"无门禁"——S4 授权折叠对任何带 origin 戳的调用 fail-closed 到Forbidden。Product/Automation 对全部五个工具都是forbidden(deny-by-default);write 保持gated_unless_granted(可写任意路径);read-like 工具通过UNGATED_LOOP_RUN_CAPABILITIESallowlist 放行。

write 的路径别名与解析

resolve_target_path(service.rs)定义了 4 个约定别名 + 任意相对路径:

target解析结果
memoryMEMORY.md(常驻记忆文档)
heartbeatHEARTBEAT.md
bootstrapBOOTSTRAP.md(清空语义)
daily_logdaily/YYYY-MM-DD.md(按调用方 timezone 解析,缺省 UTC)
其他原样作为相对路径

profile_set 与档案路径

profile_set/profile_read使用独立于 agent/project 的档案路径profile_scope_and_path把 scope 钉在(tenant_id, user_id, agent=None, project=None),文档路径固定为context/profile.json——这是"关于人类用户本人的私有本地事实",与builtin.trace_commons.profile_set无关。写入用 compare-and-write(CAS)+ 至多MAX_MEMORY_PATCH_RETRIES = 8次重试,并校验 timezone/locale/location 字段必须为字符串。

五、生命周期钩子与双通道召回

manifest 声明了完整生命周期:read_long_termread_short_termrecord_interactionprofile_read(未声明的钩子永远不会被调用)。NativeMemoryService是纯内部实现,模型只能通过工具触达,生命周期钩子由 host 驱动(service.rs 的MemoryServiceimpl)。

常驻 MEMORY.md 前缀(read_long_term 的 always-on curated prefix)

本提供方在自己的长程通道头部、全文命中之前无条件投放常驻MEMORY.md(#7185),与本次查询无关:

  • 理由:全文搜索只有在当前消息与存储事实共享词汇时才有效——新开一个无关话题的会话,已保存的偏好就不可见了;而 write 指引让模型维护的正是这份常驻文档;
  • 上限MAX_CURATED_SNIPPETS = 4,防止常驻文档吃光调用方的max_snippets配额、饿死其后的搜索命中;
  • 分块CURATED_CHUNK_RAW_BYTES = 400字节/块:host 对模型可见 snippet 有 512 字节上限并跑 prompt denylist,分块保证每个模型可见字节都经过与搜索命中相同的检查,携带 denylisted 秘密的行只丢自己、不连累整份文档;
  • 截断标记" (truncated)"与行内分隔符"; "都是明文单词——方括号等符号会被 host 的 safe-summary 规则拒绝;
  • 缺失是正常态(用户从未保存过任何东西),此时优雅降级为空前缀,而非让通道失败;后端故障同样降级并打debug!——记忆是最佳努力上下文,绝不让一次 turn 随它一起倒下。

长/短程双通道

  • read_long_term:常驻前缀 + 全文命中;从候选集中剔除threads/子树(与短程通道保持不相交)和MEMORY_PATH本身(避免重复占槽);
  • read_short_term:只检索活动线程threads/<thread_id>/子树;thread_id来自可信 host 运行上下文,绝不来自模型;无活动线程则降级为空;
  • 两个通道共享ranked_in_scope_results先超量抓取max_snippets * 8,下限 64)再做 scope+通道过滤,最后才截断——否则全局 top-N 的普通长程命中会饿死线程限定的短程通道。

record_interaction:每轮转录写入threads/

record_interaction把完整 turn 历史以 Markdown 转录(每条消息## {role} ({name}))写入每轮独立文件threads/<thread_id>/<turn_run_id>.mdappend: false覆盖写):

  • 幂等性:调度器重跑已Completed的 run 会覆盖同一文件,而不是把对话复制进无限增长的共享log.md
  • 这是唯一合法的threads/写入口:公共write对任何threads/前缀目标直接拒绝(保留命名空间审计 L1——散落写入会成为"检索黑洞"),只有可信的记录器经write_reserved_document绕过该守卫,且该 helper 自身也防御性拒绝非threads/路径。

六、版本控制、补丁与并发安全

  • Patch 语义old_string/new_string都非空(保留 Origin 的"空 new_string 不得删除匹配文本"约束),支持replace_all;基于 CAS(expected hash)+ 至多 8 次重试的 read-compare-write 循环;
  • append 语义:每条追加条目以恰好一个换行符终止——后端 append 是字节精确的,若不加换行,两条受引导的正确保存("likes tea" 与 "lives in Berlin")会拼成一行likes tealives in Berlin被当成一个事实;
  • 并发安全测试tests/#[tokio::test(flavor = "multi_thread", worker_threads = 2)]跑针对replace_document_chunks_if_current的真实抢占竞态测试(Cargo.toml 注释:单线程下tokio::join!协作式轮询会隐藏真实竞态,因此显式依赖rt-multi-thread)。

七、路径安全与输入卫生

reject_local_or_traversal_path拒绝三类输入(service.rs):

  1. \反斜杠的路径;
  2. 形如文件系统绝对路径 /~/开头 / 盘符(C:\C:/)的路径;
  3. ..遍历片段的路径(按/分段检查)。

八、守卫与边界(Guardrails / Do Not Move In Here)

从 CLAUDE.md 提炼的可执行约束:

  • 依赖纪律:只依赖上述四个 crate;ironclaw_extension_contracts仅在某个表面真正需要时才允许加入;
  • scope 纪律:后端是 host 解析 scope 之后的插件,不得推断更宽的 tenant/user/agent/project 权限,不得绕过 mount/scope 文件系统检查;
  • 语义搜索、分块、embeddings、版本控制必须留在 memory 自有的 repository/indexer 抽象之后;通用 mount/catalog 逻辑留在ironclaw_filesystem
  • 不迁移入本包:中性MemoryService词汇表(留在ironclaw_memory)、通用文件系统语义、直接 provider HTTP、原始 secret 处理、loop prompt 策略;
  • 输出纪律:错误、事件、快照、日志、文档中不得出现 secrets、raw host 路径、后端错误细节、未脱敏的用户内容。

九、验证体系:契约测试套件

验证分三层(CLAUDE.md "Validation"):

  1. 快速本地检查cargo test -p ironclaw_memory_native——tests/下五个契约文件:
    • memory_service_contract.rs(共享MemoryService一致性套件)
    • memory_backend_contract.rs
    • memory_filesystem_contract.rs
    • repo_filesystem_contract.rs
    • repo_in_memory_contract.rs 这些测试瞄准内存后端,覆盖版本控制、chunk 替换、metadata 级联、混合搜索融合等记忆文档语义(后端特定的 libSQL/Postgres 行为覆盖属于ironclaw_filesystem的后端契约测试);
  2. 边界检查:依赖/API 变更后跑cargo test -p ironclaw_architecture_tests
  3. 跨提供方一致性:同一共享套件也跑在 mem0 包上——契约变动时必须让两个提供方都保持通过。

测试基建注意点:test-supportfeature 默认关闭,避免契约测试 harness 中的.expect/.unwrap/assert!*进入生产构建并触发 scripts/check_no_panics.py 扫描;本 crate 的集成测试通过自依赖ironclaw_memory_native = { path = ".", features = ["test-support"] }启用(Cargo.toml)。

十、调度运维:每十轮一次的记忆整理(scheduled_ops)

manifest 中声明了提供方自有的循环维护(#7664):

[[memory.scheduled_ops]] trigger = "after_turn" interval_turns = 10 pass = { prompt = "prompts/memory_curation.md", tools = ["ironclaw.memory.read", "ironclaw.memory.search", "ironclaw.memory.write"], max_model_calls = 10 }
  • 归属原则:整理工作属于提供方——prompt 描述本提供方的文档形状、挑选本提供方的工具,因此随 manifest 声明而非放在 product/loop 层;host 只负责时钟、调用信封与授权;
  • 预算max_model_calls = 10是本轮自身预算(低于 host 上限);#7770 的实测显示真实模型会多花调用(一次失误的 read、一次多余的 write),需要余量来完成报告;
  • 工具选择限制:pass 的 tools 只能从同一 manifest 声明的[[tools]]中挑选,且每次调用仍要过常规能力授权。

整理 prompt(prompts/memory_curation.md)与 guidance 资产一起由MEMORY_ASSETS表承载,host 通过泛型解析(不按包名硬编码匹配),manifest 引用与资产文本由native_bundle_declares_guidance_that_resolves_to_the_bundled_asset测试保证不漂移。

结语

memory-native是"契约中立、实现可插拔"架构的完整样本:ironclaw_memory定义词汇表与行为契约,本包以文件系统为底座、以严格依赖集和 fail-closed 能力声明为边界,提供常驻记忆前缀、长/短程双通道召回、每轮转录、结构化档案与提示写入安全,并通过共享一致性套件与 mem0 提供方保持可互换。若需替换后端,可参照../mem0包实现同一MemoryService契约,二者在 compose 时经[memory]绑定切换,五个模型工具的输入/输出 schema 完全不变。

  • 人工智能
  • AI 应用
  • 交互助手
  • AI Agent

【免费下载链接】ironclaw

IronClaw is an Agent OS focused on privacy, security and extensibility

项目地址:https://gitcode.com/gh_mirrors/iro/ironclaw
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询