Clawthority:为AI代理构建代码级安全护栏的插件式策略引擎
1. 项目概述:为AI代理装上“安全护栏”
如果你正在使用或开发AI代理,尤其是那些能够调用外部工具(比如读写文件、执行命令、发送邮件)的智能体,那么一个核心的焦虑点一定是:我如何确保它不会做出危险操作?无论是无意中删除了生产环境的数据库,还是未经授权向外部发送了敏感信息,这些风险都让AI代理的落地变得如履薄冰。传统的做法是“技能式安全”,也就是在给模型的提示词里苦口婆心地叮嘱:“请先检查权限”、“请确认操作安全”。但我们都清楚,这完全依赖于模型自身的“自觉性”和推理能力,一旦模型被诱导、分心或出现幻觉,这道防线就形同虚设。
Clawthority 正是为了解决这个根本性问题而生的。它不是一个“技能”,而是一个插件,一个运行在AI代理与外部工具调用路径之间的策略执行引擎。你可以把它想象成一道坚不可摧的“安检门”。当你的AI代理想要执行任何操作时,这个请求不会直接抵达工具,而是必须先经过Clawthority的审查。Clawthority会根据你预先定义好的策略规则,做出“允许”、“拒绝”或“需要人工审批”的决策。最关键的是,这个决策过程完全独立于AI模型的推理循环之外,由代码强制执行,从根本上杜绝了因模型自身问题导致的安全绕过。
简单来说,Clawthority将安全控制的主动权,从不可预测的AI模型手中,夺回到了可预测、可审计的代码层面。它为OpenClaw生态提供了一个开箱即用的、语义化的授权运行时,让开发者能够清晰地定义“我的代理能做什么”,并在边界上强制执行,同时为关键操作保留“人在回路”的最终裁决权。
2. 核心设计理念:从“请求遵守”到“强制拦截”
要理解Clawthority的价值,我们必须先厘清两种截然不同的安全范式。
2.1 技能安全 vs. 插件安全
在Clawthority出现之前,主流的安全思路是“技能安全”。它的工作模式是这样的:你在给AI代理的提示词(系统指令或上下文)中加入一系列安全规则,例如“未经用户明确确认,不得删除任何文件”。模型在思考如何完成任务时,会“看到”这些规则,并(理论上)遵守它们。
技能安全的致命缺陷:
- 依赖模型自觉性:安全与否完全取决于模型当前的理解和“心情”。一次糟糕的推理或一个精心设计的提示词注入攻击,就可能让它忽略所有规则。
- 无强制力:模型是决策者,也是执行者。它可以选择不遵守规则,而系统没有任何代码层面的机制去阻止它。
- 可观测性差:你只能看到模型最终决定调用什么工具,但无法清晰地追溯它做出这个决定时,是否考虑了安全规则,以及是如何考虑的。
Clawthority代表的“插件安全”则采用了完全不同的架构:
- 独立执行层:它作为一个独立的代码模块,物理上位于AI代理(如OpenClaw运行时)和所有工具之间。所有工具调用请求必须流经它。
- 代码强制拦截:它的决策引擎(基于Cedar策略语言)根据预定义的策略进行评估。如果策略说“不”,那么调用请求在代码层面就会被直接拦截,根本不会发送给工具执行。
- 不可绕过:因为它运行在模型的“下游”,模型本身无法绕过这个检查点。无论模型怎么想、怎么被诱导,危险调用都无法触及真实系统。
用一个简单的类比:技能安全像是在银行柜台贴一张告示“请勿抢劫”,依赖劫匪的良知;而插件安全则是在柜台前安装了一道防弹玻璃和一道安检门,无论劫匪怎么想,他都无法直接接触到柜员和现金。
2.2 语义化授权与能力系统
Clawthority的另一个精妙设计在于其“语义化”特性。传统的基于工具名称(字符串匹配)或正则表达式的授权规则非常脆弱。工具改个名字、加个别名,或者参数格式稍有变化,规则就可能失效。
Clawthority引入了一个“动作注册表”。所有工具调用在进入策略引擎前,会先被“归一化”为一个标准的动作类。例如,无论是叫delete_file、rm还是unlink的工具,只要其行为是删除文件,都会被归类到filesystem.delete这个动作类。你编写的所有安全策略,都是针对这些标准的动作类,而非具体的工具名称。这使得策略更加健壮和可维护。
更进一步,Clawthority实现了一个加密能力系统,专门用于“人在回路”场景。当高风险操作需要人工审批时,系统会生成一个审批令牌。这个令牌并非一个简单的“已批准”标志,而是与本次操作的具体内容进行密码学绑定。它包含了动作类、目标资源和请求负载的SHA-256哈希值。这意味着:
- 防篡改:如果代理在获得批准后,试图偷偷修改请求参数(例如把收款人从“A”改成“B”),哈希值就会对不上,令牌立即失效,操作会被拒绝。
- 精准授权:批准的是“向user@example.com发送内容为X的邮件”,而不是笼统的“允许发送邮件”。
- 一次性或会话性:令牌可以设计为一次性使用,用完即废;也可以在一个会话期内对同类操作有效,在安全与便利间取得平衡。
这套组合拳——代码级强制拦截、语义化策略、加密能力绑定——共同构成了Clawthority坚实的安全基础。
3. 安装、配置与快速上手
理论讲得再多,不如动手一试。Clawthority作为OpenClaw的插件,安装和集成过程非常顺畅。
3.1 环境准备与插件安装
首先,确保你的环境满足基本要求:Node.js版本 >= 18,并且已经安装并配置好了OpenClaw。Clawthority本身是一个TypeScript项目,构建后作为插件运行。
安装步骤非常简单,直接克隆到OpenClaw的插件目录即可:
# 克隆仓库到OpenClaw的插件目录 git clone https://github.com/OpenAuthority/clawthority ~/.openclaw/plugins/clawthority # 进入插件目录,安装依赖并构建 cd ~/.openclaw/plugins/clawthority npm install npm run build构建完成后,你会在dist/目录下看到编译后的JavaScript代码。接下来,需要在OpenClaw的主配置文件中注册这个插件。编辑~/.openclaw/config.json文件(如果不存在则创建),添加插件路径:
{ "plugins": ["clawthority"] }注意:这里的
"clawthority"是一个标识符,OpenClaw会在其插件目录(即你刚才克隆的~/.openclaw/plugins/)下寻找同名的目录。确保目录名称一致。
3.2 理解两种运行模式:开放与封闭
Clawthority提供了两种开箱即用的安全基线,通过环境变量CLAWTHORITY_MODE控制。理解这两种模式的区别,对正确使用至关重要。
开放模式:这是默认模式。其核心思想是“默认允许,关键禁止”。
- 策略:所有未被明确禁止的动作类,默认都是允许的。
- 安全网:同时,它内置了一个“关键禁止”列表,无条件地拦截最高风险的操作,例如
shell.exec(执行任意命令)、payment.initiate(发起支付)、credential.write(写入凭证)等。 - 适用场景:非常适合快速启动和开发测试。你可以先让代理跑起来,大部分文件读取、信息查询等低风险操作不受阻碍,同时又被保护在关键危险操作的“安全围栏”内。当你发现代理试图进行危险操作被拦截时,再逐步细化你的策略。
封闭模式:其核心思想是“默认拒绝,明确允许”。
- 策略:所有动作类,除非在策略规则中被明确标记为
permit,否则一律拒绝。 - 安全网:同样包含关键禁止列表,但在此模式下,这个列表更像是“即使你想允许,我也绝不允许”的终极底线。
- 适用场景:适用于生产环境或对安全有极高要求的场景。你需要像配置防火墙一样,仔细规划并显式地列出代理被允许做的每一件事。这提供了最强的安全保证,但前期配置工作量较大。
- 策略:所有动作类,除非在策略规则中被明确标记为
通过设置环境变量来切换模式:
# 切换到封闭模式 export CLAWTHORITY_MODE=closed # 随后启动你的OpenClaw代理 openclaw run your-agent模式在插件激活时读取,更改后需要重启OpenClaw才能生效。
3.3 编写你的第一条策略规则
Clawthority的策略规则存储在data/rules.json文件中,支持热重载(约300毫秒生效)。规则文件是一个JSON数组,每条规则定义了一个决策。
规则的核心结构如下:
{ "effect": "permit", // 或 "forbid" "action_class": "filesystem.read", "resource": "optional_resource_identifier", "match": "optional_string_pattern", "priority": 50 // 数字,越高优先级越高 }让我们从几个实际例子开始:
示例1:允许读取文件,但禁止删除
[ { "effect": "permit", "action_class": "filesystem.read" }, { "effect": "forbid", "action_class": "filesystem.delete", "priority": 90 // 赋予较高优先级,确保不会被低优先级的permit规则覆盖 } ]在开放模式下,第一条规则是冗余的(因为默认允许),但显式声明可以让策略更清晰。第二条规则则明确禁止了删除操作。
示例2:禁止代理调用某个特定的自定义工具假设你有一个名为send_alert_to_slack的工具,你希望完全禁止代理使用它,无论它被归类为什么动作类。
[ { "effect": "forbid", "resource": "tool", "match": "send_alert_to_slack" } ]这里使用了resource和match字段进行更细粒度的匹配。resource: “tool”表示匹配工具资源,match值支持通配符。
示例3:在封闭模式下,构建白名单在封闭模式下,你必须为所有需要的操作开绿灯。
[ { "effect": "permit", "action_class": "filesystem.read" }, { "effect": "permit", "action_class": "web.get" }, { "effect": "permit", "action_class": "llm.complete" } // 注意:没有出现在此列表中的动作类,将被默认拒绝。 ]编写完规则后,保存data/rules.json文件。你会在OpenClaw的日志中看到类似[clawthority] │ Policy reloaded from disk的提示,表示新规则已生效。
现在,当你运行代理时,任何被禁止的操作都会在日志中被清晰标记并拦截:
[clawthority] │ DECISION: ✕ BLOCKED (cedar/forbid priority=100 rule=action:shell.exec) — Shell execution is unconditionally forbidden同时,这次决策的完整详情(包括动作类、目标、决策原因、时间戳等)会被以结构化的JSON格式追加到data/audit.jsonl文件中,供后续审计和分析。
4. 深入核心:动作注册表与策略评估流程
要熟练运用Clawthority,必须深入理解其内部的两个核心机制:动作注册表如何对工具调用进行“翻译”,以及两阶段的策略评估管道如何工作。
4.1 动作注册表:从工具名到语义动作
动作注册表是Clawthority的“翻译官”。它的任务是将千变万化的工具调用请求,映射到一组有限且定义明确的标准动作类上。这是实现语义化授权的基石。
一个工具调用进入Clawthority时,携带的是原始信息,比如工具名delete_file和参数{“path”: “/tmp/test.txt”}。动作注册表会执行以下归一化流程:
- 名称匹配:首先在注册表中查找
delete_file这个工具名对应的标准动作类。注册表预定义了大量常见工具及其别名。 - 参数分析:在某些情况下,还会分析参数内容。例如,一个名为
write_file的工具,如果其path参数是一个URL(如http://example.com/upload),它可能会被重新分类为web.post动作,因为其语义更接近HTTP POST请求,而非本地文件写入。 - 风险升级:对于
shell.exec或某些写入操作,如果参数中包含Shell元字符(如;、|、>)或可疑模式,其风险等级可能会被从high提升到critical,触发更严格的检查。 - 回退处理:如果工具名在注册表中完全找不到,它会被归类到
unknown_sensitive_action。这是一个非常重要的安全特性:在开放和封闭两种模式下,未知动作默认都是被关键禁止的。这迫使开发者必须显式地为新工具注册别名或审查其安全性,避免了“未知即放行”的隐患。
下表列出了部分核心动作类及其含义:
| 动作类 | 风险等级 | 默认HITL | 典型工具别名示例 | 说明 |
|---|---|---|---|---|
filesystem.read | 低 | 无 | read_file,cat,view | 读取文件内容,通常风险较低。 |
filesystem.write | 中 | 每次请求 | write_file,edit,append | 修改或创建文件。可能覆盖重要数据。 |
filesystem.delete | 高 | 每次请求 | delete_file,rm,unlink | 删除文件,可能导致数据丢失。 |
shell.exec | 高 | 每次请求 | exec,bash,run_command | 执行任意Shell命令,权限极高。 |
communication.external.send | 高 | 每次请求 | send_email,post_to_slack | 向外部系统发送信息,可能泄露数据。 |
web.post | 中 | 每次请求 | http_post,axios.post | 发起HTTP POST请求,可能修改远程状态。 |
payment.initiate | 关键 | 每次请求 | stripe_charge,transfer_funds | 涉及资金交易,风险最高。 |
credential.write | 关键 | 每次请求 | set_api_key,store_password | 写入新的凭证或密钥。 |
unknown_sensitive_action | 关键 | 每次请求 | (所有未知工具) | 未知工具的兜底分类,强制安全处理。 |
实操心得:在开发自定义工具时,花点时间查阅完整的动作注册表文档,为你工具的功能选择最贴切的动作类别名。这能确保你的安全策略精准生效。如果工具行为复杂,考虑将其拆分为多个更细粒度的工具,分别对应清晰的动作类。
4.2 两阶段评估管道:从能力检查到策略引擎
当一个工具调用被归一化为ExecutionEnvelope(执行信封,包含动作类、目标、负载哈希等)后,它将进入一个两阶段的评估管道。这个管道是串行的,任何一阶段拒绝,整个调用即被拒绝。
阶段一:能力门禁这是第一道,也是最快的一道检查。它主要处理与预先批准的权限相关的情况。
- 低风险绕过:对于标记为极低风险(如
llm.complete)的动作,可能直接允许,以降低开销。 - 验证能力令牌:如果本次调用关联了一个有效的“人在回路”批准令牌(Capability Token),本阶段会校验其有效性:
- 令牌是否匹配:核对令牌绑定的
(action_class, target, payload_hash)是否与当前请求完全一致。 - 令牌是否在有效期内:检查TTL(生存时间)。
- 令牌类型:是单次使用(
approve_once)还是会话级(session)?单次令牌在使用后即被消耗。
- 令牌是否匹配:核对令牌绑定的
- 快速拒绝:如果请求来自不可信源且涉及高风险动作,可能在此阶段就直接拒绝,无需进入更复杂的策略引擎。
阶段二:约束执行引擎如果请求通过了能力门禁,或者本就不需要/没有能力令牌,则进入核心的策略评估阶段。
- 路径保护检查:针对文件系统操作,检查目标路径是否在保护列表内(如
~/.ssh/,/etc/,*.env等)。尝试访问这些路径的操作会被直接拒绝。 - 可信域检查:针对外部通信操作(如
communication.external.send),检查目标地址(如邮箱、URL)是否在可信域白名单内。 - 策略引擎评估:调用底层的Cedar策略引擎,根据
data/rules.json中定义的规则,对当前请求的action_class和resource等进行最终评估,得出permit或forbid的结论。规则按优先级排序,高优先级规则覆盖低优先级规则。
人在回路触发在整个管道中,如果某个动作类被配置为需要人工审批(hitl: per_request),且当前请求没有有效的能力令牌,那么管道会在此处暂停。
- 系统会通过配置的通道(如Telegram Bot)向预设的审批人发送审批请求,包含操作详情和一次性批准链接。
- 同时,向代理返回一个
deny决策,原因字段为pending_hitl_approval。 - 审批人点击链接批准后,系统会生成一个与该次请求绑定的能力令牌。
- 代理需要重新发起完全相同的请求(这通常需要代理工作流具备重试或等待逻辑),这次请求携带了有效令牌,从而通过阶段一的能力门禁,最终被允许执行。
这个两阶段管道确保了安全检查既高效(阶段一快速处理已知安全状态)又全面(阶段二进行深度策略分析),同时无缝集成了人工监督。
5. 高级配置与“人在回路”集成
Clawthority的强大之处在于其灵活且强大的配置能力,尤其是与外部通信工具集成的“人在回路”功能,为高风险操作提供了最终的安全阀。
5.1 多层级配置管理
Clawthority的配置来自三个层面,优先级和热重载能力各不相同:
| 配置层面 | 位置 | 热重载 | 说明 |
|---|---|---|---|
| 环境变量 | 系统环境变量 | 否(需重启) | 控制核心行为模式、功能开关和通信密钥。例如CLAWTHORITY_MODE,TELEGRAM_BOT_TOKEN,SLACK_BOT_TOKEN。 |
| 策略规则 | data/rules.json | 是 (~300ms) | 定义具体的允许/禁止规则。这是最常修改的部分,支持动态更新。 |
| HITL策略 | hitl-policy.yaml | 是 (~300ms) | 定义哪些动作类需要人工审批,以及审批的详细参数(如TTL)。 |
典型环境变量配置示例:
# 设置运行模式为封闭模式 export CLAWTHORITY_MODE=closed # 设置Telegram Bot Token用于发送审批通知 export TELEGRAM_BOT_TOKEN=your_bot_token_here export TELEGRAM_CHAT_ID=your_personal_chat_id_here # 启用调试日志,了解更多内部决策过程 export CLAWTHORITY_LOG_LEVEL=debughitl-policy.yaml配置示例:
# 定义哪些动作类需要人工介入,以及如何介入 policies: - action_class: "filesystem.delete" hitl: mode: "per_request" # 每次请求都需要审批 ttl_seconds: 120 # 批准令牌有效期为120秒 consume: "approve_once" # 令牌使用一次后即失效 channels: ["telegram"] # 通过Telegram通知 - action_class: "communication.external.send" hitl: mode: "per_request" ttl_seconds: 300 consume: "session" # 令牌在本会话内对同类操作有效 channels: ["slack"] # 通过Slack通知 - action_class: "shell.exec" hitl: mode: "per_request" ttl_seconds: 60 # 执行命令的审批有效期更短 consume: "approve_once" channels: ["telegram", “slack"] # 多通道通知,确保触达5.2 搭建Telegram审批机器人
“人在回路”功能极大地提升了安全性,而Telegram是设置起来最快捷的通道之一。
- 创建Bot:在Telegram中搜索
@BotFather,发送/newbot指令,按提示创建新机器人,最终你会获得一个Bot Token(形如1234567890:ABCdefGhIJKlmNoPQRsTUVwxyZ)。 - 获取Chat ID:与你刚创建的Bot发起对话,发送任意消息(如
/start)。然后,在浏览器中访问以下URL(将<YOUR_BOT_TOKEN>替换为你的Token):https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates在返回的JSON中,找到message.chat.id字段,这个数字就是你的Chat ID。 - 配置Clawthority:将获取到的Token和Chat ID设置为环境变量。
export TELEGRAM_BOT_TOKEN=1234567890:ABCdefGhIJKlmNoPQRsTUVwxyZ export TELEGRAM_CHAT_ID=987654321 - 测试:配置完成后,重启OpenClaw。当代理触发一个需要审批的操作(如尝试删除文件)时,你的Telegram就会收到一条格式清晰的消息:
点击Approve链接即可批准该次操作。链接指向Clawthority内置的HTTP审批端点(默认运行在本地)。🛡️ Clawthority 需要您的审批 Action: filesystem.delete Target: /tmp/important_log.txt Summary: 删除文件 /tmp/important_log.txt Expires: 2023-10-27T10:30:00Z Approve: https://your-approval-endpoint/approve/01HJP6... Deny: https://your-approval-endpoint/deny/01HJP6...
注意事项:生产环境中,审批链接应当通过反向代理(如Nginx)配置HTTPS,并设置适当的访问控制,避免被未授权访问。
hitl-policy.yaml中的ttl_seconds不宜设置过长,通常60-300秒是合理范围,以平衡安全与操作便利性。
5.3 审计日志分析与故障排查
所有决策,无论是允许、拒绝还是等待审批,都会被详细记录到data/audit.jsonl文件。这是一份按行分隔的JSON日志,是安全审计和问题排查的黄金数据。
一条典型的拒绝日志:
{ "timestamp": "2023-10-27T10:15:00.123Z", "decision": "deny", "stage": "cedar/forbid", "action_class": "shell.exec", "target": "rm -rf /", "rule": "action:shell.exec", "priority": 100, "mode": "open", "deny_reason": "Shell execution is unconditionally forbidden", "latency_ms": 5, "context_hash": "a1b2c3d4..." }关键字段解读:
stage: 标识决策发生在哪个阶段(如capability_gate,cedar/permit,cedar/forbid),帮助定位问题。rule: 触发此次决策的具体规则标识符。priority: 规则的优先级。mode: 决策时的运行模式(open或closed)。deny_reason: 人类可读的拒绝原因,非常直观。
常见问题排查思路:
代理所有操作都被拒绝?
- 检查模式:首先确认
CLAWTHORITY_MODE环境变量。如果在closed模式下,你必须显式添加permit规则。 - 检查规则文件:确认
data/rules.json格式正确,没有语法错误。可以尝试暂时移除所有自定义规则,看是否恢复默认(开放)行为。 - 查看审计日志:日志中的
deny_reason和rule字段会明确指出被哪条规则拦截。
- 检查模式:首先确认
“人在回路”通知未收到?
- 检查Token和Chat ID:确认
TELEGRAM_BOT_TOKEN和TELEGRAM_CHAT_ID环境变量设置正确,且Bot已启动并与用户对话。 - 检查网络:确认运行Clawthority的服务器可以访问Telegram API。
- 检查HITL策略:确认
hitl-policy.yaml中为对应动作类正确配置了channels。
- 检查Token和Chat ID:确认
自定义工具被归类为
unknown_sensitive_action并被禁止?- 这是预期行为,是安全特性。你需要为你的工具在Clawthority的代码中注册动作别名,或者编写一条针对该工具名称的显式规则。
- 临时方案:在
data/rules.json中添加一条针对该工具名的permit规则(需谨慎评估风险)。 - 长期方案:向Clawthority项目提交Pull Request,为你的工具添加标准的动作类映射。
Clawthority的设计哲学是“默认安全”,因此在遇到配置问题时,行为往往会偏向于“拒绝”而非“允许”。耐心查看审计日志,理解每条决策背后的规则,是驾驭这套系统的关键。随着你对动作类和规则引擎越来越熟悉,你将能构建出既安全又高效的AI代理授权策略。
