小学子讲技术,带你探索AI Agent的底层设计
想象一下,AI Agent就像一个拥有各种工具的工程师。它需要发现工具、理解工具、选择工具、执行工具——这整个流程就是所谓的工具管道(Tool Pipeline)。
今天,小学子带大家深入探索OpenClaw的工具管道架构,看看它是如何设计出一个灵活,安全、可扩展的工具系统的。
┌─────────────────────────────────────────────────────────────────────────────┐
│ OpenClaw 工具管道架构 │
├─────────────────────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 工具定义层 │ -> │ 工具过滤层 │ -> │ 工具暴露层 │ -> │ 工具执行层 │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │ │
│ v v v v │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ │ 核心工具 │ │ 策略过滤 │ │ System │ │ Sandbox │
│ │ 技能系统 │ │ Provider │ │ Prompt │ │ Execution │
│ │ 插件工具 │ │ 技能门控 │ │ Tool Schema│ │ 容器运行 │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
OpenClaw内置了丰富的核心工具,涵盖文件操作、浏览器控制、消息发送、节点管理等领域:
| 工具分类 | 包含工具 | 功能描述 |
|---|---|---|
| 文件系统 | read, write, edit, apply_patch |
文件的读写编辑 |
| 运行时 | exec, bash, process |
执行Shell命令,管理后台进程 |
| 浏览器 | browser |
控制OpenClaw管理的专用浏览器 |
| 消息 | message |
跨平台发送消息(Discord/Slack/Telegram等) |
| 节点 | nodes |
发现并控制配对的设备节点 |
| 会话 | sessions_* |
会话列表、历史、发送、孵化 |
| 自动化 | cron, gateway |
定时任务和网关管理 |
为了简化配置,OpenClaw引入了工具组的概念:
{
// 工具组示例
tools: {
allow: ["group:fs", "group:runtime", "browser"],
},
}
可用工具组:
group:fs → read, write, edit, apply_patchgroup:runtime → exec, bash, processgroup:sessions → sessions_list, sessions_history, sessions_send, sessions_spawn, session_statusgroup:memory → memory_search, memory_getgroup:web → web_search, web_fetchgroup:ui → browser, canvasgroup:automation → cron, gatewaygroup:messaging → messagegroup:nodes → nodesOpenClaw采用适配器模式来统一不同类型工具的接口。核心思路是:
任何工具都可以被适配成统一的函数调用格式
模式A:HTTP Daemon(信号示例)
// signal-cli 运行JSON-RPC over HTTP
// 事件流走SSE: /api/v1/events
// 健康检查: /api/v1/check
模式B:stdio子进程(遗留iMessage)
// OpenClaw spawn imsg rpc 作为子进程
// JSON-RPC通过stdin/stdout按行传递
// 无需TCP端口,守护进程非必需
每个工具都遵循统一的schema定义:
// 工具定义的适配器接口
interface ToolDefinition {
name: string;
description: string;
parameters: {
type: "object";
properties: Record<string, Schema>;
required?: string[];
};
}
技能是OpenClaw的教学系统——它告诉Agent如何正确使用各种工具。技能采用AgentSkills兼容格式,核心是SKILL.md文件:
---
name: hello_world
description: 一个简单的问候技能
metadata: {
"openclaw": {
"requires": { "bins": ["curl"], "env": ["API_KEY"] },
"emoji": "👋"
}
}
---
# Hello World Skill
当用户请求问候时,使用 `echo` 工具说"你好!"。
优先级(高到低):
workspace/skills → ~/.openclaw/skills → bundled skills
技能在加载时会被条件过滤:
{
"metadata": {
"openclaw": {
"requires": {
"bins": ["uv"], // 必须存在的二进制
"env": ["GEMINI_API_KEY"], // 必须存在的环境变量
"config": ["browser.enabled"] // 必须开启的配置
},
"os": ["darwin", "linux"] // 平台限制
}
}
}
OpenClaw支持细粒度的工具策略控制:
{
tools: {
// 基础工具配置
profile: "coding", // minimal | coding | messaging | full
// 白名单/黑名单
allow: ["read", "write", "browser"],
deny: ["exec", "process"],
// Provider特定策略
byProvider: {
"google-antigravity": { profile: "minimal" },
"openai/gpt-5.2": { allow: ["group:fs"] }
},
// 循环检测
loopDetection: {
enabled: true,
warningThreshold: 10,
criticalThreshold: 20
}
}
}
全局配置 (tools.*)
↓
Provider配置 (tools.byProvider.*)
↓
Agent配置 (agents.list[].tools.*)
↓
运行时覆盖
1. 工具定义
├── 核心工具注册
├── 插件工具注册
└── 技能工具注册
2. 工具过滤
├── 工具组展开
├── 配置文件应用
├── 技能门控过滤
└── Provider策略过滤
3. 工具暴露
├── System Prompt注入(人类可读)
├── Tool Schema注入(机器可读)
└── 技能列表注入
4. 工具执行
├── 参数验证
├── 策略检查
├── Sandbox容器执行
└── 结果返回
// 1. 工具定义阶段
const toolDefinitions = [
{
name: "read",
description: "Read file contents",
parameters: {
type: "object",
properties: {
path: { type: "string", description: "File path to read" },
limit: { type: "number" },
offset: { type: "number" }
},
required: ["path"]
}
},
// ... 更多工具
];
// 2. 工具过滤阶段
function filterTools(config: OpenClawConfig, skills: Skill[]): Tool[] {
let tools = expandToolGroups(toolDefinitions);
// 应用allow/deny
if (config.tools.deny) {
tools = tools.filter(t => !config.tools.deny.includes(t.name));
}
if (config.tools.allow) {
tools = tools.filter(t => config.tools.allow.includes(t.name));
}
// 应用技能门控
skills = skills.filter(skill => checkGating(skill));
return tools;
}
// 3. 工具暴露阶段
function exposeTools(tools: Tool[]): void {
// System Prompt
const promptText = tools.map(t =>
`- ${t.name}: ${t.description}`
).join('\n');
// Tool Schema (JSON)
const toolSchemas = tools.map(t => ({
type: "function",
function: t.parameters
}));
// 注入到模型
model.setSystemPrompt(promptText);
model.setTools(toolSchemas);
}
// 4. 工具执行阶段
async function executeTool(toolCall: ToolCall): Promise<ToolResult> {
// 策略检查
if (!checkToolPolicy(toolCall.name)) {
throw new Error("Tool not allowed");
}
// Sandbox执行
if (session.sandbox.enabled) {
return sandboxedExecute(toolCall);
}
// Host执行
return hostExecute(toolCall);
}
OpenClaw支持Docker容器隔离工具执行:
{
agents: {
defaults: {
sandbox: {
mode: "non-main", // off | non-main | all
scope: "session", // session | agent | shared
workspaceAccess: "none" // none | ro | rw
}
}
}
}
请求工具执行
↓
检查工具策略(allow/deny)
↓
检查沙箱模式(off/non-main/all)
↓
创建/复用容器
↓
挂载工作空间
↓
执行工具
↓
返回结果
子代理(Sub-agents)是OpenClaw的任务分发机制:
{
// 孵化一个子代理
sessions_spawn: {
task: "研究最新的AI论文",
agentId: "researcher",
runtime: "subagent", // subagent | acp
thread: true, // 线程绑定
sandbox: "inherit" // 继承或强制沙箱
}
}
| 深度 | 角色 | 可用工具 |
|---|---|---|
| 0 | 主Agent | 全部(除session tools) |
| 1 | 子代理(Orchestrator) | +sessions_spawn, +subagents |
| 2 | 子子代理(Worker) | 无session tools |
OpenClaw的工具管道架构体现了几个核心设计理念:
这套架构让OpenClaw能够灵活应对各种场景——从简单的文件操作到复杂的跨平台自动化,都能游刃有余。
参考来源