配置实战:tools.allow与tools.deny权限控制指南)
1. OpenClaw 工具权限失控的真实场景与 tools.allow/tools.deny 是什么如果你刚把 OpenClaw 跑起来大概率会遇到一个很微妙的问题代理好像什么都能干。它能读文件、能跑 shell、能开浏览器、能发消息甚至能定时任务。功能多是好事但当你把它接到真实项目里尤其是多人共用或者跑在服务器上时这种“全权限”状态就变成了风险。我见过最典型的情况是一个只负责整理文档的代理因为没限制工具顺手把工作区里的配置文件改了还执行了一条rm命令。事后排查才发现问题不在模型而在openclaw.json里根本没配工具白名单。OpenClaw 的工具系统Tools本质上是一套“能力清单”。代理能调用哪些工具不是模型自己决定的而是由配置在请求发往模型提供商之前就裁剪好的。也就是说tools.allow和tools.deny控制的是“模型能看到哪些工具”而不是“模型想不想用”。这一点非常关键因为很多权限问题其实在请求发出前就能被拦住。tools.allow是白名单tools.deny是黑名单两者同时存在时deny 优先。匹配时不区分大小写支持*通配符*表示所有工具。还有一个容易踩的坑如果tools.allow里只写了未知或未加载的插件工具名OpenClaw 会记录警告并忽略整个允许列表目的是让核心工具保持可用。这个设计很贴心但也意味着你写错工具名时白名单可能“静默失效”。除了 allow/deny还有tools.profile作为基础允许列表它在 allow/deny 之前应用。可选的 profile 有minimal、coding、messaging、full。比如coding会展开成group:fs、group:runtime、group:sessions、group:memory、image这些组。代理级还能用agents.list[].tools.profile覆盖全局设置。再往细里说tools.byProvider可以针对特定提供商或单个provider/model进一步缩小工具集。它的应用顺序是基础 profile → byProvider → allow/deny。所以 byProvider 只能缩小不能放大。这个顺序决定了你排查权限问题时的思路先看 profile再看 byProvider最后看 allow/deny。工具组group:*是写配置时的好帮手。group:runtime包含 exec、bash、processgroup:fs包含 read、write、edit、apply_patchgroup:sessions包含会话相关的一整套group:memory、group:web、group:ui、group:automation、group:messaging、group:nodes、group:openclaw各有对应范围。用组来写白名单比一个个列工具名更不容易漏。还有一个容易被忽略的点工具是通过两个并行渠道暴露给代理的——系统提示文本和工具模式发给模型 API 的结构化函数定义。如果某个工具没出现在这两者中模型根本无法调用它。所以 allow/deny 生效后你不仅会在行为上看不到该工具在请求体里也找不到它的 schema。这就是为什么验证时要同时看配置和实际请求。适合谁读这篇如果你正在用 OpenClaw 做自动化、接消息渠道、跑定时任务或者准备把代理放到共享环境里那工具权限配置就是必须掌握的一环。下面我会从openclaw.json的实际写法开始一步步给出可复制的片段、验证命令和排错方法。2. TaoToken 前置准备Base URL、API Key 与 Model ID 三件套在讲工具权限之前得先把模型接入这条链路打通。因为 allow/deny 裁剪的是“发给模型提供商的工具列表”如果模型本身没接上你根本看不到工具被裁剪的效果。我用的是 TaoToken 作为模型接入层它的 API 地址是https://taotoken.net/api官网是https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。注意 API 地址不带 UTM 参数直接写https://taotoken.net/api就行。接入需要三件套Base URL、API Key、Model ID。Base URL 就是上面那个 API 地址API Key 在控制台的 API Keys 页面创建地址是https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewriteModel ID 则取决于你想用的模型可以在模型对话页面确认地址是https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite。如果你用的是 Claude Code 这类编码工具TaoToken 也提供了对应的接入文档地址是https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite。长期跑编码或 Agent 任务的话可以看看 Coding Plan地址是https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite。在 OpenClaw 里模型配置通常写在openclaw.json的models或providers段。一个最小可用的配置片段长这样{ providers: { taotoken: { baseUrl: https://taotoken.net/api, apiKey: sk-你的Key, models: { default: { id: claude-sonnet-4-20250514, provider: taotoken } } } } }这里要注意baseUrl必须写完整不要漏掉/api。apiKey建议用环境变量注入不要硬编码在文件里。Model ID 要和你实际能用的模型一致写错了会在请求时返回模型不存在的错误。配置好之后先别急着配工具权限先用一个最简单的请求验证模型能通。可以用openclaw的 CLI 跑一次对话或者直接看网关日志里有没有成功的响应。如果这一步就报 401那说明 Key 有问题如果报模型不存在那就是 Model ID 写错了。把这三件套确认无误后面的工具权限配置才有意义。另外提醒一句TaoToken 是模型接入服务不是编辑器替代品也不要用它去直连生产数据库。工具权限配置的目的是让代理在可控范围内工作而不是给它开无限权限。这个边界要一开始就划清楚。3. 可复制的 openclaw.json 工具权限配置片段这一节是重点我会给出几个可以直接复制到openclaw.json里的配置片段覆盖从全局白名单到代理级覆盖的常见场景。每个片段都标注了路径和适用场景你可以按需组合。3.1 全局禁用浏览器与运行时工具最常见的需求是代理只做文本处理不需要开浏览器也不需要跑 shell。这时候用 deny 最直接{ tools: { deny: [browser, group:runtime] } }这段配置放在openclaw.json的顶层tools字段下。group:runtime会展开成 exec、bash、process所以这一条就同时禁掉了三个工具。deny 优先于 allow所以即使后面有 allow 写了这些工具也不会生效。3.2 用 profile 做基础白名单再叠加 allow如果你希望代理默认只有编码相关能力但额外允许 Slack 和 Discord 工具可以这样写{ tools: { profile: coding, allow: [slack, discord] } }profile: coding会先展开成group:fs、group:runtime、group:sessions、group:memory、image。然后allow再追加 slack 和 discord。注意这里的顺序profile 先应用allow 后应用deny 最后应用。所以如果你同时写了 denydeny 会覆盖前面所有。3.3 用 byProvider 针对特定模型缩小工具集假设你全局用的是 coding profile但某个模型端点不太稳定想只给它文件工具和会话列表{ tools: { profile: coding, byProvider: { openai/gpt-5.2: { allow: [group:fs, sessions_list] } } } }byProvider的键可以是provider也可以是provider/model。它只能缩小工具集不能放大。所以这里虽然全局是 coding但对openai/gpt-5.2来说最终只有group:fs和sessions_list可用。3.4 代理级覆盖给 support 代理单独配 messaging如果你有多个代理想让其中一个只做消息功能可以这样写{ tools: { profile: coding }, agents: { list: [ { id: support, tools: { profile: messaging, allow: [slack] } } ] } }全局是 coding但support这个代理用 messaging profile并且额外允许 slack。代理级配置会覆盖全局配置所以 support 代理最终的工具集是 messaging 加上 slack。3.5 只允许文件工具和浏览器如果你想让代理只能读写文件、开浏览器其他一律不给{ tools: { allow: [group:fs, browser] } }这里没有写 deny所以 allow 就是最终的白名单。注意group:fs包含 read、write、edit、apply_patchbrowser是单个工具。如果你还想加 web 搜索可以写成[group:fs, browser, group:web]。3.6 开启循环检测防止工具调用死循环工具权限配好之后还有一个实用配置是循环检测。它默认关闭开启后可以防止代理反复调用同一个工具{ tools: { loopDetection: { enabled: true, warningThreshold: 10, criticalThreshold: 20, globalCircuitBreakerThreshold: 30, historySize: 30, detectors: { genericRepeat: true, knownPollNoProgress: true, pingPong: true } } } }genericRepeat检测相同工具加相同参数的重复调用knownPollNoProgress检测类似轮询且输出相同的调用pingPong检测 A/B/A/B 交替无进展的模式。代理级也可以用agents.list[].tools.loopDetection覆盖。3.7 工具组速查表写配置时经常需要查某个组包含哪些工具下面这张表可以对照工具组包含的工具group:runtimeexec, bash, processgroup:fsread, write, edit, apply_patchgroup:sessionssessions_list, sessions_history, sessions_send, sessions_spawn, session_statusgroup:memorymemory_search, memory_getgroup:webweb_search, web_fetchgroup:uibrowser, canvasgroup:automationcron, gatewaygroup:messagingmessagegroup:nodesnodesgroup:openclaw所有 OpenClaw 内置工具不含提供商插件用组来写 allow/deny比逐个列工具名更清晰也更不容易漏。比如你想禁掉所有运行时能力直接写deny: [group:runtime]就行。3.8 配置文件的完整结构参考把上面的片段组合起来一个相对完整的openclaw.json工具配置段大概长这样{ tools: { profile: coding, deny: [group:runtime], allow: [group:fs, group:web], byProvider: { taotoken/claude-sonnet-4-20250514: { allow: [group:fs] } }, loopDetection: { enabled: true, warningThreshold: 10, criticalThreshold: 20 } }, agents: { list: [ { id: support, tools: { profile: messaging, allow: [slack] } } ] } }这段配置的效果是全局用 coding profile但禁掉 runtime 组只允许 fs 和 web 组对taotoken/claude-sonnet-4-20250514这个模型进一步缩小到只有 fs 组support 代理单独用 messaging profile 加 slack。循环检测开启阈值分别是 10 和 20。写配置时建议先用 JSON 校验工具检查语法因为openclaw.json对格式很敏感少一个逗号就会导致整个配置加载失败。改完配置后记得重启网关或者用gateway工具的config.apply让配置生效。4. 验证 allow/deny 是否生效命令与预期输出配置写完不代表生效必须验证。验证分两步先确认配置被正确加载再确认工具列表在请求里被裁剪。4.1 用 gateway 工具检查配置路径OpenClaw 的gateway工具提供了一个config.schema.lookup操作可以一次检查一个配置路径而不用把完整 schema 加载到提示上下文里。比如你想确认tools.deny的值{ action: config.schema.lookup, path: tools.deny }预期返回里会包含当前生效的 deny 列表。如果返回为空或者和你写的不一致说明配置没加载成功。这时候先检查openclaw.json的路径对不对再检查 JSON 语法。也可以用config.get获取完整配置{ action: config.get }返回的 JSON 里会包含tools段。对照你写的 allow/deny确认没有拼写错误。特别注意工具名大小写不敏感但组名必须写成group:xxx的格式写成group.fs是不认的。4.2 用 sessions_history 查看实际工具调用配置生效后最直接的验证方式是跑一次对话然后看会话历史里有没有被禁用的工具。用sessions_history操作{ action: sessions_history, sessionKey: main, limit: 20, includeTools: true }includeTools: true会把工具调用也包含进来。如果你禁用了group:runtime那历史里就不应该出现 exec、bash、process 的调用记录。如果出现了说明 deny 没生效需要回去检查配置顺序。4.3 用 browser status 验证浏览器工具是否被禁如果你禁用了 browser可以直接尝试调用它看返回什么{ action: status }在 browser 工具被禁用的情况下这个调用不会出现在模型可用的工具列表里所以模型根本不会发起这个调用。如果你在日志里看到模型尝试调用 browser 但被拒绝那说明 deny 生效了。另一种情况是模型压根不知道 browser 存在这也是生效的表现。4.4 检查请求体里的工具 schema更底层的验证是看发给模型提供商的请求体。OpenClaw 会把工具模式作为结构化函数定义发给模型 API。你可以在网关日志里找到请求体搜索tools字段。如果 deny 生效被禁用的工具不会出现在这个数组里。这一步需要看日志不同部署方式的日志位置不一样。如果你用的是本地网关日志通常在终端输出里。搜索关键词tools或者具体工具名比如browser。如果搜不到说明裁剪成功。4.5 预期输出对照表下面这张表列出了常见配置和对应的预期结果方便你对照配置预期结果deny: [browser]请求体 tools 数组里没有 browser模型不会调用 browserallow: [group:fs]只有 read/write/edit/apply_patch 可用exec 等不可用profile: minimal只有 session_status 可用byProvider 缩小对应 provider/model 的工具集比全局更小allow 写了未知工具名日志出现警告允许列表被忽略核心工具仍可用如果实际结果和预期不符先检查配置顺序profile → byProvider → allow/deny。deny 永远优先。再检查工具名拼写尤其是组名。最后检查配置有没有被代理级覆盖因为agents.list[].tools会覆盖全局tools。4.6 用 loopDetection 验证循环防护如果你开启了 loopDetection可以故意让代理重复调用同一个工具观察是否触发警告或阻断。配置里的warningThreshold是警告阈值criticalThreshold是严重阈值globalCircuitBreakerThreshold是全局熔断阈值。触发后会在日志里看到相应记录。验证时建议先用一个简单的工具比如session_status让它反复调用。如果阈值设得比较低很快就能看到警告。确认生效后再把阈值调回合理值。5. 本篇常见错误排查401、local proxy failed、reading choices、OAuth工具权限配置过程中报错往往不来自配置本身而是来自模型接入链路。下面这几个是我实际遇到过的按出现频率排序。5.1 401 Unauthorized这是最常见的错误通常出现在模型请求阶段。原因一般是 API Key 无效、过期或者没带上。检查openclaw.json里providers.taotoken.apiKey的值确认没有多余空格。如果你用环境变量注入确认环境变量名和配置里引用的一致。还有一种情况是 Base URL 写错了。比如写成了https://taotoken.net而漏掉/api请求会打到错误的路径返回 401 或 404。正确写法是https://taotoken.net/api。如果 Key 确认没问题但还是 401检查一下是不是把 Key 用在了错误的 provider 上。比如你配置了多个 provider但请求走的是另一个没配 Key 的 provider。5.2 local proxy failed这个错误通常和网络配置有关。OpenClaw 在本地跑网关时如果配置了代理或者网关地址不对会出现这个报错。检查gatewayUrl是不是ws://127.0.0.1:18789端口有没有被占用。如果你改了默认端口配置里也要同步改。另外如果你在 WSL2 里跑网关Windows 侧的 Chrome CDP 连接可能会出问题。这种情况需要检查 WSL2 和 Windows 之间的网络互通确保 CDP 端口可访问。具体排查可以参考 OpenClaw 的 WSL2 Windows 远程 Chrome CDP 故障排除文档。5.3 reading choices 报错这个错误一般出现在模型返回格式不符合预期时。可能原因是 Model ID 写错了或者模型端点返回了非标准响应。先确认 Model ID 和 TaoToken 模型对话页面里列出的完全一致。如果 Model ID 没问题检查请求体里有没有被工具配置影响。比如 allow 列表写错导致工具 schema 异常也可能间接引发解析错误。还有一种情况是tools.allow里只写了未知工具名OpenClaw 忽略允许列表后核心工具全部可用请求体变大某些模型端点可能对请求体大小有限制。这时候精简 allow 列表只保留必要工具通常能解决。5.4 OAuth 相关错误如果你用的是需要 OAuth 的 provider比如某些 Google 服务可能会遇到 OAuth 报错。检查 OAuth 凭据有没有过期回调地址有没有配错。OpenClaw 的byProvider配置里如果针对某个 provider 做了限制确认没有误伤 OAuth 相关工具。OAuth 错误有时会伪装成 401所以看到 401 时也要考虑是不是 OAuth 凭据的问题。区分方法是看错误信息里有没有oauth关键词。5.5 配置不生效的排查顺序如果 allow/deny 改了但没效果按这个顺序排查第一检查 JSON 语法。用python -m json.tool openclaw.json或者在线校验工具确认没有语法错误。第二检查配置路径。tools字段必须在顶层agents.list[].tools必须在对应代理下。写错层级会导致配置被忽略。第三检查应用顺序。profile 先应用byProvider 其次allow/deny 最后。deny 优先于 allow。如果你同时写了 allow 和 deny 同一个工具deny 赢。第四检查代理级覆盖。agents.list[].tools会覆盖全局tools。如果你在全局禁用了 browser但某个代理的 tools 里又允许了那这个代理仍然能用 browser。第五重启网关。改完配置后用gateway工具的restart操作或者手动重启。配置不会自动热加载。5.6 工具名拼写错误工具名大小写不敏感但拼写必须正确。比如browser不能写成browsersgroup:fs不能写成group:file。如果 allow 里写了未知工具名OpenClaw 会记录警告并忽略整个允许列表。这时候核心工具仍然可用但你的白名单意图就失效了。所以改完配置后一定要看日志里有没有警告。5.7 循环检测误报如果你开启了 loopDetection正常的长任务可能被误判为循环。比如代理在轮询一个长时间运行的任务knownPollNoProgress可能会触发。这时候可以调高warningThreshold和criticalThreshold或者针对特定代理关闭检测。代理级配置用agents.list[].tools.loopDetection。6. 把工具权限收进可控范围从模型对话到 Coding Plan 的接入路径工具权限配置不是一次性的工作而是随着代理用途变化不断调整的过程。我自己的做法是先用minimal或messagingprofile 跑起来确认基础功能正常再按需逐步放开。每放开一个工具组就跑一次验证看请求体里工具列表是否符合预期。这样比一开始就全开再收紧要安全得多。如果你还在选模型接入方式可以先用模型对话页面测试不同模型在工具调用上的表现地址是https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite。确认模型能稳定处理工具调用后再去 API Keys 页面创建正式 Key地址是https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite。接入文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite里面有 Base URL、Key、Model ID 的完整说明。如果你打算长期跑编码或 Agent 任务Coding Plan 会更合适地址是https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite。它针对持续性的编码场景做了优化配合工具权限配置可以把代理的能力边界控制得很清楚。最后提醒一个实操细节每次改完openclaw.json先用gateway的config.schema.lookup确认配置被正确加载再跑一次sessions_history看工具调用记录。两步都通过才算真正生效。工具权限这件事宁可配得保守一点也不要等出了问题再回头收紧。