OpenClaw 源码解读(6): —— 自动化工具链
拆解 OpenClaw 自动化工具链三大核心:CDP 无头浏览器实现网页视觉抓取与操控、跨会话协同工具实现多工作区消息调度,以及 ClawHub 插件生态的沙箱隔离与动态挂载机制。
在上一篇中,我们见识了 OpenClaw 的 A2UI 渲染引擎,看到了 Agent 是如何在我们的屏幕上“作画”的。但这还不够,一个真正的全能 AI 助手不能只是个会画图的“嘴炮”。
当你说“帮我查一下今天 Hacker News 的热榜,然后发到我的开发者群里”时,Agent 需要有“眼睛”去浏览网页,还需要有“手”去跨越会话发送消息。
这就是 OpenClaw 自动化工具链(Tools)的职责所在。今天,我们就来翻开源码,拆解这套赋予大模型实体行动能力的系统。
浏览器控制:不仅仅是爬虫,而是真正的“数字替身”
很多早期的 AI 助手如果要获取网页信息,往往只是在后台跑一个 curl 或者请求一下普通的 HTTP 接口。但作为开发者我们都知道,现在的 Web 应用大多是 SPA(单页应用),大量的 DOM 是由 JavaScript 动态渲染的,单纯拉取 HTML 源码根本拿不到有效数据。
OpenClaw 的做法非常硬核:直接托管一个无头浏览器(Headless Browser),通过 CDP(Chrome DevTools Protocol)协议进行底层操作。
在源码的 skills/browser 目录中,我们可以看到它是如何定义浏览器的“视觉抓取”和“行为操作”的。
// skills/browser/BrowserTool.ts (源码概念简化版)
import { Tool, ToolContext } from '@openclaw/core';
import { BrowserManager } from './BrowserManager';
export class BrowserNavigateTool extends Tool {
name = 'browser_navigate';
description = '导航到指定 URL 并返回页面的视觉快照与可交互元素树(DOM Tree)。';
async execute(params: { url: string }, context: ToolContext) {
const page = await BrowserManager.getOrCreatePage(context.workspaceId);
// 1. 导航到目标网页
await page.goto(params.url, { waitUntil: 'networkidle2' });
// 2. 注入脚本:给所有可点击元素打上数字标签 (BBox)
const interactableTree = await page.evaluate(() => {
return window.__openclaw_mark_elements();
});
// 3. 抓取视觉快照 (带标签)
const screenshot = await page.screenshot({ encoding: 'base64' });
// 将结构化 DOM 和截图一并丢回给 Agent
return {
snapshot: screenshot,
tree: interactableTree
};
}
}
通过这种方式,网页在 Agent 眼里不再是一堆杂乱的 HTML 标签,而是一张带有编号的“地图”。Agent 看了截图后,可以接着调用 browser_click({ targetId: 42 })。这赋予了 OpenClaw 极强的泛化能力,即使是没有 API 接口的老旧后台,Agent 也能像真人一样点进去帮你操作。
跨会话协同:Agent 的“分身术”
浏览完网页,拿到了数据,下一步是“发到开发者群里”。这就涉及到 OpenClaw 中非常精妙的跨会话协同工具集:sessions_*。
在《OpenClaw 源码解读(3): Workspaces 与多智能体路由》中我们讲过,每个群聊/单聊都是一个独立的 Workspace。那主会话的超级 Agent,如何干涉其他工作区呢?
OpenClaw 提供了一组内置的原生工具,允许高权限的 Agent 查询并操作网关中的其他会话流。
// core/tools/sessions/SessionSendTool.ts (源码概念简化版)
export class SessionSendTool extends Tool {
name = 'sessions_send';
description = '作为系统指令或以 Agent 身份向其他会话/群组发送消息。';
async execute(params: { targetSessionId: string, content: string }, context: ToolContext) {
// 权限校验:只有主会话 (Main Session) 的 Agent 有权调用
if (!context.permissions.canCrossSession) {
throw new Error("Permission denied: Only main session can cross-post.");
}
const gateway = context.getGatewayClient();
// 跨空间投递消息
await gateway.sendMessage({
sessionId: params.targetSessionId,
message: {
role: 'assistant',
content: params.content
}
});
return { status: 'success', deliveredTo: params.targetSessionId };
}
}
有了 sessions_list (获取所有活跃群组列表) 和 sessions_send (跨频道发送),你的私人 Agent 就变成了一个超级调度中心(Dispatcher)。你可以对它说:“把上周五我和业务合伙人讨论的架构图,转发到研发一部的 Slack 频道里,并@所有人查收”,Agent 就能自行编排这几个工具完成任务。
技能扩展体系:ClawHub 的插件生态边界
作为一个有追求的独立开发者或 SaaS 创业者,我们一定会有定制化的需求。比如,我想让 Agent 直接查询我服务器的数据库,或者帮我发推文。
OpenClaw 并没有把所有工具都写死在源码里,而是设计了一个名为 ClawHub 的技能注册表(Registry)。
在这个体系中,工具(Tools)被严格划分为两类:
- 原生工具(Native Tools): 比如文件读写、跨会话调用。这些直接运行在 Node.js 主进程中,拥有最高权限。
- 扩展插件(Plugins/Skills): 从 ClawHub 下载或用户自定义的脚本。
为了防止第三方插件搞破坏,OpenClaw 在安装权限验证和执行边界上做了严格的隔离:
// core/registry/SkillLoader.ts (源码概念简化版)
export class SkillLoader {
async loadSkill(manifestUrl: string) {
const manifest = await fetchManifest(manifestUrl);
// 1. 权限审查:如果插件申请了高危权限 (如执行 bash),必须人工弹窗确认
if (manifest.requestedPermissions.includes('system.run')) {
await this.promptUserForConsent(manifest.name, 'system.run');
}
// 2. 沙箱隔离:非原生工具一律放入 Sandbox 环境运行
const executable = createSandboxWrapper(manifest.entrypoint);
// 3. 动态挂载到当前 Workspace 的 TOOLS.md
await WorkspaceManager.mountTool(executable);
}
}
通过这套机制,开发一个 OpenClaw 的新技能,就像开发一个简单的无服务器函数(Serverless Function)一样简单。定义好入参、出参和功能描述,扔给 Agent 就能直接调用。
总结
如果说 Gateway 是神经中枢,A2UI 是画板,那么 Tools 工具链就是 OpenClaw 切实改变物理与数字世界的杠杆。
- CDP 浏览器托管 赋予了它洞察任何现代 Web 应用的“眼睛”。
- 跨会话原生工具 让它拥有了分发调度全局任务的“手”。
- ClawHub 技能体系 则保证了这套系统能够像拼乐高一样无限扩展,同时守住安全底线。
到这里,关于 OpenClaw 纯软件层面的核心架构我们已经剖析得差不多了。但在实际使用中,我们不可能永远坐在电脑前打字。
下一篇,我们将看看 OpenClaw 是如何突破设备壁垒的。敬请期待第 7 篇,关于跨平台语音唤醒实现机制。我们下期见!