@bzpovo/agent-memory
v0.1.1
Published
Faithfulness-gated four-layer advertising agent memory plugin for OpenClaw
Maintainers
Readme
Lingix Agent Memory
面向广告投放 Agent 的四层长期记忆系统,同时可作为 OpenClaw 工具插件使用。它以 SQLite 持久化记忆,提供忠实性门控、LLM Judge、Embedding/FTS 混合检索、实时记忆 TTL、受控更新、策略模板晋升以及完整审计链路。
当前版本:
0.1.0。OpenClaw 插件 ID:lingix-agent-memory;npm 包名:@bzpovo/agent-memory。
核心能力
- 四层记忆:L1 核心规则、L2 策略经验、L3 实时环境、L4 技能模板。
- DoubtMem Guard:三层串行架构——规则先行(确定性拦截未经用户确认的 Assistant 建议/推荐、试探性偏好、Agent 推断直写 L1/L2、无依据数值结论)→ LLM Judge 或本地 DoubtMem 模型(语义归因、grounding 复核、一致性判定)→ 分层策略器(L1–L4 各自的来源/条件/时效约束,L1/L4 硬性限制可覆盖 LLM 结论)。四种决策动作:WRITE / UPDATE / REJECT / PENDING_REVIEW(高风险转人工审核)。
- LLM Judge / ValueScorer / ConflictDetector(必需):通过 OpenAI-compatible API 处理语义归因、一级价值打分和语义冲突检测;未配置
MEMORY_LLM_API_KEY时系统会直接报错拒绝启动,不再静默降级为规则判定。 - factuality_check 事实检测工具(可选):
LLMJudge可注入tool_verifier(默认实现DefaultFactualityToolVerifier),在候选记忆命中数值/效果/时效性表述或已有相关记忆时,先用campaign_analysis/memory_search/industry_benchmark做一次客观核验,再据此对grounding做升级/降级,减少对 LLM 自身数值判断的依赖;未注入时行为与之前完全一致。 - 混合检索:结构化筛选 + SQLite FTS5 关键词检索 + 可注入的真实 Embedding 余弦相似度。
- 记忆治理:L3 默认 24 小时 TTL;高质量新证据可以版本化 UPDATE;成熟 L2 才能晋升 L4。
- 质量闭环:Trace 审计、抽样复核、Guard 精度/召回/误拒率指标(
MemoryStorage.guard_metrics,依赖人工复核)、护栏指标(MemoryStorage.guardrail_metrics,REJECT 率/记忆库增长率,直接由已有数据计算,无需人工复核)、反思和容量淘汰。
架构
记忆写入支持两种入口(见下文「快速开始」第 5 步),最终都会汇聚到同一套四级
筛选漏斗(memory/trigger.py::process_event),依次回答四个问题:值不值得记、
是不是真的、和已有记忆是否重复/矛盾、质量够不够:
OpenClaw Tool / CLI
│
├── ingest(description) ──┐ 自由文本,无需预先判断事件类型
│ ⓪ 自动分类 (LLMEventClassifier)
│ → trigger_type + 结构化 raw_data
│ 置信度不足/无法分类 → 直接拒绝,不进入下方漏斗
│ │
└── trigger(event_type, data) ─────┘ 已有结构化数据,跳过分类
│
▼
MemoryTrigger.process_event()
① 价值判断 (LLMValueScorer) —— 这条信息是否包含可沉淀的知识
② 忠实性门控 (DoubtMem Guard) —— 这条信息是不是真的、该写到哪一层
③ 冲突检测 (LLMConflictDetector) —— 和已有记忆是否重复/矛盾
④ 质量评估 (MemoryValidator) —— 五维度加权复核,产出 importance_score
│
▼
SQLite Storage(FTS5 + Embedding 混合检索)
│
└──────────── Trace / Review / Metrics ────┘第②级 DoubtMem Guard 内部采用三层串行处理:先由确定性规则做前置拦截——未经
用户确认的 Assistant 建议/推荐(正则匹配 "建议"/"推荐"/"you should" 等表达后无
用户确认信号)直接 REJECT,不调用任何 LLM Judge;Agent 推断(source_attribution
= agent_inference)不允许直接写入 L1/L2;L1 仅接受权威来源(human_config/
rule_update),非权威来源转 PENDING_REVIEW;L4 不接受外部写入,仅由 L2 受控
晋升。规则阶段给出 WRITE/UPDATE 但需要语义复核时才调用 LLM Judge(网关
LLMJudge 或本地 DoubtMemLocalJudge),L1/L4 的硬性层级限制不受 Judge 结论
影响——即使 LLM 判定 WRITE,L1/L4 的分层约束仍由确定性代码最终把关。
importance_score 统一来自第④级 MemoryValidator 的五维度加权评分(0-1 换算
为 0-10),不再由第一级价值判断赋固定基准分——第一级只做“值不值得记”的二元
判断,真正的重要度/质量差异由第四级评分体现,参与后续 retention_score(留存
排序)和检索相关度排序。
第一级信息价值判断按 8 种触发类型(memory/models.py::TriggerType)分别定义
判断标准,而不是套用统一的新颖性/可操作性/普适性打分。每种类型对应 3 个结构化
判断维度(memory/ai_provider.py::VALUE_CRITERIA),三者全部满足才判定为
“包含可沉淀的知识”,任一不满足即在第一级被拒绝:
| 触发类型 | 说明 | 3 个判断维度 |
|---|---|---|
| user_feedback | 用户反馈:纠错/确认/偏好表达 | 态度明确、有具体正确做法、确实来自用户 |
| strategy_execution | 策略执行结果:任务闭环产出的实际效果 | 有因果链条、有量化目标/实际对比、适用条件明确 |
| environment_change | 环境变化:大促、冷启动等外部信号 | 有时间边界、来自客观观测、影响后续决策 |
| rule_update | 规则更新:合规/预算/系统规则调整 | 来自权威来源、生效范围明确、是硬性约束 |
| anomaly_pattern | 异常模式:ROI/指标显著偏离预期 | 超出偏差阈值、有可能原因、非一次性噪音 |
| performance_optimization | 性能优化:调优带来的量化增益 | 有前后对比、提升超出噪音范围、变量单一可归因 |
| cross_domain_correlation | 跨域关联:品类/渠道间的联动规律 | 跨越多个域、有统计支撑、排除混淆因素 |
| periodic_pattern | 周期性规律:时段/周/季节性规律 | 跨越完整周期、多周期重复出现、可转化为操作建议 |
| 层级 | 用途 | 写入约束 |
|---|---|---|
| L1 core_rules | 合规、预算和系统核心规则 | 非权威来源转人工审核;不可自动覆盖 |
| L2 strategy_exp | 广告主画像、成功策略、失败教训、品类规律 | 需要来源与适用条件,复杂案例由 Judge 裁决 |
| L3 realtime_env | 冷启动、ROI 异常、活动等实时信号 | 必须有工具/系统来源、观测时间与 TTL |
| L4 skill_template | 可复用策略模板 | 仅由成熟、验证通过的 L2 受控晋升 |
快速开始:本地 Python CLI
1. 安装依赖
要求 Python 3.10+:
python3 -m pip install -r requirements.txt2. 配置 LLM Provider(必需,否则无法启动)
系统的语义检索、忠实性审核、价值打分和冲突检测均依赖真实 LLM/Embedding 服务,必须先配置:
export MEMORY_LLM_API_KEY='your-secret'
export MEMORY_LLM_BASE_URL='https://aigc.sankuai.com/v1/openai/native' # 可选,默认即此值
export MEMORY_JUDGE_MODEL='gpt-4o-mini' # 可选
export MEMORY_EMBEDDING_MODEL='text-embedding-3-small' # 可选未设置 MEMORY_LLM_API_KEY 时,memory_skill.py 的任何子命令都会直接抛出 RuntimeError 并退出,不会静默降级。
3. 查看状态
python3 catclaw_skill/memory_skill.py status首次运行会在 data/lingix_memory.db 创建 SQLite 数据库,并默认写入种子数据。
4. 检索记忆
python3 catclaw_skill/memory_skill.py search "医药OTC冷启动出价策略" \
--advertiser brand_A \
--business-line medical \
--top-k 45. 写入记忆
优先使用 ingest:只需一段自然语言描述,事件分类(8 种触发类型之一)和结构化
字段抽取均由系统内部的 LLMEventClassifier 完成:
python3 catclaw_skill/memory_skill.py ingest \
"本次医药OTC冷启动计划用三阶段出价策略,目标ROI 3.0,实际做到3.4" \
--advertiser brand_A已经拿到结构化数据时(如任务系统直接返回 plan_id/roi 等字段),可以用
trigger 显式指定事件类型,跳过分类步骤:
python3 catclaw_skill/memory_skill.py trigger strategy_execution \
--advertiser brand_A \
--summary "医药OTC冷启动计划完成三周投放" \
--data '{
"plan_id":"plan_001",
"category":"医药OTC",
"business_line":"medical",
"strategy_used":"三阶段冷启动",
"target_metric":{"roi":3.0},
"actual_metric":{"roi":3.4,"cpc":2.8},
"duration_days":21
}'更多日常操作、事件字段和排障说明参见 用户手册。
作为 OpenClaw Skill 部署(无需修改 AGENTS.md)
如果不需要 npm 插件那一层 TypeScript/Node 适配(例如沙箱容器里直接部署源码),可以把 catclaw_skill/ 目录作为一个标准 Skill 接入:
# 1. 把整个项目部署到持久化目录,例如:
cp -r memory_sample ~/.openclaw/memory_sample
# 2. 把 catclaw_skill/ 链接(或复制)进 Skill 扫描目录
ln -s ~/.openclaw/memory_sample/catclaw_skill ~/.openclaw/skills/lingix-agent-memory
# 3. 配置必需的环境变量(容器环境变量面板,或 shell profile)
export MEMORY_LLM_API_KEY='...'
export MEMORY_SKILL_ROOT=~/.openclaw/memory_sampleOpenClaw 会通过 skills.load.extraDirs(默认包含 ~/.openclaw/skills)自动扫描到 catclaw_skill/SKILL.md,把其中的 description 注入系统提示词,Agent 据此判断何时调用 memory_search/memory_trigger 等命令——全程不需要编辑全局 AGENTS.md,Skill 目录本身就是能力声明的来源。完整工具说明和环境变量清单见 catclaw_skill/SKILL.md 与 catclaw_skill/REFERENCE.md。
OpenClaw 插件安装
前置条件
- Node.js 20+;
- OpenClaw
2026.5.17+; - Python 3.10+;
- Python 依赖已安装。
发布包中包含 Python 源码和 requirements.txt,但不会自动执行 pip install。安装后请在插件目录或受控虚拟环境中安装 Python 依赖。
本地开发安装
npm install
npm run plugin:build
openclaw plugins install . --dangerously-force-unsafe-install
openclaw plugins enable lingix-agent-memory插件通过 Node child_process 调用其包内的 Python CLI,因此 OpenClaw 会识别为“执行外部进程”。--dangerously-force-unsafe-install 是对此行为的显式信任确认;请只安装可信来源的发布包。
从 npm 安装
发布后使用:
openclaw plugins install @bzpovo/agent-memory --dangerously-force-unsafe-install
openclaw plugins enable lingix-agent-memory使用 openclaw plugins inspect lingix-agent-memory --json 查看安装信息;使用 openclaw plugins doctor 检查加载问题。
OpenClaw 配置
插件配置使用键 lingix-agent-memory。下例展示运行时核心配置;具体配置文件位置由 OpenClaw 部署方式决定:
{
"plugins": {
"entries": {
"lingix-agent-memory": {
"enabled": true,
"config": {
"pythonCommand": "python3",
"dataDir": "/absolute/path/to/lingix-memory-data",
"autoSeed": true,
"recallTopK": 4,
"judge": {
"enabled": true,
"baseUrl": "https://aigc.sankuai.com/v1/openai/native",
"model": "gpt-4o-mini"
},
"embedding": {
"enabled": true,
"model": "text-embedding-3-small"
}
}
}
}
}
}未设置 dataDir 时,适配层默认使用 ~/.openclaw/lingix-agent-memory/lingix_memory.db。生产环境建议指定绝对持久化路径,并纳入备份策略。
judge/embedding 字段用于覆盖网关地址和模型名(enabled: true 时生效,会被映射为 MEMORY_LLM_BASE_URL/MEMORY_JUDGE_MODEL/MEMORY_EMBEDDING_MODEL 环境变量传给 Python 子进程);两者省略或 enabled: false 时使用 Python 侧默认值,不代表禁用 LLM。
⚠️ 启用插件前必须先配置
MEMORY_LLM_API_KEY环境变量(见下文"LLM Judge 与 Embedding")。出于安全考虑,API Key 不支持通过config字段配置,只能来自宿主环境变量;未设置时,src/index.ts会在调用 Python 子进程前直接抛出错误,所有lingix_memory_*工具调用都会失败。
OpenClaw 可调用以下工具:
lingix_memory_searchlingix_memory_ingest:自由文本自动分类 + 写入,无需预先判断 8 种触发类型(推荐 Agent 优先使用)lingix_memory_trigger:需显式指定event_type+ 结构化data,适合调用方已掌握结构化字段的场景lingix_memory_statuslingix_memory_reflectlingix_memory_review
当前 OpenClaw 适配器提供显式工具调用。自动 Prompt 注入不由工具插件入口启用,建议由 Agent 提示词规定“回答前先调用
lingix_memory_search”。
LLM Judge 与 Embedding
MEMORY_LLM_API_KEY 是启动 Python 核心的必需环境变量(见前文"快速开始"第 2 步);OpenClaw 插件场景下同样需要在启动 OpenClaw 主进程前 export 好该变量,插件通过 child_process.spawn 继承父进程环境变量透传给 Python 子进程,无需在 openclaw.plugin.json 的 config 字段中重复填写密钥。
网关地址(MEMORY_LLM_BASE_URL)和模型名(MEMORY_JUDGE_MODEL/MEMORY_EMBEDDING_MODEL)可以二选一配置:
- 本地 Python CLI:直接
export对应环境变量; - OpenClaw 插件:在
config.judge/config.embedding中设置enabled: true并填写baseUrl/model,src/index.ts会将其映射为同名环境变量再传给 Python 子进程;若同时设置了环境变量和插件 config,插件 config 会覆盖继承自宿主进程的环境变量。
不要将 API Key 提交到 Git、写入 README、openclaw.plugin.json 或 SQLite 数据库。Embedding 模型名必须替换为所接入网关真实支持的模型。
记忆提取阶段接入本地 DoubtMem 模型(可选)
主 Agent 的其余任务(对话、Embedding 检索、一级价值打分、冲突检测)默认始终走 MEMORY_LLM_* 配置的网关模型;如果本地已部署训练好的 DoubtMem 忠实性判定模型(局部 GRPO / Axis-GRPO 方案,动作空间 WRITE/UPDATE/REJECT + 强制 <doubt-check> 推理链),可以让记忆提取阶段的忠实性判定单独切换到该本地模型,其余能力不受影响:
# 1. 部署 DoubtMem 模型(ms-swift/vLLM OpenAI 兼容 server,详见 ../DoubtMem/docs/USAGE.md 第 6 节)
python3 /path/to/ms-swift/swift/cli/deploy.py \
--model DoubtMem/checkpoints/doubtmem/axis_grpo_qwen3_4b_v1_8gpu/global_step_150/actor/huggingface \
--model_type qwen3 --served_model_name DoubtMem-AxisGRPO-Qwen3-4B-step150 \
--infer_backend vllm --host 0.0.0.0 --port 8005 --gpu_memory_utilization 0.85
# 2. 配置本地模型地址(其余 MEMORY_LLM_* 保持不变,继续服务主 Agent)
export MEMORY_DOUBTMEM_BASE_URL='http://localhost:8005/v1'
export MEMORY_DOUBTMEM_MODEL='DoubtMem-AxisGRPO-Qwen3-4B-step150' # 可选,默认即此值配置 MEMORY_DOUBTMEM_BASE_URL 后,DoubtMemGuard 内部使用的 Judge 会自动切换为 memory.ai_provider.DoubtMemLocalJudge(见该类 docstring),把候选记忆 + 触发事件拼装为 DoubtMem 训练时的对话/已有记忆格式,调用本地服务并解析 <doubt-check> + JSON 动作,再按规则映射为 WRITE/UPDATE/REJECT 及 source_attribution/grounding/consistency 等字段;未配置该变量时行为与之前完全一致(使用 MEMORY_JUDGE_MODEL 网关模型)。L1/L4 的硬性层级限制、以及规则先行拦截(试探性偏好、Agent 推断禁止直接写入 L1/L2)不受 Judge 来源影响,仍由 DoubtMemGuard 的确定性代码把关。
事实检测工具(
campaign_analysis/industry_benchmark/memory_search)目前只接入了走美团网关的LLMJudge,DoubtMemLocalJudge的忠实性判定完全由本地专训模型的<doubt-check>推理链完成,暂不叠加工具核验。
factuality_check 事实检测工具(可选)
LLMJudge 在 factuality_check 阶段可以调用客观工具核验候选记忆中的数值/效果结论,而不是完全依赖模型自身判断,用法:
from memory.ai_provider import LLMJudge, DefaultFactualityToolVerifier
judge = LLMJudge(provider, tool_verifier=DefaultFactualityToolVerifier(storage))触发条件(命中任一即触发):候选记忆包含具体数值、包含效果类表述(提升/下降/ROI 等)、包含时效性表述(当前/最新/近期等),或已检索到同范围的相关记忆。触发后依次尝试:
campaign_analysis:核对候选记忆引用的数值是否能在事件原始数据(event.raw_data/candidate.supporting_data)中找到依据,并根据复现次数判断是「多次复现」还是「仅单次」;memory_search:复用已检索到的相关记忆,核查候选是否与其完全重复/矛盾;industry_benchmark:核对是否有行业大盘数据支撑(本仓库未内置行业大盘数据源,默认恒为“无相关数据”)。
核验结果按以下规则调整 grounding(与 LLM 自身判断的规则叠加,工具结论优先):
| 工具核验结果 | grounding 调整 |
|---|---|
| 数值吻合且多次复现 | 升级为 grounded |
| 数值吻合但仅单次 | 维持/降为 weakly_grounded |
| 数值不符 | 降级为 unsupported |
| 无相关数据 | 维持 LLM 原判断 |
DefaultFactualityToolVerifier 只依赖系统内已有数据(不依赖外部投放数据服务/行业大盘服务);生产环境如需接入真实的投放数据/行业大盘查询服务,应实现同名方法(campaign_analysis/industry_benchmark/memory_search,参数与返回结构一致)替换默认实现。不注入 tool_verifier 时,LLMJudge 行为与引入本机制之前完全一致。
历史数据回填:
python3 catclaw_skill/memory_skill.py embed-backfill --batch-size 50示例与测试
想快速理解"一段对话如何一步步变成一条记忆",运行最简场景演示(推荐首次接触本项目时看这个):
python3 -m demo.minimal_demo该演示只用一段真实的用户纠错对话,手动串联打印第 0~4 级的每一步中间产物(自动分类抽取 → 候选记忆 → 价值判断 → 忠实性门控 → 冲突检测 → 质量评估 → 写入 → 检索验证),忠实性门控默认优先使用本地 DoubtMemLocalJudge(配置 MEMORY_DOUBTMEM_BASE_URL 后生效),未配置时自动回退网关 LLMJudge,脚本顶部注释包含完整的运行前配置说明。
运行当前能力全链路演示(覆盖更多分支场景):
python3 -m demo.current_features_demo演示会使用独立数据库 data/current_features_demo.db,覆盖 Guard 拒绝、L3 TTL、混合检索、Judge 审核、UPDATE、L2→L4 晋升、Trace 复核和向量回填。
运行测试:
python3 -m unittest discover -s tests -v
npm run plugin:validate开发与发布
npm install
npm run plugin:build
npm run plugin:validate
npm run pack:check发布前请确认:
package.json的版本号符合发布策略;openclaw.plugin.json已由npm run plugin:build更新;- Python 与插件校验均通过;
- 未提交
.env、SQLite 数据库或密钥; - npm scope
@bzpovo已具备发布权限(publishConfig.access已设为public)。
发布:
npm publish --access public目录说明
memory/ Python 记忆核心:模型、Guard、存储、反思、校验
catclaw_skill/ Python CLI 入口 + 标准 Skill 定义(SKILL.md,可被 Agent 自动发现,无需修改全局 AGENTS.md)
demo/ 可重复运行的功能演示
src/index.ts OpenClaw Tool Plugin 适配器
dist/ 编译后的 OpenClaw 插件入口
bin/ npm CLI 包装器
openclaw.plugin.json OpenClaw 插件清单
USER_MANUAL.md 用户操作手册安全与数据治理
- LLM Judge 不是安全边界;规则先行拦截(未经用户确认的 Assistant 建议、Agent 推断直写 L1/L2)、L1/L4 分层约束、数据格式和审计规则均由确定性代码执行,不受 Judge 结论影响。
- L3 实时数据默认会在 24 小时后过期;业务上需要不同生命周期时应通过事件/数据模型扩展。
- 所有高风险写入、拒绝和审核决策会记录 Trace;建议定期执行复核并关注 Guard 指标。
- SQLite 数据库包含广告策略、偏好和审计数据,生产环境应设置访问控制、备份与保留策略。
