OpenClaw 本地记忆落地与无审批能力边界
#OpenClaw #本地Embedding #执行审批 #最小权限
记录 OC-21 的最终结果:恢复 Web 检索与容器网络,部署纯本地
embedding,并重新评估 OpenClaw 在不弹出 exec 审批时能否覆盖日常使用。
相关笔记:《OpenClaw 后续功能规划》 ·
《OpenClaw 配置续集》 ·
《OpenClaw Exec 审批与生命周期治理》 ·
《N100 安全事件响应与 fail2ban 加固》 ·
《OpenClaw 微信安全下载体系:确定性 Gate 与 qB 隔离》
一、这轮解决了什么
1. Web 检索与代理恢复
替换过期代理节点后,清理了重复导入项,并把 Docker 网桥使用的代理
forwarder 从临时 Python 进程改为受 systemd 管理的用户服务。DuckDuckGo
插件完成两组独立合成检索,web_fetch 也通过公开网页验收。
Node 24 需要显式启用环境代理。微信 API 走代理,而局域网 llama-server
使用 NO_PROXY 中的精确主机 192.168.2.10 直连。这里不能只依赖192.168.2.0/24:Node 的代理绕过匹配与 curl 不完全相同。
另一个容易忽略的运行时条件是 net.ipv4.ip_forward。配置文件虽写着1,运行值一度为 0,导致 Docker 网桥无法访问局域网模型服务。恢复转发后,容器内模型列表与合成推理均返回 HTTP 200。
2. 本地记忆索引上线
生产 OpenClaw 保持 2026.6.10,不升级主程序,也不修改 bundle。派生镜像只加入同版本官方 llama-cpp embedding provider 和对应 Linux x64
运行时;模型文件经过大小与 SHA-256 核对。
上线前先在隔离状态目录使用单个合成 marker 验证:
-
provider 为
local; -
fallback 为
none; -
768 维向量可写入并检索;
-
合成数据不接触真实记忆。
生产只向现有插件 allowlist 增加精确 ID llama-cpp。最终三套真实索引为:
| Agent | 文件 | Chunks | 状态 |
|---|---|---|---|
| main | 22 | 264 | valid |
| download | 19 | 89 | valid |
| heartbeat | 18 | 118 | valid |
三套索引均为 dirty=false、embedding probe 成功、扫描问题为 0。私人记忆没有发送到云端。
3. 微信凭据文件与回滚链
微信 context-token 文件收紧为 0600,父目录为 0700;容器重建后权限没有反弹。配置、旧镜像和三套 SQLite 索引都在变更前创建受限备份。
首次生产切换发现 llama-cpp 不在插件 allowlist 时,没有绕过策略继续索引,而是自动恢复旧配置和旧镜像。取得仅增加该精确 ID 的授权后才重新执行完整流程。
二、当前“不需要 exec 审批”可以完成什么
生产审批基线统一为:
1 | security = allowlist |
main 与 heartbeat 只有一个精确、零参数的只读健康快照入口:
1 | /home/node/tools/openclaw-health-snapshot |
download 没有 exec allowlist 条目。这个基线不是“什么都不能做”,而是把无需 shell 的能力和需要 shell 的能力明确分开。
已覆盖
| 场景 | 无 exec 审批 | 说明 |
|---|---|---|
| WebChat / 微信日常对话 | 是 | 使用本地主模型,保留既有 fallback |
| Web 搜索与公开网页读取 | 是 | DuckDuckGo 与 web_fetch 已验收 |
| 本地长期记忆检索 | 是 | 三个 agent 均使用纯本地 embedding |
| Memory Dreaming | 是 | 定时任务最近状态正常 |
| 系统健康摘要 | 是 | 只允许固定健康快照,不开放通用 shell |
| 只读邮件摘要 | 基本覆盖 | 六项 cron 中大多数最近运行正常;一次失败归类为网络问题,而非审批拒绝 |
| 普通消息与文件理解 | 是 | 不涉及宿主机命令时不经过 exec 审批 |
这已经覆盖“聊天、查资料、回忆上下文、接收通知、查看健康状态”这一类高频日常使用。
有条件覆盖
| 场景 | 当前限制 |
|---|---|
| 邮件读取 | 插件和网络正常时可用;仍需继续观察定时任务稳定性 |
| 本地模型服务 | llama-server 正常运行时体验完整;自动唤醒尚未启用 |
| 文件操作 | Agent 工作区内的普通工具不等于宿主机任意路径权限 |
| 云端 fallback | 可用但会产生隐私边界变化,不应把私人内容默认外发 |
明确不覆盖,也不应直接免审批
-
任意 shell、SSH、Docker 管理和系统服务重启;
-
修改 OpenClaw、代理、模型路由或系统配置;
-
安装软件、升级镜像、下载并执行未知代码;
-
删除下载、覆盖文件、发送邮件等不可逆或外发动作;
-
读取工作区外的敏感文件或扩大网络/插件 allowlist。
这些操作继续要求审批是正确的安全边界,不应为了“日常无弹窗”而放开通用bash、ssh 或路径通配符。
三、是否已经覆盖日常使用
结论是:覆盖了信息型日常使用,但没有覆盖操作型日常使用。
如果日常需求主要是:
-
微信或 WebChat 对话;
-
查公开资料;
-
使用本地记忆;
-
收取摘要和健康报告;
那么当前系统已经够用,而且比扩大 shell 权限更安全。
如果期望 OpenClaw 无人值守地管理下载、发送邮件、重启模型或修复服务,当前仍不完整。缺口不应通过“允许任意命令”解决,而应继续增加窄入口。
四、建议的后续更新
P0:恢复性与外发保护
-
开启邮件发送显式确认。 当前两个邮件插件的
requireExplicitSendConfirmation都是false。应改为true,把
“读取摘要”和“向外发送”拆成不同风险级别。 -
固化 IP forwarding 运行时检查。 配置文件已有
ip_forward=1,但仍出现运行值漂移。健康快照应检查实际 sysctl;Docker 或网络服务启动后若不是 1,应告警而不是静默失去 LAN 路由。 -
保证 forwarder 无人登录也能启动。 当前用户服务虽然 enabled,但
Linger=no。可选择启用该用户的 linger,或把 forwarder 改为受限
system service;两者都需要一次管理员级变更和重启验收。
P1:按操作增加窄入口
-
下载管理专用 wrapper。 为 list/status/pause/resume 分别设计固定参数 schema;删除任务继续要求人工确认。download agent 不获得通用
shell。 -
邮件读取专用入口。 将“列未读、生成摘要”做成无参数或有限参数的只读 wrapper;发送、移动、删除邮件保持确认。
-
模型服务 handoff。 继续使用已有 controller 的
PrepareStop / PrepareStart / RestoreLocal闭环。先完成最小权限和失败回滚审查,再考虑把 Guardian 从 dry-run 改为真实动作。
P2:审批生命周期缺陷
隔离源码分析确认:有效审批等待和 blocked-tool 自动中止使用两套互不关联的生命周期。长时间等待审批可能先被卡死恢复逻辑中止。
正确修复不是增大全局超时,也不是让所有 exec 永不回收,而是给匹配的
session/run/tool-call 注册有明确过期时间的“合法等待”信号;决议、过期、重启和工具结束时必须清除。修复进入生产前仍应走上游式窄 patch 和隔离测试。
五、最终边界
当前最佳策略不是追求“完全无审批”,而是:
1 | 信息获取与只读健康检查 → 无审批 |
这套边界已经适合把 OpenClaw 当作日常信息助手使用。阶段结束后,邮件外发确认、下载专用 wrapper、模型 handoff 核心闭环和 forwarder linger 均已完成对应的窄范围验收;微信下载的确定性 Gate 另见《OpenClaw 微信安全下载体系:确定性 Gate 与 qB 隔离》。
后续真实使用又暴露出另一层可靠性问题:上下文压缩可能失败,维护型 session reset
可能与活动请求竞态,错误提示过于笼统,且 fallback 是否适用取决于错误类别和隐私边界。这些不通过扩大 shell、审批或全局超时解决,统一转入 OC-25“日常可靠性收口”。近期 desktop GPU 会被游戏占用,llama-server 由用户手动关闭;Guardian 仍保持
dry-run,不自动拉起。公开普通请求与私人内容在本地模型离线时必须采用不同的 fallback
策略。
