上周在掘金热榜看到有人用 OpenClaw 搭了 11 个 AI Agent 还能自我进化,我心动了,立马上手折腾。结果第二天就翻车——给一个 Agent 配了文件读写的 Skill,它把另一个 Agent 的工作目录给清了。排查了半天才发现是权限控制没设对,OpenClaw 默认的权限策略比我想象的宽松得多。
OpenClaw 的权限控制通过 claw.permissions.yaml 配置文件实现,核心是「角色-技能-资源」三层绑定模型。你需要为每个 Agent(或 Agent 组)定义角色,再把 Skills 的调用权限和可访问资源精确绑定上去。没配的话,默认是 allow-all,生产环境下这很危险。
先说结论
| 配置项 | 作用 | 不配的后果 |
|---|---|---|
roles | 定义 Agent 角色 | 所有 Agent 共享全局权限 |
skills.allow | 控制可调用的 Skills 列表 | Agent 能调用任意 Skill |
resources.scope | 限制文件/API/数据库访问范围 | Agent 可读写任意路径 |
execution.sandbox | 是否开启沙箱执行 | 代码直接在宿主环境跑 |
audit.log | 操作审计日志 | 出事了没法追溯 |
我现在的做法:先全部 deny,再逐个 allow,别偷懒用默认配置。
环境准备
你需要:
- OpenClaw CLI 最新版(阿里算力支持后性能好了不少)
- Python 3.11+
- 一个支持 OpenAI 协议的 API(后面代码会用到)
# 安装 OpenClaw CLI
pip install openclaw --upgrade
# 确认版本(2026年4月最新)
openclaw --version
# openclaw 2.3.x
# 初始化项目
openclaw init my-agents
cd my-agents
初始化完你会看到这个目录结构:
my-agents/
├── claw.config.yaml # 主配置
├── claw.permissions.yaml # 权限配置(重点)
├── skills/ # Skills 目录
├── agents/ # Agent 定义
└── logs/ # 审计日志
方案一:基于角色的静态权限配置
最基础也最稳的方案。在 claw.permissions.yaml 里手动定义角色和权限:
# claw.permissions.yaml
version: "2.0"
default_policy: deny # 重要!默认拒绝一切
roles:
reader:
description: "只读分析 Agent"
skills:
allow:
- "web_search"
- "file_read"
- "data_analysis"
deny:
- "file_write"
- "shell_execute"
- "api_call"
resources:
file_system:
read: ["./data/*", "./reports/*"]
write: []
network:
allow_domains: ["api.ofox.ai", "arxiv.org"]
deny_domains: ["*"]
execution:
sandbox: true
timeout_seconds: 30
max_memory_mb: 512
writer:
description: "内容生成 Agent"
skills:
allow:
- "web_search"
- "file_read"
- "file_write"
- "llm_call"
deny:
- "shell_execute"
- "db_query"
resources:
file_system:
read: ["./data/*", "./templates/*"]
write: ["./output/*"] # 只能写 output 目录
network:
allow_domains: ["api.ofox.ai"]
execution:
sandbox: true
timeout_seconds: 60
max_memory_mb: 1024
admin:
description: "管理型 Agent,权限最大但也要限制"
skills:
allow: ["*"]
deny: ["shell_execute"] # 就算是 admin 也别给 shell
resources:
file_system:
read: ["**/*"]
write: ["./output/*", "./config/*"]
network:
allow_domains: ["*"]
execution:
sandbox: true
timeout_seconds: 120
# 把角色绑定到具体 Agent
agent_bindings:
- agent_id: "research-agent-01"
role: reader
- agent_id: "content-agent-01"
role: writer
- agent_id: "orchestrator"
role: admin
配完之后验证一下:
# 检查权限配置是否合法
openclaw permissions validate
# 模拟某个 Agent 的权限(超好用的调试命令)
openclaw permissions simulate --agent research-agent-01 --action file_write --target ./data/test.txt
# 输出: DENIED - agent 'research-agent-01' (role: reader) has no write permission to ./data/
simulate 命令帮我省了无数调试时间,每次改完权限都跑一遍。
方案二:动态权限 + LLM 驱动的权限申请
这是 OpenClaw 2.3 新加的功能,适合多 Agent 协作场景。Agent 可以在运行时向 Orchestrator 申请临时权限,审批逻辑可以用 LLM 来判断。
先在配置里开启动态权限:
# claw.permissions.yaml 追加
dynamic_permissions:
enabled: true
approval_agent: "orchestrator" # 谁来审批
approval_mode: "llm" # auto / manual / llm
llm_config:
model: "claude-sonnet-4.6"
base_url: "https://api.ofox.ai/v1"
approval_prompt: |
你是权限审批系统。Agent {requester} (角色: {role}) 请求以下权限:
- 操作: {action}
- 目标: {target}
- 理由: {reason}
请判断是否批准。只回复 APPROVE 或 DENY,并说明理由。
max_grant_duration: 300 # 临时权限最长5分钟
audit: true
然后在 Agent 代码里申请权限:
import openclaw
from openai import OpenAI
# 初始化 OpenClaw Agent
agent = openclaw.Agent(
agent_id="research-agent-01",
config_path="./claw.config.yaml"
)
# 正常操作:读文件(有权限,直接过)
data = agent.skills.file_read("./data/report.csv")
# 需要写文件但没权限,发起动态申请
try:
agent.skills.file_write("./output/summary.txt", content=summary)
except openclaw.PermissionDenied as e:
# 自动发起权限申请
grant = agent.request_permission(
action="file_write",
target="./output/summary.txt",
reason="需要保存分析摘要到输出目录"
)
if grant.approved:
# 拿到临时权限,有效期内可以写
with grant:
agent.skills.file_write("./output/summary.txt", content=summary)
# grant 过期自动回收
else:
print(f"权限被拒绝: {grant.deny_reason}")
这里的 LLM 审批调用我用的是 ofox.ai 的聚合接口。ofox.ai 是一个 AI 模型聚合平台,一个 API Key 可以调用 Claude Opus 4.6、GPT-5、Kimi K2.5 等 50+ 模型,支持 OpenAI 协议兼容,不用改代码就能切换模型。审批这种轻量任务用 Sonnet 就够了,成本很低。
整个权限申请的流程长这样:
sequenceDiagram
participant A as Research Agent
participant O as Orchestrator
participant L as LLM (审批)
participant R as 资源
A->>R: file_write("./output/summary.txt")
R-->>A: PermissionDenied
A->>O: request_permission(action, target, reason)
O->>L: 审批 prompt + 上下文
L-->>O: APPROVE / DENY
alt 批准
O-->>A: TemporaryGrant(300s)
A->>R: file_write (带临时令牌)
R-->>A: Success
Note over A,R: 300s后令牌自动失效
else 拒绝
O-->>A: DenyReason
end
踩坑记录
坑 1:default_policy 不写等于 allow-all
这个最坑。claw.permissions.yaml 里如果没显式写 default_policy: deny,OpenClaw 默认是 allow-all。我第一次部署就是漏了这行,导致 reader 角色的 Agent 能执行 shell 命令。
永远在第一行写 default_policy: deny。
坑 2:通配符路径的坑
# 你以为这样是只允许读 data 目录
read: ["./data/*"]
# 但实际上 ./data/subdir/secret.txt 也能读到
# 因为 * 匹配任意深度
# 正确做法:如果只想允许一级目录
read: ["./data/*.csv", "./data/*.json"]
OpenClaw 的通配符 * 是递归匹配的(跟 gitignore 的 ** 一个意思),这个行为跟大多数人的直觉不一样。文档里有写,但藏在一个不起眼的 footnote 里。
坑 3:sandbox 模式下的 Python 包限制
开了 sandbox: true 之后,Agent 执行的 Python 代码只能用白名单里的包。默认白名单很短:
# 如果你的 Skill 用了 pandas 但报 ImportError
# 需要在 sandbox 配置里加白名单
execution:
sandbox: true
allowed_packages:
- "pandas"
- "numpy"
- "requests"
- "json"
- "csv"
我的 data_analysis Skill 用了 pandas,sandbox 里跑直接报错,加了白名单才好。
坑 4:微信端打通后的权限同步
OpenClaw 最近打通了微信端(安卓/iOS 都支持),但微信端创建的 Agent 默认不继承服务端的权限配置,需要手动开启同步:
openclaw sync permissions --target wechat --agent-group all
不然微信端的 Agent 还是 allow-all。手机上随手创建的 Agent 跑起来毫无限制,想想就可怕。
我的最终权限配置策略
跑了两周多 Agent 协作之后,总结出一套还算稳的策略:
- 全局 deny,逐个 allow —— 多花 10 分钟配权限,少花 10 小时修数据
- sandbox 必开 —— 哪怕性能损失 10-15%,也开
- 审计日志必开 ——
audit.log: true,出了问题能回溯 - 动态权限用 LLM 审批 —— 比纯规则灵活,比纯人工快
- 每周跑一次
openclaw permissions audit—— 扫描所有 Agent 实际使用了哪些权限,帮你收缩过宽的配置
# 权限审计:找出过度授权的 Agent
openclaw permissions audit --output ./reports/permission-audit.json
# 输出示例:
# agent 'content-agent-01' has 'web_search' permission but never used it in 7 days
# Suggestion: remove 'web_search' from role 'writer'
小结
OpenClaw 的权限控制说复杂也不复杂,核心就是那个 claw.permissions.yaml。但默认配置太宽松这个设计确实坑,尤其是阿里算力介入之后用户量涨得快,新手很容易裸奔上线。
先花 20 分钟把权限配死,再慢慢按需放开。别学我,等 Agent 把文件删了才想起来配权限。