OpenClaw Agent 核心原理
详细讲解 OpenClaw Agent 的运行机制,包括运行时、工具系统、消息处理等核心组件。
概述
OpenClaw 的 Agent 是一个基于**工具调用(Tool Calling)**范式的智能助手,它通过以下核心能力实现复杂任务的自动化处理:
- 智能推理:使用大语言模型(LLM)理解用户意图
- 工具调用:动态选择并执行合适的工具完成任务
- 流式响应:实时输出生成内容,提升用户体验
- 会话管理:维护对话历史,支持上下文延续
- 自适应重试:智能处理错误和认证问题
- 可扩展架构:通过插件系统无缝扩展功能
整体架构
用户输入层
└── CLI / WhatsApp / Telegram / Discord / Slack / Signal / iMessage
OpenClaw Gateway
└── 消息路由 · 会话管理 · 权限控制 · 配置管理
Agent 运行时
├── 1. 请求预处理 (权限检查 · 参数验证 · 钩子触发)
├── 2. 系统提示构建 (工作区文件 · 技能提示 · 工具列表)
├── 3. LLM 调用 (模型选择 · 认证管理 · 流式输出)
├── 4. 工具调度执行 (工具查找 · 参数解析 · 权限检查)
├── 5. 结果处理返回 (工具结果整合 · 流式文本累积)
└── 6. 会话持久化 (消息追加 · 上下文检查 · 自动压缩)
Agent 运行时
运行入口
async function runEmbeddedPiAgent(
params: RunEmbeddedPiAgentParams
): Promise<EmbeddedPiRunResult> {
// 1. 生成运行 ID
const runId = generateSecureToken(12);
// 2. 创建运行句柄
const runHandle: EmbeddedPiQueueHandle = {
queueMessage: (text: string) => { /* 消息队列逻辑 */ },
isStreaming: () => activeStreaming,
isCompacting: () => activeCompacting,
abort: () => { /* 中止运行 */ },
};
// 3. 注册运行状态
setActiveEmbeddedRun(params.sessionId, runHandle, params.sessionKey);
// 4. 执行主运行循环(带重试)
const result = await runMainLoop({
...params,
runId,
runHandle,
cleanup: () => clearActiveEmbeddedRun(params.sessionId, runHandle),
});
return result;
}
工具调用机制
工具定义
type AgentTool = {
// 基础信息
name: string;
description: string;
label?: string;
// 参数 schema
parameters: JsonSchema;
// 处理函数
handler: ToolHandler;
// 权限控制
ownerOnly?: boolean;
actionGate?: ActionGate<Record<string, boolean | undefined>>;
// 可选性
optional?: boolean;
};
type ToolHandler = (
params: Record<string, unknown>,
context: ToolContext,
) => Promise<AgentToolResult>;
type ToolContext = {
config: OpenClawConfig;
workspaceDir: string;
agentDir: string;
agentId: string;
sessionKey: string;
sessionId: string;
senderIsOwner: boolean;
sandboxed?: boolean;
};
Bash 工具示例
const bashTool: AgentTool = {
name: "bash",
description: "Execute shell commands on the host system",
label: "Bash",
parameters: {
type: "object",
properties: {
command: {
type: "string",
description: "Shell command to execute",
},
timeout_ms: {
type: "number",
description: "Timeout in milliseconds (optional, default: 300000)",
},
},
required: ["command"],
},
ownerOnly: true, // 仅所有者可以执行
handler: async (params, context) => {
const { command, timeout_ms } = params;
// 权限检查
if (!context.senderIsOwner) {
throw new ToolAuthorizationError("bash is owner-only");
}
// 执行命令
const result = await runExec(command, {
timeout: timeout_ms ?? 300_000,
cwd: context.workspaceDir,
});
return {
text: result.stdout,
error: result.stderr,
exitCode: result.exitCode,
};
},
};
系统提示构建
提示词结构
完整的系统提示包含以下部分:
# OpenClaw Agent
## Capabilities
You are an AI assistant with access to various tools to complete tasks.
## Tool Names
[工具名称列表 - 例如: bash, read, write, edit, browser]
## Tools
[工具详细描述 - 每个 tool 的 name, description, parameters]
## Skills
[技能提示 - 来自 SKILL.md]
## Project Context
[工作区文件内容 - AGENTS.md, TOOLS.md, SKILL.md]
## Runtime
- Host: openclaw
- OS: darwin 24.0.0
- Node: v22.12.0
- Model: anthropic/claude-opus-4-6
## User Timezone
Timezone: UTC+8
会话管理
会话存储
type SessionStore = Record<string, SessionEntry>;
type SessionEntry = {
// 时间戳
createdAt: string;
updatedAt: string;
// 消息历史
transcript: Message[];
// 元数据
metadata?: {
channelId?: string;
threadId?: string;
model?: string;
provider?: string;
};
// 会话配置
config?: SessionConfig;
};
会话压缩
当上下文窗口接近满时,系统会自动压缩会话:
async function compactEmbeddedPiSession(
params: CompactEmbeddedPiSessionParams
): Promise<EmbeddedPiCompactResult> {
// 1. 加载会话
const session = await loadSessionFile(sessionFile);
// 2. 生成摘要(使用 LLM)
const summaryPrompt = buildSummaryPrompt(session.transcript);
const summary = await runEmbeddedPiAgent({
systemPrompt: "Summarize the conversation concisely.",
userPrompt: summaryPrompt,
tools: [],
});
// 3. 保留重要消息并创建压缩后的会话
const compacted: SessionFile = {
...session,
transcript: [
...importantMessages,
{
role: "system",
content: `Conversation summary: ${summary.text}`,
},
],
};
// 4. 保存
await writeSessionFile(sessionFile, compacted);
return { ok: true, compacted: true, result: {...} };
}
错误处理与重试
重试策略
const BASE_RUN_RETRY_ITERATIONS = 24;
const RUN_RETRY_ITERATIONS_PER_PROFILE = 8;
const MIN_RUN_RETRY_ITERATIONS = 32;
const MAX_RUN_RETRY_ITERATIONS = 160;
// 指数退避策略
const OVERLOAD_FAILOVER_BACKOFF_POLICY: BackoffPolicy = {
initialMs: 250,
maxMs: 1500,
factor: 2,
jitter: 0.2,
};
错误分类
function isContextOverflowError(error: unknown): boolean {
const message = (error as Error).message ?? "";
return (
message.includes("context length exceeded") ||
message.includes("maximum context length")
);
}
function isRateLimitError(error: unknown): boolean {
const message = (error as Error).message ?? "";
return (
message.includes("rate limit") ||
message.includes("too many requests") ||
message.includes("429")
);
}
function isAuthError(error: unknown): boolean {
const message = (error as Error).message ?? "";
return (
message.includes("unauthorized") ||
message.includes("invalid api key") ||
message.includes("401")
);
}
钩子系统
钩子类型
type PluginHookName =
| "before_model_resolve" // 模型解析前
| "before_prompt_build" // 提示构建前
| "before_agent_start" // Agent 启动前
| "llm_input" // LLM 输入时
| "llm_output" // LLM 输出时
| "agent_end" // Agent 结束时
| "before_compaction" // 压缩前
| "after_compaction" // 压缩后
| "message_received" // 消息接收时
| "message_sending" // 消息发送前
| "message_sent" // 消息发送后
| "before_tool_call" // 工具调用前
| "after_tool_call" // 工具调用后
钩子注册示例
// 在插件中注册钩子
export default function registerPlugin(api: OpenClawPluginApi) {
// 注册 before_agent_start 钩子
api.registerHook("before_agent_start", async (event, ctx) => {
console.log("Agent starting:", event.sessionId);
// 可以修改系统提示
return {
systemPrompt: event.systemPrompt + "\n\nCustom hook injected.",
};
});
// 注册 after_tool_call 钩子
api.registerHook("after_tool_call", async (event, ctx) => {
console.log("Tool called:", event.toolName, event.result);
return event.result;
});
}
子代理系统
子代理参数
type SubagentRunParams = {
sessionKey: string;
message: string;
extraSystemPrompt?: string;
lane?: string;
deliver?: boolean;
idempotencyKey?: string;
};
type SubagentRunResult = {
runId: string;
};
type SubagentWaitParams = {
runId: string;
timeoutMs?: number;
};
type SubagentWaitResult = {
status: "ok" | "error" | "timeout";
error?: string;
};
子代理生成
const spawnTool: AgentTool = {
name: "sessions_spawn",
description: "Spawn a subagent to handle a task",
parameters: {
type: "object",
properties: {
message: {
type: "string",
description: "Message for the subagent",
},
system_prompt: {
type: "string",
description: "Custom system prompt (optional)",
},
lane: {
type: "string",
description: "Execution lane (optional)",
},
},
required: ["message"],
},
handler: async (params, context) => {
const { message, system_prompt, lane } = params;
// 1. 生成子代理会话键
const subSessionKey = generateSubagentSessionKey(context.sessionKey);
// 2. 运行子代理
const result = await context.runtime.subagent.run({
sessionKey: subSessionKey,
message,
extraSystemPrompt: system_prompt,
lane,
deliver: false,
});
return {
runId: result.runId,
sessionKey: subSessionKey,
};
},
};
总结
核心原理
- 工具调用驱动 - LLM 根据用户意图动态选择工具,工具执行结果返回给 LLM 继续推理
- 流式响应 - 实时输出生成内容,支持中途断开和恢复
- 智能会话管理 - 自动压缩长对话,上下文窗口保护
- 鲁棒错误处理 - 多层重试机制,认证资料自动轮换
- 可扩展钩子系统 - 21 种钩子点覆盖整个生命周期
- 子代理支持 - 并行任务处理,专业化子代理
关键设计原则
- 工具优先 - 每个工具有明确的 schema 和处理函数
- 安全第一 - 权限控制、路径安全检查
- 可观测性 - 详细的日志和诊断信息
- 可扩展性 - 通过插件系统添加新功能
- 鲁棒性 - 完善的错误处理和重试机制
- 性能优化 - 上下文窗口、令牌管理、流式批处理