OpenClaw 源码解析(十二):Tools 工具系统与 Agent 能力扩展的配置骨架

发布时间:2026/9/27 16:55:44
OpenClaw 源码解析(十二):Tools 工具系统与 Agent 能力扩展的配置骨架 1. 从一次“工具全开”的翻车说起OpenClaw 的 Tools 工具系统是 Agent 从“会聊天”变成“能干活”的分水岭。它把 exec、read、write、web_search、message、sessions_spawn 这些类型化函数暴露给模型让 Agent 能读文件、跑命令、搜网页、发消息、开子会话。适合谁适合正在本地搭 Agent、想让模型真正操作项目和环境又不想把权限一次性全放开的人。我试过最省事的做法tools.profile full结果模型在一个群聊会话里直接调 exec 去跑构建命令把工作目录搅得一团乱。问题不在模型而在配置骨架没搭好——工具可见性、执行环境、审批链路全是默认值。这一篇就聚焦落地配置给你一份可复制的config.toml与settings.json骨架覆盖 Tools、Tool policy、Tool Search 关键字段再走一遍通过 TaoToken 统一 Key/API 通道接入后的验证动作和报错排查。先把概念对齐不然后面配置会看晕。Tool 是 Agent 可调用的动作函数Skill 是告诉 Agent 怎么用工具的说明书SKILL.mdPlugin 是给 OpenClaw 加新能力的扩展包可以注册 tools、skills、channels、providers。三者关系是Plugin 提供能力Tool 暴露动作Skill 指导怎么用Agent 组合工具完成任务。一句话Tool 解决“能不能做”Skill 解决“怎么做得规范”Plugin 解决“怎么扩展新能力”。工具集合不是静态写死的。源码里createOpenClawCodingTools会根据 agent、session、sandbox、channel、provider、workspace 动态构造候选工具再经过 profile、allow/deny、byProvider、toolsBySender、sandbox policy 一层层过滤最终只把允许的工具 schema 发给模型。所以同一个 OpenClaw 实例主用户私聊能看到 exec、read、write群聊访客可能只剩 message 和 session_status。理解这一点配置才有意义。2. TaoToken 前置统一 Key 与 API 通道本地 Agent 开发最烦的是每个 provider 一套 Key、一套 base_url、一套鉴权头。TaoToken 的作用是把模型调用收敛到一个统一入口一个 Key一个 API 地址兼容主流模型协议。对 OpenClaw 这种要按 provider 做工具策略的场景特别合适——你只需要在配置里维护一份 provider 映射不用到处散落密钥。接入前先拿到凭证。打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后进入控制台在 API Keys 页面创建一个 Key。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite API Keys 管理页是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。创建时建议按用途命名比如openclaw-local-dev方便后面按环境轮换。API 基地址统一用 https://taotoken.net/api 注意这个地址不带任何查询参数。OpenClaw 里配置 provider 时把 base_url 指向它把 Key 填进对应字段即可。如果你用的是 Anthropic 协议风格的模型接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有协议差异和字段说明配置前扫一眼能少踩坑。注意Key 只放在本地配置文件或环境变量里不要提交到 Git。OpenClaw 的 config 支持从环境变量读取后面骨架里会体现。3. 可复制配置config.toml 与 settings.json 骨架OpenClaw 的配置分两层config.toml管 Gateway 和 provider 通道settings.json管 Agent 的 tools 策略。下面这份骨架可以直接抄按注释改。先看config.toml重点是 provider 指向 TaoToken# ~/.openclaw/config.toml [gateway] host 127.0.0.1 port 8787 auth_token ${OPENCLAW_GATEWAY_TOKEN} [providers.taotoken] # 统一 API 入口不带查询参数 base_url https://taotoken.net/api api_key ${TAOTOKEN_API_KEY} # 按需声明你要用的模型provider/model 形式 models [ openai/gpt-5.4, anthropic/claude-sonnet-4-5, google/gemini-2.5-pro ] [agents.default] provider taotoken model anthropic/claude-sonnet-4-5 workspace /Users/me/projects/demo再看settings.json这是工具策略的主战场{ tools: { profile: coding, allow: [group:fs, group:web, group:sessions, session_status], deny: [exec, process, apply_patch], byProvider: { google/gemini-2.5-pro: { profile: minimal }, openai/gpt-5.4: { allow: [group:fs, sessions_list] } }, toolsBySender: { channel:discord:1234567890123: { alsoAllow: [group:fs] }, id:guest-user-id: { deny: [group:runtime, group:fs] }, *: { deny: [exec, process, write, edit, apply_patch] } }, exec: { backgroundMs: 10000, timeoutSec: 120, cleanupMs: 5000, notifyOnExit: true, applyPatch: { enabled: false, allowModels: [] } } }, toolSearch: { enabled: true, maxDescriptors: 200, fallback: structured } }几个关键点解释一下。profile是粗粒度画像minimal 只留 session_statuscoding 覆盖文件、运行时、Web、sessions、memory、cron、imagemessaging 偏消息会话full 基本不限制。allow/deny是细粒度白黑名单deny 优先级更高命中 deny 的工具即使出现在 allow 里也会被移除且支持大小写不敏感和通配符。工具组简写能省很多字group:runtime含 exec、process、code_executiongroup:fs含 read、write、edit、apply_patchgroup:web含 web_search、x_search、web_fetchgroup:sessions含会话管理类group:plugins表示已加载插件拥有的工具。注意想彻底禁止文件修改别只 denywrite。write和apply_patch是不同工具 ID正确做法是 denygroup:fs或显式列出 write、edit、apply_patch。这是最容易漏的一条。byProvider的顺序是 base profile → provider profile → allow/deny。上面配置里 gemini 被压到 minimalgpt-5.4 只留文件读和会话列表适合模型兼容性差异大的场景。toolsBySender是 channel 访问控制之外的纵深防御sender 值必须来自 channel adapter不能来自消息文本所以别指望用户自己填个 ID 就能提权。4. 验证请求确认工具真的按策略生效配置写完别急着跑任务先验证工具目录和当前会话的有效工具。OpenClaw Gateway 暴露了三个方法tools.catalog看全局目录tools.effective看当前 session 真实可用工具tools.invoke从外部调用工具。排查“模型为什么看不到某个工具”tools.effective是第一现场。先确认 Gateway 起来了export TAOTOKEN_API_KEYsk-你的key export OPENCLAW_GATEWAY_TOKEN本地随便设一个 openclaw gateway start --config ~/.openclaw/config.toml然后查全局工具目录curl -s http://127.0.0.1:8787/tools/catalog \ -H Authorization: Bearer $OPENCLAW_GATEWAY_TOKEN \ | jq .groups[] | {source, tools: [.tools[].name]}预期能看到 core 组和 plugin 组plugin 工具会带source: plugin、pluginId、risk、tags、defaultProfiles等元信息。这一步只说明系统“理论上有哪些工具”。再查当前会话的有效工具这一步才反映策略过滤结果curl -s http://127.0.0.1:8787/tools/effective \ -H Authorization: Bearer $OPENCLAW_GATEWAY_TOKEN \ -H Content-Type: application/json \ -d {sessionKey:discord:1234567890123} \ | jq .tools[].name如果 catalog 里有 exec但 effective 里没有说明被某一层策略拦了——可能是 toolsBySender 的 deny也可能是 sandbox policy 屏蔽了 runtime。这就是定位问题的正确姿势。最后验证一次真实调用走 Gateway 策略路径curl -s http://127.0.0.1:8787/tools/invoke \ -H Authorization: Bearer $OPENCLAW_GATEWAY_TOKEN \ -H Content-Type: application/json \ -d { name: read, args: {path: package.json}, sessionKey: discord:1234567890123, idempotencyKey: verify-read-001 } | jq {ok, toolName, output}成功时返回ok: true、toolName、output、source被策略拦截或需要审批时返回ok: false加错误结构。注意tools.invoke复用同一套 Gateway policy path不会绕过策略和审批所以它既是调用入口也是策略验证入口。模型侧验证更直接在会话里问“你现在能用哪些工具”或让它读一个文件。如果它说没有 read 工具回到tools.effective对一遍基本能定位到是哪层 deny 生效了。5. 本篇常见错排查报错一401 Unauthorized或invalid api key。先确认TAOTOKEN_API_KEY环境变量在当前 shell 里真的存在echo $TAOTOKEN_API_KEY看一眼。再确认config.toml里写的是${TAOTOKEN_API_KEY}而不是字面量。base_url 必须是https://taotoken.net/api多带斜杠或查询参数都可能 404。报错二模型看不到 exec但 catalog 里有。按顺序查tools.profile是不是 minimaltools.deny有没有命中group:runtimebyProvider里当前模型是不是被压到小集合toolsBySender的*规则是不是 deny 了 execsandbox policy 是否屏蔽 runtime。用tools.effective逐层排除比猜快得多。报错三deny 了 write 还是能改文件。前面强调过apply_patch是独立工具 ID。改成 denygroup:fs或显式列出write、edit、apply_patch。改完重新查tools.effective确认。报错四Tool Search 开了但模型还是收到一堆 schema。检查toolSearch.enabled是否为 truemaxDescriptors是否设得过大导致退化成全量暴露。Tool Search 的机制是模型先搜 compact descriptors再tool_describe拿精确 schema最后tool_call执行真实调用仍回到 Gateway 走 policy、approval、hook、logging。如果工具数量本来就不多开不开差别不大插件和 MCP 工具一多收益才明显。报错五elevated 打开了还是不能跑 host 命令。Elevated 只影响 sandboxed exec 的执行位置不能绕过 tool policy。如果 exec 被 denyelevated 无效。另外 elevated 的 on/ask 保留 approvalsfull 才跳过审批别在不可信发送者上开 full。报错六tools.invoke返回ok: false但没细节。看返回的 typed error 结构常见是工具名不存在、参数 schema 不匹配、需要 confirm 审批、或 idempotencyKey 重复。补上confirm: true或换一个 idempotencyKey 再试。6. 把工具系统当成能力控制面来配OpenClaw 的 Tools 系统值得学的地方是它没把工具列表做成静态配置而是按 agent、session、channel、sender、provider、sandbox、plugin 状态动态生成并且把权限前置到模型调用之前——模型只能看到被允许的 schema而不是先看到再拒绝。这套设计让同一个 Gateway 能支撑多用户、多会话、多平台、多权限。配置骨架搭好后日常维护就三件事改settings.json调策略用tools.effective验证用tools.invoke做回归。长期跑编码和 Agent 任务的话建议把模型调用统一走 TaoToken 的 Coding Plan地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 一个 Key 覆盖多模型省去按 provider 维护密钥的麻烦。想先试模型对话效果用 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 快速验证Claude Code 风格的接入参考 https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecodeutm_campaignrewrite 。最后留一个实用习惯每次改完工具策略先跑一遍tools.effective把返回的工具名列表存成快照。下次模型行为异常时diff 一下快照八成能直接看出是哪条 deny 或 provider 策略动了手脚。工具系统不是配一次就完事的东西它更像 Agent 的能力控制面值得当成代码一样管理。