第 8 章 · 工具体系深度实践
Agent 的能力边界,就是它的工具边界。没有工具的 Agent 只会"说话";有了工具的 Agent 才能"做事"。OpenClaw 的工具体系是三层架构——内置工具是"手脚",技能(Skill)是"说明书",插件(Plugin)是"扩展包"。
本章你将学到:
- 理解 OpenClaw 三层工具架构的设计哲学
- 掌握内置工具的配置、安全控制和高级用法
- 能独立编写 Skill,教会 Agent 新技能
- 能编写和发布 Plugin,为 OpenClaw 扩展新能力
8.1 三层架构:工具、技能、插件
在上一章,你了解了会话管理——Agent 如何在有限记忆中保持连贯。本章转向"能力层":Agent 到底能做什么?
OpenClaw 的工具体系分三层,各有分工:
┌─────────────────────────────────────────────────────────────┐
│ 插件层 (Plugin) │
│ 可安装的扩展包,注册新工具/通道/模型提供商/语音等 │
│ 例如:@openclaw/voice-call, @openclaw/matrix │
│ 来源:npm / ClawHub / 本地目录 │
├─────────────────────────────────────────────────────────────┤
│ 技能层 (Skill) │
│ SKILL.md 文件,注入系统提示词,教会 Agent 如何使用工具 │
│ 例如:gemini、peekaboo、summarize │
│ 来源:内置 / ~/.openclaw/skills / workspace/skills │
├─────────────────────────────────────────────────────────────┤
│ 工具层 (Tool) │
│ Agent 可调用的类型化函数,发送给模型 API │
│ 例如:exec、browser、web_search、read、write │
│ 来源:OpenClaw 内置 + 插件注册 │
└─────────────────────────────────────────────────────────────┘
用一个比喻来理解:
- 工具是 Agent 的"手脚"——能执行操作(读文件、运行命令、搜索网页)
- 技能是 Agent 的"说明书"——告诉它什么时候用哪个工具、怎么用
- 插件是 Agent 的"扩展包"——可以给 Agent 装上全新的手脚和说明书
没有技能的 Agent 拥有工具但不知道什么时候用;没有插件的 Agent 只能用内置能力。三者协同,才是完整的工具体系。
8.2 内置工具全览
OpenClaw 开箱即用的工具覆盖了 Agent 工作中的核心场景:
| 工具 | 功能 | 关键参数 |
|---|---|---|
exec / process |
运行 Shell 命令,管理后台进程 | command, workdir, background, timeout |
browser |
控制 Chromium 浏览器(导航、点击、截图) | profile, target, snapshot/click/type |
web_search |
搜索网页 | query, count, country, freshness |
web_fetch |
抓取网页并提取可读内容 | url, extractMode, maxChars |
read / write / edit |
工作空间文件读写编辑 | 文件路径、内容 |
apply_patch |
多文件补丁(OpenAI 模型) | 工作区路径 |
message |
跨所有通道发送消息 | target, text, channel |
canvas |
驱动节点 Canvas | present/eval/snapshot |
nodes |
发现和操作配对设备 | discover/target |
cron / gateway |
管理定时任务、重启网关 | 定时表达式 |
image / image_generate |
分析或生成图像 | provider, prompt |
sessions_* |
会话管理、子 Agent | list/history/send/spawn |
tts |
文字转语音 | text, provider |
8.2.1 工具配置:允许与拒绝
你可以通过配置精确控制 Agent 能用哪些工具:
{
tools: {
allow: ["group:fs", "browser", "web_search"], // 只允许这些
deny: ["exec"], // 禁止 exec
},
}
deny 优先级高于 allow——即使一个工具同时在两个列表中,它也会被禁止。
8.2.2 工具配置文件(Profile)
除了手动指定 allow/deny,OpenClaw 提供了几种预设配置文件:
| 配置文件 | 包含的工具 | 适用场景 |
|---|---|---|
full |
所有工具(默认) | 完全信任的本地环境 |
coding |
文件 I/O、运行时、会话、记忆、图像 | 编程助手,不需要消息功能 |
messaging |
消息发送、会话列表/历史/发送/状态 | 客服机器人,不需要文件访问 |
minimal |
只有 session_status |
最低权限,只做对话 |
{
tools: {
profile: "coding", // 基础配置文件
allow: ["browser"], // 在 coding 基础上额外允许 browser
deny: ["exec"], // 再排除 exec
},
}
执行顺序:profile 先建立基础允许列表 → allow 追加 → deny 排除。
8.2.3 工具组(Group)
allow/deny 支持组快捷方式:
{
tools: {
allow: ["group:web"], // 同时允许 web_search 和 web_fetch
deny: ["group:runtime"], // 同时禁止 exec, bash, process
},
}
| 组名 | 包含的工具 |
|---|---|
group:runtime |
exec, bash, process |
group:fs |
read, write, edit, apply_patch |
group:sessions |
sessions_list, sessions_history, sessions_send, sessions_spawn, sessions_yield, subagents, session_status |
group:memory |
memory_search, memory_get |
group:web |
web_search, web_fetch |
group:ui |
browser, canvas |
group:automation |
cron, gateway |
group:messaging |
message |
group:nodes |
nodes |
group:openclaw |
所有内置工具(不含插件工具) |
8.2.4 按模型提供商限制工具
有些模型提供商的安全策略不同,你可以按提供商设置不同的工具策略:
{
tools: {
profile: "coding",
byProvider: {
// 给 Gemini 最低权限(因为它对提示词注入更敏感)
"google-antigravity": { profile: "minimal" },
// 本地模型可以给完整权限
"ollama": { profile: "full" },
},
},
}
这在多模型混合使用的场景中非常有用——给本地模型全权,给云端模型受限权限。
8.3 exec 工具:让 Agent 执行命令
exec 是 Agent 最强大的工具——它让 Agent 能在主机上运行任意 Shell 命令。强大意味着危险,所以 OpenClaw 为它设计了多层安全控制。
8.3.1 基本用法
// 前台执行
{ "tool": "exec", "command": "ls -la" }
// 后台执行 + 轮询
{ "tool": "exec", "command": "npm run build", "yieldMs": 1000 }
{ "tool": "process", "action": "poll", "sessionId": "<id>" }
// 向后台进程发送按键
{ "tool": "process", "action": "send-keys", "sessionId": "<id>", "keys": ["Enter"] }
{ "tool": "process", "action": "send-keys", "sessionId": "<id>", "keys": ["C-c"] }
8.3.2 执行位置:sandbox / gateway / node
exec 支持三种执行位置:
┌────────────────────────────────────────────────────────┐
│ host=sandbox(默认) │
│ 在 Docker 容器中执行 │
│ 隔离性强,适合不可信的 Agent │
│ │
│ host=gateway │
│ 在 Gateway 进程所在主机执行 │
│ 需要 approval 审批 │
│ 适合需要访问宿主机资源的场景 │
│ │
│ host=node │
│ 在配对的远程设备上执行 │
│ 需要 Node Host 运行 │
│ 适合需要特定硬件的场景(如 macOS 上运行 Swift) │
└────────────────────────────────────────────────────────┘
⚠️ 踩坑记录
问题:沙盒关闭后,Agent 调用
exec仍然成功执行了命令。原因:旧版 OpenClaw 在沙盒关闭时会静默回退到
gateway执行。解决:当前版本已修复——沙盒关闭 +
host=sandbox会直接失败,而不是静默回退。确保显式设置host=gateway或启用沙盒。
8.3.3 安全审批机制
当 exec 在 gateway 或 node 上执行时,需要通过审批:
{
tools: {
exec: {
host: "gateway",
security: "allowlist", // deny | allowlist | full
ask: "on-miss", // off | on-miss | always
},
},
}
| security 模式 | 行为 |
|---|---|
deny |
拒绝所有主机执行(沙盒默认) |
allowlist |
只允许白名单中的命令路径 |
full |
允许所有命令(危险,仅限可信环境) |
| ask 模式 | 行为 |
|---|---|
off |
不弹审批(配合 allowlist 使用) |
on-miss |
白名单中没有的命令才弹审批 |
always |
每次都弹审批 |
审批列表存储在 ~/.openclaw/exec-approvals.json,支持三种响应:
allow-once:本次允许allow-always:永久加入白名单deny:拒绝
8.3.4 会话级覆盖
你可以用 /exec 命令在当前会话中临时更改 exec 设置:
/exec host=gateway security=allowlist ask=on-miss node=mac-1
/exec # 查看当前设置
这只影响当前会话,不写入配置文件。要永久禁用 exec,使用 tools.deny: ["exec"]。
8.3.5 安全回收站:Safe Bins
OpenClaw 区分两种"白名单":
- allowlist:完全信任的可执行文件路径
- safeBins:仅 stdin 模式的流过滤器(如
cat、head、grep)
{
tools: {
exec: {
safeBins: ["cat", "head", "tail", "grep", "wc"],
safeBinTrustedDirs: ["/usr/local/bin/mysafetools"],
},
},
}
⚠️ 安全警告
不要把解释器(
python3、node、ruby、bash)加入 safeBins。safeBins 的设计初衷是"只能读取 stdin 的纯过滤器"。解释器可以执行任意代码,放在 safeBins 中等于绕过了安全控制。如果需要允许解释器,使用显式的 allowlist 条目并保持审批开启。
8.4 browser 工具:让 Agent 操控浏览器
browser 工具让 Agent 能像人一样操作网页——打开页面、点击按钮、填写表单、截图。
8.4.1 两个浏览器档案
OpenClaw 的浏览器工具支持两种档案(Profile):
openclaw 档案(默认)
├── 独立的 Chromium 实例
├── 不共享你的登录状态
├── Agent 可以完全控制
└── 安全、隔离
user 档案
├── 附加到你正在运行的 Chrome
├── 共享你的登录状态(已登录的网站可以直接用)
├── 通过 Chrome DevTools MCP 协议连接
└── 需要你在电脑前批准连接
选择建议:日常自动化用 openclaw 档案;需要操作已登录的网站时用 user 档案。
8.4.2 快速上手
# 启动浏览器
openclaw browser start
# 打开网页
openclaw browser open https://example.com
# 获取页面快照(AI 模式,返回带编号的元素列表)
openclaw browser snapshot
# 获取交互元素列表(角色模式,返回可操作的元素)
openclaw browser snapshot --interactive
# 点击编号为 12 的元素
openclaw browser click 12
# 在编号为 23 的输入框中输入文字
openclaw browser type 23 "hello"
# 截图
openclaw browser screenshot
# 等待特定文本出现
openclaw browser wait --text "Done"
# 等待 URL 匹配
openclaw browser wait --url "**/dashboard"
8.4.3 Agent 如何使用浏览器
Agent 获取一个 browser 工具,工作流程是:
1. Agent 调用 browser snapshot → 获取页面元素列表和编号
2. Agent 根据编号调用 browser act(click/type/drag/select)
3. 需要验证时调用 browser screenshot
4. 编号在导航后会变化,需要重新 snapshot
这意味着 Agent 不需要写 CSS 选择器——它通过"看"(snapshot)来"操作"(click/type),和人类操作浏览器的方式一样。
8.4.4 配置
{
browser: {
enabled: true,
defaultProfile: "openclaw",
headless: false, // true = 无头模式,不显示浏览器窗口
profiles: {
openclaw: { cdpPort: 18800, color: "#FF4500" },
// 远程浏览器(如 Browserless 云服务)
browserless: {
cdpUrl: "wss://production-sfo.browserless.io?token=<KEY>",
color: "#00AA00",
},
},
},
}
8.4.5 调试工作流
当 Agent 的浏览器操作失败时(如"not visible"、"strict mode violation"):
# 1. 查看当前页面状态
openclaw browser snapshot --interactive
# 2. 使用角色引用操作(更精确)
openclaw browser click e12
# 3. 高亮显示目标元素,确认 Playwright 找到了正确的元素
openclaw browser highlight e12
# 4. 检查网络请求
openclaw browser requests --filter api --clear
# 5. 检查控制台错误
openclaw browser console --level error
# 6. 深度调试:录制 Trace
openclaw browser trace start
# ... 复现问题 ...
openclaw browser trace stop
💡 提示:快照中的引用编号(ref)在页面导航后会失效。如果操作失败,重新获取快照并使用新的编号。这是设计如此——保证操作的是"当前"页面的"当前"状态。
8.5 web_search 和 web_fetch:信息获取双武器
8.5.1 web_search:搜索网页
web_search 是轻量级的 HTTP 搜索工具,不涉及浏览器自动化。
选择搜索提供商:
| 提供商 | 结果风格 | API Key | 特色 |
|---|---|---|---|
| Brave | 结构化摘要 | BRAVE_API_KEY |
免费 1000 次/月,支持 llm-context 模式 |
| DuckDuckGo | 结构化摘要 | 无需 | 免费,非官方 HTML 解析 |
| Gemini | AI 合成答案 + 引用 | GEMINI_API_KEY |
谷歌搜索增强 |
| Grok | AI 合成答案 + 引用 | XAI_API_KEY |
xAI 搜索增强 |
| Perplexity | 结构化 + 内容提取 | PERPLEXITY_API_KEY |
支持域名过滤 |
| Exa | 神经搜索 + 内容提取 | EXA_API_KEY |
语义搜索,支持高亮 |
| Firecrawl | 结构化摘要 | FIRECRAWL_API_KEY |
搭配 scrape 工具深度提取 |
| Tavily | 结构化摘要 | TAVILY_API_KEY |
支持主题过滤 |
自动检测机制:如果不指定 provider,OpenClaw 按以下顺序检测 API Key 并使用第一个找到的:
Brave → Gemini → Grok → Kimi → Perplexity → Firecrawl → Tavily → DuckDuckGo(兜底)
配置示例(Brave Search):
{
plugins: {
entries: {
brave: {
config: {
webSearch: {
apiKey: "BRAVE_API_KEY_HERE",
},
},
},
},
},
tools: {
web: {
search: {
provider: "brave",
maxResults: 5,
timeoutSeconds: 30,
cacheTtlMinutes: 15,
},
},
},
}
8.5.2 web_fetch:抓取网页内容
web_fetch 做的事情很简单:HTTP GET + HTML 转可读内容。它不执行 JavaScript,所以不适合 JS 重度的网站。
{
tools: {
web: {
fetch: {
enabled: true,
maxChars: 50000,
timeoutSeconds: 30,
cacheTtlMinutes: 15,
readability: true, // 使用 Readability 提取正文
},
},
},
}
Firecrawl 回退:如果 Readability 提取失败,可以配置 Firecrawl 作为回退方案——它有更强的反爬虫绕过能力:
{
tools: {
web: {
fetch: {
firecrawl: {
enabled: true,
apiKey: "fc-...",
timeoutSeconds: 60,
},
},
},
},
}
选择决策:
需要搜索?→ web_search
需要读取特定 URL?→ web_fetch
网页是 JS 渲染的?→ browser 工具
需要登录?→ browser 工具(user 档案)
8.6 技能(Skill):教会 Agent 新技能
Skill 是 OpenClaw 最灵活的扩展方式之一。它不需要写代码——只需要写一个 Markdown 文件。
8.6.1 Skill 是什么
每个 Skill 是一个包含 SKILL.md 的目录。SKILL.md 由两部分组成:
---
name: my-skill
description: 用简洁的一句话描述这个技能
---
这里是详细的 Markdown 指令,告诉 Agent:
- 什么时候使用这个技能
- 使用哪些工具
- 按什么步骤操作
- 有什么注意事项
YAML 头(frontmatter)是元数据,告诉 OpenClaw "这是一个技能";Markdown 正文是"说明书",注入到系统提示词中。
8.6.2 Skill 的加载位置和优先级
Skill 可以存放在三个地方:
<workspace>/skills/ (最高优先级,仅当前 Agent 可见)
~/.openclaw/skills/ (中优先级,所有 Agent 共享)
OpenClaw 内置 (最低优先级)
同名 Skill,高优先级覆盖低优先级。这意味着你可以在 workspace 中自定义内置 Skill 的行为——只需要创建同名目录。
还可以通过配置添加额外的共享目录:
{
skills: {
load: {
extraDirs: ["~/Projects/agent-scripts/skills"],
},
},
}
8.6.3 动手写第一个 Skill
场景:你想让 Agent 在每次生成代码后自动运行测试。
# 1. 创建 Skill 目录
mkdir -p ~/.openclaw/workspace/skills/test-after-code
# 2. 编写 SKILL.md
~/.openclaw/workspace/skills/test-after-code/SKILL.md:
---
name: test_after_code
description: 在生成或修改代码文件后,自动运行相关测试
---
# 代码后测试
## 触发条件
当用户要求你编写、修改或重构代码文件时,在完成代码编写后:
1. 检查项目中是否存在测试文件
2. 如果存在,运行对应的测试命令
3. 如果测试失败,修复代码并重新运行
4. 直到所有测试通过再回复用户
## 步骤
1. 用 `exec` 运行 `find . -name "*.test.*" -o -name "*_test.*" -o -name "test_*"` 查找测试文件
2. 根据项目类型运行测试:
- Node.js: `npm test` 或 `npx jest`
- Python: `pytest` 或 `python -m pytest`
- Go: `go test ./...`
3. 如果测试失败,分析失败原因并修复
4. 重新运行测试确认通过
## 注意
- 不要在测试命令中添加不存在的测试文件
- 如果项目没有测试框架,跳过此技能
- 长时间运行的测试套件可以设置 `yieldMs: 5000` 后台运行
3. 启用新会话:
/new # 或 openclaw gateway restart
4. 验证 Skill 已加载:
openclaw skills list
5. 测试:
你:帮我写一个计算斐波那契数列的函数
Agent:[编写代码]
[自动检测到测试框架]
[运行测试]
[测试通过]
[回复用户]
8.6.4 环境门控:Skill 的条件加载
不是所有 Skill 都应该在所有环境中可用。OpenClaw 提供了"门控"(Gating)机制——在加载时根据条件过滤 Skill:
---
name: gemini
description: 使用 Gemini CLI 进行编程辅助和 Google 搜索
metadata:
{
"openclaw":
{
"emoji": "♊️",
"requires": { "bins": ["gemini"] },
"os": ["darwin", "linux"],
},
}
---
门控字段:
| 字段 | 含义 |
|---|---|
requires.bins |
所有列出的二进制必须在 PATH 中 |
requires.anyBins |
至少一个二进制在 PATH 中 |
requires.env |
环境变量必须存在(或在 config 中提供) |
requires.config |
openclaw.json 中的指定路径必须为真值 |
os |
限定操作系统(darwin、linux、win32) |
always |
始终包含(跳过其他门控) |
如果门控条件不满足,Skill 不会出现在系统提示词中——Agent 根本不知道有这个 Skill。
8.6.5 Skill 配置
你可以在配置中启用/禁用 Skill、注入环境变量:
{
skills: {
allowBundled: ["gemini", "peekaboo"], // 只允许这些内置 Skill
entries: {
"image-lab": {
enabled: true,
apiKey: { source: "env", provider: "default", id: "GEMINI_API_KEY" },
env: {
GEMINI_API_KEY: "GEMINI_KEY_HERE",
},
},
"unwanted-skill": { enabled: false }, // 禁用某个 Skill
},
},
}
⚠️ 安全警告
第三方 Skill 应被视为不可信代码。安装前务必阅读 SKILL.md 内容。对于不信任的输入和有风险的工具调用,优先在沙盒中运行。
8.6.6 ClawHub:公共 Skill 市场
ClawHub 是 OpenClaw 的公共 Skill 注册中心,浏览地址:https://clawhub.com
# 安装 Skill 到当前 workspace
openclaw skills install <skill-slug>
# 更新所有已安装的 Skill
openclaw skills update --all
# 列出已安装的 Skill
openclaw skills list
8.6.7 Token 成本
每个 Skill 在系统提示词中约占 97 个 token(加上名称和描述的长度)。如果你加载了大量 Skill,这些 token 会累积。通过 /context list 可以查看 Skill 占用的具体 token 数:
Skills list: 2,184 chars (~546 tok) (12 skills)
如果 Skill 占用太多上下文,用 skills.allowBundled 精简允许的 Skill 列表。
8.7 插件(Plugin):给 OpenClaw 装上新能力
Plugin 是 OpenClaw 最强大的扩展方式。它可以注册新的工具、通道、模型提供商、语音服务等——几乎所有能力都可以通过 Plugin 扩展。
8.7.1 Plugin 的两种格式
| 格式 | 工作方式 | 来源 |
|---|---|---|
| Native | openclaw.plugin.json + 运行时模块,进程内执行 |
官方插件、社区 npm 包 |
| Bundle | Codex/Claude/Cursor 兼容布局,映射到 OpenClaw 功能 | .codex-plugin/、.claude-plugin/、.cursor-plugin/ |
Bundle 格式意味着 OpenClaw 可以直接使用为其他 AI 编码工具开发的插件——这是一个重要的生态兼容设计。
8.7.2 安装和管理
# 查看已加载的插件
openclaw plugins list
# 从 npm 安装
openclaw plugins install @openclaw/voice-call
# 从 ClawHub 安装
openclaw plugins install clawhub:@openclaw/voice-call
# 从本地目录安装(开发模式)
openclaw plugins install ./my-plugin
# 更新
openclaw plugins update --all
# 诊断
openclaw plugins doctor
8.7.3 配置
{
plugins: {
enabled: true,
allow: ["voice-call"],
deny: ["untrusted-plugin"],
entries: {
"voice-call": {
enabled: true,
config: { provider: "twilio" },
},
},
slots: {
memory: "memory-core", // 记忆插件槽位(互斥)
contextEngine: "legacy", // 上下文引擎槽位(互斥)
},
},
}
关键概念:Slots(槽位)是互斥的——同一类别只能有一个活跃插件。例如 memory 槽位可以是 memory-core(内置)或 memory-lancedb(安装型),但不能同时启用两个。
8.7.4 发现顺序
OpenClaw 按以下顺序发现插件(第一个匹配生效):
1. plugins.load.paths → 显式指定的文件/目录
2. <workspace>/.openclaw/extensions/ → 工作空间扩展
3. ~/.openclaw/extensions/ → 全局扩展
4. 内置插件 → 随 OpenClaw 安装
工作空间来源的插件默认禁用——必须显式启用。内置插件遵循各自的默认启用/禁用状态。
8.7.5 核心 Plugin API
Plugin 通过 register(api) 回调注册能力:
export default definePluginEntry({
id: "my-plugin",
name: "My Plugin",
register(api) {
// 注册模型提供商
api.registerProvider({ /* ... */ });
// 注册 Agent 工具
api.registerTool({
name: "my_tool",
description: "做一件事",
parameters: Type.Object({ input: Type.String() }),
async execute(_id, params) {
return { content: [{ type: "text", text: `Got: ${params.input}` }] };
},
});
// 注册通道
api.registerChannel({ /* ... */ });
// 注册生命周期钩子
api.registerHook("before_tool_call", async (ctx) => {
// 在工具调用前执行逻辑
return { block: false };
});
},
});
完整的注册方法列表:
| 方法 | 注册什么 |
|---|---|
registerProvider |
模型提供商(LLM) |
registerChannel |
聊天通道 |
registerTool |
Agent 工具 |
registerSpeechProvider |
语音合成 / 语音识别 |
registerMediaUnderstandingProvider |
图像/音频分析 |
registerImageGenerationProvider |
图像生成 |
registerWebSearchProvider |
网页搜索 |
registerHook / on(...) |
生命周期钩子 |
registerHttpRoute |
HTTP 端点 |
registerCommand / registerCli |
CLI 命令 |
registerContextEngine |
上下文引擎 |
registerService |
后台服务 |
8.8 动手写一个 Plugin
现在我们来写一个实用的 Plugin:一个能查询服务器状态的自定义工具。
8.8.1 项目结构
my-server-monitor/
├── package.json
├── openclaw.plugin.json
├── index.ts
└── tsconfig.json
8.8.2 package.json
{
"name": "@myorg/openclaw-server-monitor",
"version": "1.0.0",
"type": "module",
"openclaw": {
"extensions": ["./index.ts"]
}
}
openclaw 字段告诉 OpenClaw 去哪里找入口文件。
8.8.3 openclaw.plugin.json
{
"id": "server-monitor",
"name": "Server Monitor",
"description": "查询服务器状态信息",
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"servers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"host": { "type": "string" },
"port": { "type": "number" }
},
"required": ["name", "host"]
}
}
}
}
}
manifest 声明了插件的身份、配置 Schema。即使不需要配置,也必须提供空的 configSchema。
8.8.4 index.ts
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
import { Type } from "@sinclair/typebox";
interface ServerConfig {
name: string;
host: string;
port?: number;
}
export default definePluginEntry({
id: "server-monitor",
name: "Server Monitor",
description: "查询服务器状态信息",
register(api) {
// 注册必需工具——始终可用
api.registerTool({
name: "server_status",
description: "查询已配置服务器的状态",
parameters: Type.Object({
serverName: Type.Optional(Type.String({ description: "服务器名称" })),
}),
async execute(_id, params) {
const config = api.pluginConfig as { servers?: ServerConfig[] };
const servers = config.servers || [];
const target = params.serverName
? servers.find(s => s.name === params.serverName)
: servers[0];
if (!target) {
return {
content: [{ type: "text", text: `未找到服务器: ${params.serverName || "默认"}` }],
};
}
// 这里是实际的查询逻辑
// 示例:通过 exec 检查服务器是否在线
return {
content: [{
type: "text",
text: `服务器 ${target.name} (${target.host}:${target.port || 80}) 状态正常`,
}],
};
},
});
// 注册可选工具——用户必须显式允许
api.registerTool(
{
name: "server_restart",
description: "重启指定的服务器(危险操作)",
parameters: Type.Object({
serverName: Type.String({ description: "服务器名称" }),
}),
async execute(_id, params) {
return {
content: [{
type: "text",
text: `已发送重启请求到 ${params.serverName}`,
}],
};
},
},
{ optional: true },
);
},
});
关键设计决策:
server_status是必需工具——安全,只读操作server_restart是可选工具——有副作用,用户必须显式允许
8.8.5 使用
// openclaw.json
{
plugins: {
entries: {
"server-monitor": {
enabled: true,
config: {
servers: [
{ name: "web-1", host: "192.168.1.10", port: 80 },
{ name: "db-1", host: "192.168.1.20", port: 5432 },
],
},
},
},
},
// 允许可选工具
tools: {
allow: ["server_restart"],
},
}
# 安装
openclaw plugins install ./my-server-monitor
# 重启 Gateway
openclaw gateway restart
# 验证
openclaw plugins list
8.9 子 Agent(Sub-Agent):并行任务分派
子 Agent 是 OpenClaw 的"多任务处理"机制——主 Agent 可以派生出独立的子 Agent 在后台并行执行任务。
8.9.1 工作原理
主 Agent
├── 收到用户请求:"帮我同时查三个项目的状态"
├── 调用 sessions_spawn × 3
│ ├── 子 Agent A → 查询项目 Alpha
│ ├── 子 Agent B → 查询项目 Beta
│ └── 子 Agent C → 查询项目 Gamma
├── [等待所有子 Agent 完成]
└── 汇总结果并回复用户
每个子 Agent 运行在独立的会话中(agent:<agentId>:subagent:<uuid>),有独立的上下文和 Token 消耗。完成后通过"announce"机制将结果回传给主 Agent。
8.9.2 配置
{
agents: {
defaults: {
subagents: {
model: "anthropic/claude-sonnet-4-6", // 子 Agent 使用更便宜的模型
maxSpawnDepth: 1, // 不允许嵌套派生(默认)
maxChildrenPerAgent: 5, // 每个 Agent 最多 5 个子任务
maxConcurrent: 8, // 全局并发上限
runTimeoutSeconds: 900, // 单次运行超时(秒)
archiveAfterMinutes: 60, // 完成后 60 分钟归档
},
},
},
}
💡 成本提示:每个子 Agent 有独立的上下文和 Token 消耗。对于繁重或重复性的任务,给子 Agent 配置更便宜的模型,主 Agent 用高质量模型——这样可以显著降低成本。
8.9.3 嵌套子 Agent(编排器模式)
当 maxSpawnDepth: 2 时,子 Agent 可以再派生子 Agent:
主 Agent
└── 编排器子 Agent(depth 1)
├── 工人子 Agent A(depth 2)→ 执行具体任务
├── 工人子 Agent B(depth 2)→ 执行具体任务
└── 工人子 Agent C(depth 2)→ 执行具体任务
结果沿着链条回传:depth-2 → depth-1 → 主 Agent。
| 深度 | 会话键格式 | 角色 | 能否派生 |
|---|---|---|---|
| 0 | agent:<id>:main |
主 Agent | 始终可以 |
| 1 | agent:<id>:subagent:<uuid> |
子 Agent(编排器) | maxSpawnDepth >= 2 |
| 2 | agent:<id>:subagent:<uuid>:subagent:<uuid> |
子子 Agent(工人) | 永远不能 |
8.9.4 命令行控制
/subagents list # 查看当前会话的子 Agent
/subagents spawn main 分析日志 # 手动派生一个子 Agent
/subagents kill <id> # 停止特定子 Agent
/subagents kill all # 停止所有子 Agent
/subagents log <id> 50 # 查看子 Agent 日志
/subagents info <id> # 查看子 Agent 详情
/subagents send <id> 改用新方法 # 向子 Agent 发送消息
/subagents steer <id> 换个方向 # 实时引导子 Agent
8.9.5 工具策略
默认情况下,子 Agent 不获得会话工具(sessions_*)——防止子 Agent 派生更多子 Agent 或访问其他会话。
{
tools: {
subagents: {
tools: {
deny: ["gateway", "cron"], // 额外禁止 gateway 和 cron
},
},
},
}
当 maxSpawnDepth >= 2 时,depth-1 的编排器子 Agent 会自动获得 sessions_spawn、subagents、sessions_list、sessions_history,以便管理其子任务。
8.10 斜杠命令:实时控制
斜杠命令是你在聊天中控制 Agent 的方式。它们分为两类:
8.10.1 指令(Directives)
指令可以嵌入消息中,也可以单独发送。单独发送时会持久化到当前会话。
| 指令 | 功能 | 示例 |
|---|---|---|
/think |
调整思考深度 | /think:high, /t medium |
/fast |
快速模式 | /fast on, /fast off |
/verbose |
详细日志 | /verbose on, /verbose full |
/reasoning |
显示推理过程 | /reasoning on, /reasoning stream |
/elevated |
提权模式 | /elevated on, /elevated full |
/exec |
exec 设置 | /exec host=gateway security=allowlist |
/model |
切换模型 | /model opus, /model 3 |
/queue |
队列设置 | /queue debounce:2s cap:25 |
思考深度级别:
| 级别 | 映射 | 效果 |
|---|---|---|
off |
关闭 | 不使用扩展思考 |
minimal |
think | 基础思考 |
low |
think hard | 较深思考 |
medium |
think harder | 深度思考 |
high |
ultrathink | 最大预算 |
xhigh |
ultrathink+ | 超大预算(仅 GPT-5.2/Codex) |
adaptive |
自适应 | 由提供商管理(Claude 4.6 默认) |
内联 vs 持久化:
# 内联:只影响这条消息
帮我分析这段代码 /think:high
# 持久化:影响当前会话的所有后续消息
/think:high
→ Thinking level set to high.
8.10.2 命令(Commands)
命令必须作为独立消息发送:
/status # 查看当前状态
/tools # 查看当前可用的工具
/compact # 手动压缩上下文
/new # 新会话
/new sonnet # 新会话 + 切换模型
/stop # 停止当前运行
/tts always # 开启语音回复
/usage tokens # 显示 Token 用量
/export-session # 导出当前会话为 HTML
/btw 当前在做什么? # 临时侧问题,不影响会话上下文
8.10.3 /btw:临时侧问题
/btw 是一个独特的设计——它让 Agent 在不改变主会话上下文的情况下回答一个临时问题:
用户:/btw 我们刚才讨论到了哪里?
Agent:[基于当前会话上下文回答,但不写入历史记录]
这适合在长任务进行中快速获取信息,而不打断 Agent 的工作流。
8.10.4 命令权限控制
{
commands: {
native: "auto", // 原生命令(Discord/Telegram)
text: true, // 文本命令解析
bash: false, // ! <cmd> 直接执行 Shell(危险)
config: false, // /config 修改配置(危险)
plugins: false, // /plugins 管理插件(危险)
debug: false, // /debug 运行时覆盖(危险)
allowFrom: { // 命令权限白名单
"*": ["admin_user"],
discord: ["user:123456"],
},
useAccessGroups: true, // 使用访问组权限
},
}
⚠️ 安全建议:
config、bash、plugins、debug默认都是关闭的,因为它们允许通过聊天直接修改配置或执行命令。只在可信环境中启用。
8.11 TTS(文字转语音)
OpenClaw 支持将回复转换为语音,支持多个提供商:
| 提供商 | API Key | 特色 |
|---|---|---|
| ElevenLabs | ELEVENLABS_API_KEY |
高质量多语言语音 |
| Microsoft | 无需 | 通过 Edge TTS,免费但无 SLA |
| OpenAI | OPENAI_API_KEY |
GPT-4o-mini-tts |
8.11.1 配置
{
messages: {
tts: {
auto: "inbound", // off | always | inbound | tagged
provider: "elevenlabs",
providers: {
elevenlabs: {
voiceId: "pMsXgVXv3BLzUgSXRplE",
modelId: "eleven_multilingual_v2",
},
},
},
},
}
auto 模式:
| 模式 | 行为 |
|---|---|
off |
不自动转语音 |
always |
所有回复都转语音 |
inbound |
只在收到语音消息后回复语音 |
tagged |
只在回复中包含 [[tts]] 标签时转语音 |
8.11.2 模型驱动的语音控制
模型可以在回复中嵌入 TTS 指令来动态控制语音参数:
这是正常文本。
[[tts:voiceId=pMsXgVXv3BLzUgSXRplE speed=1.1]]
[[tts:text]](笑声) 再读一遍这首歌。[[/tts:text]]
这允许 Agent 根据上下文选择不同的语气、语速和情感。
8.11.3 运行时控制
/tts status # 查看当前状态
/tts always # 所有回复都转语音
/tts inbound # 只在收到语音后回复语音
/tts provider openai # 切换提供商
/tts limit 2000 # 设置摘要阈值
/tts summary off # 关闭长文本自动摘要
/tts audio 你好世界 # 一次性生成语音
8.12 LLM Task:结构化 JSON 输出
llm-task 是一个可选的插件工具,专门用于需要 JSON 结构化输出的场景——比如工作流引擎中的 LLM 步骤。
8.12.1 启用
{
plugins: {
entries: {
"llm-task": { enabled: true },
},
},
tools: {
allow: ["llm-task"],
},
}
8.12.2 使用场景
{
"prompt": "分析这封邮件的意图和情感倾向",
"input": {
"subject": "紧急:服务器宕机",
"body": "我们的生产服务器已经离线 30 分钟了..."
},
"schema": {
"type": "object",
"properties": {
"intent": { "type": "string" },
"sentiment": { "type": "string", "enum": ["urgent", "normal", "low"] },
"draft_reply": { "type": "string" }
},
"required": ["intent", "sentiment", "draft_reply"]
}
}
返回的 JSON 会自动按照 schema 验证。如果提供了 schema 但输出不符合,工具会返回验证错误。
⚠️ 安全提示:
llm-task是 JSON-only 模式——模型只能输出 JSON,不能调用工具。如果需要 LLM 有工具能力,使用子 Agent(sessions_spawn)代替。
8.13 综合实战:构建一个"代码审查助手"
让我们把本章学到的知识综合起来,构建一个实用的代码审查助手。
8.13.1 需求
一个能自动审查 Git 提交的 Agent,当收到新的 Pull Request 时:
- 获取变更的代码
- 运行测试
- 分析代码质量
- 输出审查报告
8.13.2 实现
Step 1:创建审查 Skill
~/.openclaw/workspace/skills/code-review/SKILL.md:
---
name: code_review
description: 审查 Git 提交或 PR 的代码变更,输出结构化审查报告
metadata:
{
"openclaw":
{
"requires": { "bins": ["git"] },
},
}
---
# 代码审查流程
## 触发条件
当用户要求审查代码、检查 PR 或审查提交时激活。
## 步骤
1. 获取变更范围
- 如果是 PR:用 `exec` 运行 `gh pr diff <pr-number>`
- 如果是提交:用 `exec` 运行 `git show <commit-hash>`
- 如果是当前变更:用 `exec` 运行 `git diff`
2. 运行测试
- 检测测试框架(查找 package.json / pytest.ini / go.mod)
- 运行测试:`npm test` / `pytest` / `go test ./...`
- 如果测试失败,在报告中标记为"阻塞问题"
3. 代码分析
- 使用 `read` 工具逐文件读取变更内容
- 检查以下维度:
a. 安全漏洞(SQL 注入、XSS、硬编码密钥)
b. 性能问题(N+1 查询、内存泄漏、不必要的循环)
c. 代码质量(命名、复杂度、重复代码)
d. 边缘情况处理(空值、错误处理、边界条件)
4. 输出报告
格式如下:
## 审查报告
**审查范围**:[PR/提交描述]
### 测试结果
- 状态:[通过/失败]
- 失败详情:[如有]
### 发现的问题
| 严重度 | 文件 | 行号 | 描述 | 建议 |
|:---:|:---|:---:|:---|:---|
| 高 | path/to/file.ts | 42 | SQL 注入风险 | 使用参数化查询 |
| 中 | path/to/file.ts | 78 | 未处理空值 | 添加 null check |
### 总结
- 高优先级问题:N 个
- 中优先级问题:N 个
- 低优先级问题:N 个
- 建议:[通过/需要修改后通过/拒绝]
Step 2:配置工具权限
{
tools: {
profile: "coding",
allow: ["browser"], // 如果需要查看 PR 网页
},
commands: {
bash: true, // 允许 ! 命令(在可信环境中)
},
}
Step 3:使用
你:审查一下最新的提交
Agent:[执行 git log -1 --oneline]
[执行 git show HEAD]
[检测到测试框架,运行 pytest]
[逐文件分析代码]
[输出审查报告]
8.13.3 进阶:用子 Agent 并行审查
如果审查涉及多个大型文件,可以用子 Agent 并行处理:
用户:审查 PR #123,这个 PR 改了 5 个文件
Agent:[获取 PR diff]
[识别变更文件:file1.ts, file2.ts, file3.ts, file4.ts, file5.ts]
[派生 3 个子 Agent 并行审查]
[等待结果]
[汇总审查报告]
这需要在配置中启用子 Agent 并设置合理的并发数。
8.14 工具体系的设计哲学
理解了工具体系的实现细节后,我们来看看它背后的设计哲学——这有助于你在实际使用中做出更好的决策。
8.14.1 最小权限原则
OpenClaw 的工具权限设计遵循最小权限原则:
默认状态
├── 工具 profile: full(所有内置工具可用)
├── exec host: sandbox(在容器中执行)
├── exec security: deny(禁止主机执行)
└── 子 Agent: 无会话工具(不能派生更多子 Agent)
收紧权限
├── tools.deny: ["exec"] → 禁止命令执行
├── tools.profile: "minimal" → 只有 session_status
├── plugins.deny: [...] → 禁止特定插件
└── skills.allowBundled: [...] → 限制可用技能
8.14.2 能力与知识分离
Skill 只提供"知识"(怎么做),不提供"能力"(能做什么)。这保证了:
- 禁用
exec工具后,即使 Skill 中写了运行 git 命令,Agent 也无法执行 - 禁用
browser工具后,即使 Skill 中写了打开网页,Agent 也无法操作
能力由工具层控制,知识由技能层提供,二者解耦。
8.14.3 插件作为所有权边界
OpenClaw 的架构中,插件 = 所有权边界。每个能力(如图片生成)应该先定义接口契约,再由插件实现。这意味着:
- 切换图片生成提供商不需要改代码——只需要换插件
- 不同插件可以注册同一个能力(如多个语音提供商)
- 核心 OpenClaw 只定义契约,不耦合任何具体实现
本章小结
- OpenClaw 的工具体系是三层架构:工具(能做什么)→ 技能(怎么做)→ 插件(扩展什么)
- 工具通过 allow/deny/profile 精细控制,deny 优先于 allow
- exec 工具支持 sandbox/gateway/node 三种执行位置,配合安全审批机制
- browser 工具支持 isolated(openclaw 档案)和 existing-session(user 档案)两种模式
- web_search 支持 8 个搜索引擎提供商,自动检测 API Key
- Skill 是 Markdown 文件,通过环境门控条件加载,是零代码扩展 Agent 能力的最佳方式
- Plugin 可以注册工具、通道、模型提供商等几乎所有能力,是深度扩展的唯一方式
- 子 Agent 实现并行任务分派,支持嵌套编排器模式
- 斜杠命令分为指令(内联/持久化)和命令(独立消息)两类
下一步
Agent 有了"手脚"(工具体系),接下来要让它"多线操作"——这就是多 Agent 路由的范畴。下一章深入 OpenClaw 的多 Agent 架构,从路由策略到委派模式,让你的系统从"单 Agent"进化到"多 Agent 协作"。