OpenClaw 学习系列之八:Agent 运行机制
Agent 运行机制
📚 学习路径:本文档是架构文档的第 6 部分。建议按顺序阅读:
- 01. 技术基础 - 了解 TypeScript 技术特性
- 02. 整体框架 - 理解 OpenClaw 架构
- 03. 消息流转 - 掌握消息生命周期
- 04. 设计原理 - 理解反共识设计
- 05. Gateway 深度解析 - 理解控制平面
前言
Agent 是 OpenClaw 的核心处理引擎,负责组装上下文、调用 AI 模型、执行工具操作。本文档将深入解析 Agent 的运行机制、故障转移策略以及核心设计。
通过阅读本文档,你将能够:
- 理解 Agent Loop 的执行流程
- 掌握上下文组装和模型调用机制
- 了解故障转移和容错策略
- 理解工具调用和流式处理
一、Agent 概述
1.1 Agent 的作用
Agent 是真正干活的核心引擎,负责:
- ✅ 组装上下文:加载会话历史、系统提示词、记忆检索
- ✅ 调用 AI 模型:与 AI 模型交互,获取回复
- ✅ 执行工具:执行命令行、浏览器、文件操作等工具
- ✅ 保存状态:保存会话状态到磁盘
1.2 Agent 框架
OpenClaw 支持调用已有的 CLI Agent(如 Claude Code),但默认情况下使用基于 Pi-Agent 框架的嵌入式 Agent 运行时。
Pi-Agent 框架的优势:
| 特性 | 说明 |
|---|---|
| 高扩展性 | 满足 OpenClaw 定制化需求 |
| 大模型支持 | 支持多种大模型供应商 |
| Session 管理 | 完善的会话管理机制 |
| 工具定制 | 灵活的工具定制化能力 |
| 流式输出 | 支持流式响应输出 |
| 消息订阅 | 支持事件订阅机制 |
1.3 Agent 架构
二、Agent Loop 执行流程
2.1 执行流程概览
2.2 详细步骤
步骤 1:消息接收
- 接收来自 Gateway 的消息
- 解析消息内容和元数据
- 确定会话标识(Session Key)
步骤 2:上下文组装
- 加载会话历史(从
.jsonl文件) - 组装系统提示词(AGENTS.md、SOUL.md 等)
- 记忆检索(搜索相关历史记忆)
- 工具注册(准备可用的工具列表)
步骤 3:模型调用
- 调用 AI 模型获取回复
- 流式接收响应
- 实时检测工具调用
步骤 4:工具执行
- 如果 AI 需要调用工具,执行工具
- 返回工具结果给 AI
- AI 继续生成最终回复
步骤 5:回复发送
- 将 AI 回复发送回渠道
- 格式化输出内容
- 处理流式输出
步骤 6:状态保存
- 保存会话状态到磁盘
- 更新记忆索引
- 记录使用统计
三、上下文组装
3.1 上下文组件
export async function buildAgentContext(
route: RouteDecision,
config: OpenClawConfig,
): Promise<AgentContext> {
// 1. 加载会话历史
const sessionHistory = await loadSessionHistory(route.sessionKey);
// 2. 组装系统提示词
const systemPrompt = await buildSystemPrompt(config);
// 3. 记忆检索
const memories = await searchMemory(route.sessionKey, route.content);
// 4. 工具注册
const tools = await registerTools(config.tools);
return {
sessionHistory,
systemPrompt,
memories,
tools,
// ... 更多上下文信息
};
}
3.2 会话历史加载
代码位置:src/agents/session-loader.ts
export async function loadSessionHistory(
sessionKey: string,
): Promise<SessionMessage[]> {
// 1. 确定会话文件路径
const sessionPath = resolveSessionFilePath(sessionKey);
// 2. 读取 JSONL 文件
const lines = await fs.readFile(sessionPath, 'utf-8');
// 3. 解析每一行
const messages = lines
.split('\n')
.filter(line => line.trim())
.map(line => JSON.parse(line));
// 4. 返回消息列表
return messages;
}
存储格式:
~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl
JSONL 格式示例:
{"role": "user", "content": "你好", "timestamp": "2024-01-01T12:00:00Z"}
{"role": "assistant", "content": "你好!有什么可以帮助你的?", "timestamp": "2024-01-01T12:00:01Z"}
{"role": "user", "content": "帮我查一下天气", "timestamp": "2024-01-01T12:00:02Z"}
3.3 系统提示词组装
代码位置:src/agents/prompt-builder.ts
export async function buildSystemPrompt(
config: OpenClawConfig,
): Promise<string> {
const parts: string[] = [];
// 1. 基础系统提示词
parts.push(config.systemPrompt || DEFAULT_SYSTEM_PROMPT);
// 2. AGENTS.md 文件内容
const agentsContent = await readAgentsFile();
if (agentsContent) {
parts.push(agentsContent);
}
// 3. SOUL.md 文件内容
const soulContent = await readSoulFile();
if (soulContent) {
parts.push(soulContent);
}
// 4. 工具描述
const toolsDescription = buildToolsDescription(config.tools);
if (toolsDescription) {
parts.push(toolsDescription);
}
// 5. 合并所有部分
return parts.join('\n\n');
}
提示词文件位置:
~/.openclaw/agents/<agentId>/AGENTS.md- Agent 行为描述~/.openclaw/agents/<agentId>/SOUL.md- Agent 个性描述
3.4 记忆检索
代码位置:src/agents/memory-search.ts
export async function searchMemory(
sessionKey: string,
query: string,
): Promise<MemoryResult[]> {
// 1. 向量搜索
const vectorResults = await vectorSearch(query);
// 2. 关键词搜索
const keywordResults = await keywordSearch(query);
// 3. 结果融合
const mergedResults = mergeHybridResults(
vectorResults,
keywordResults,
alpha = 0.7, // 向量搜索权重
);
// 4. 返回前 N 个结果
return mergedResults.slice(0, MAX_MEMORY_RESULTS);
}
混合检索:
- 向量搜索:基于语义相似度
- 关键词搜索:基于 BM25 算法
- 结果融合:加权合并两种搜索结果
3.5 工具注册
export async function registerTools(
config: ToolConfig[],
): Promise<Tool[]> {
const tools: Tool[] = [];
// 1. 内置工具
tools.push(...BUILTIN_TOOLS);
// 2. 自定义工具
for (const toolConfig of config) {
const tool = await loadCustomTool(toolConfig);
tools.push(tool);
}
// 3. 过滤不可用工具
const availableTools = tools.filter(tool => tool.isAvailable());
return availableTools;
}
内置工具:
exec- 命令行执行browser- 浏览器操作file_read- 文件读取file_write- 文件写入memory_search- 记忆搜索
四、模型调用
4.1 流式调用
代码位置:src/agents/openai-ws-connection.ts
export async function* streamChatCompletion(
params: ChatCompletionParams,
): AsyncGenerator<StreamChunk> {
const stream = await openai.chat.completions.create({
model: params.model,
messages: params.messages,
tools: params.tools,
stream: true, // 启用流式
});
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content;
const toolCall = chunk.choices[0]?.delta?.tool_calls;
// 实时处理每个 chunk
if (content) {
yield { type: 'content', data: content };
}
if (toolCall) {
yield { type: 'tool_call', data: toolCall };
}
}
}
4.2 工具调用检测
代码位置:src/agents/pi-embedded-runner/attempt.ts
async function* processStream(stream: AsyncIterable<StreamChunk>) {
const toolCallBuffer: ToolCall[] = [];
for await (const chunk of stream) {
if (chunk.type === 'content') {
// 普通内容,直接转发给用户
yield { type: 'content', data: chunk.data };
}
else if (chunk.type === 'tool_call') {
// 检测到工具调用,但不阻塞
toolCallBuffer.push(chunk.data);
// 异步启动工具执行
executeToolAsync(chunk.data).then(result => {
// 工具完成后,通过回调注入结果
injectToolResult(result);
});
}
}
}
4.3 模型配置
代码位置:src/agents/model-resolver.ts
export function resolveModel(
provider: string,
modelId: string,
agentDir: string,
config: OpenClawConfig,
): ModelInfo {
// 1. 查找模型配置
const modelConfig = config.models?.[modelId];
// 2. 解析上下文窗口
const contextWindow = modelConfig?.contextWindow || DEFAULT_CONTEXT_WINDOW;
// 3. 解析支持的特性
const features = modelConfig?.features || {};
return {
id: modelId,
provider,
contextWindow,
features,
// ... 更多模型信息
};
}
五、工具执行
5.1 工具执行流程
5.2 工具执行器
export async function executeTool(
toolCall: ToolCall,
sandbox: Sandbox,
): Promise<ToolResult> {
// 1. 解析工具参数
const { command, args } = parseToolCall(toolCall);
// 2. 在沙箱中执行
const result = await sandbox.exec(command, args);
// 3. 格式化结果
return {
success: result.exitCode === 0,
output: result.stdout,
error: result.stderr,
exitCode: result.exitCode,
};
}
5.3 沙箱隔离
export class Sandbox {
constructor(private config: SandboxConfig) {
// 初始化沙箱环境
}
async exec(command: string, args: string[]): Promise<ExecResult> {
// 1. 验证命令安全性
if (!this.isCommandSafe(command)) {
throw new Error('Command not allowed');
}
// 2. 限制资源使用
const limits = this.config.limits;
const options = {
timeout: limits.timeout,
maxMemory: limits.maxMemory,
};
// 3. 执行命令
const result = await this.runCommand(command, args, options);
return result;
}
private isCommandSafe(command: string): boolean {
// 检查命令是否在白名单中
return ALLOWED_COMMANDS.includes(command);
}
}
沙箱限制:
| 限制类型 | 说明 | 默认值 |
|---|---|---|
| 超时 | 命令执行超时时间 | 30 秒 |
| 内存 | 最大内存使用 | 512 MB |
| CPU | CPU 使用限制 | 50% |
| 网络 | 网络访问限制 | 禁止(主会话除外) |
六、故障转移机制
6.1 故障转移策略
为了能 24×7 持续运行,不能因为一些异常就停止。OpenClaw 实现了完整的故障转移机制:
6.2 Auth Profile 轮换
当一个 API Key 遇到速率限制或认证失败时,自动切换到下一个可用的 Profile。
代码位置:src/agents/pi-embedded-runner/run.ts
const profileOrder = resolveAuthProfileOrder({
cfg: params.config,
store: authStore,
provider,
preferredProfile: preferredProfileId,
});
// 主执行循环,支持故障转移
while (true) {
const attempt = await runEmbeddedAttempt({
sessionId: params.sessionId,
sessionKey: params.sessionKey,
// ... 大量参数
});
// 处理认证/速率限制故障转移
if (shouldRotate) {
const rotated = await advanceAuthProfile();
if (rotated) continue;
}
return {
payloads: payloads.length ? payloads : undefined,
meta: {
durationMs: Date.now() - started,
agentMeta,
aborted,
systemPromptReport: attempt.systemPromptReport,
},
};
}
6.3 上下文溢出自动压缩
当会话过长时,自动压缩历史消息。
if (isContextOverflowError(errorText)) {
if (!overflowCompactionAttempted) {
const compactResult = await compactEmbeddedPiSessionDirect({
sessionId: params.sessionId,
sessionKey: params.sessionKey,
// ...
});
if (compactResult.compacted) {
continue; // 使用压缩后的会话重试
}
}
}
6.4 思考级别降级
当模型不支持扩展思考模式时,自动降级到基本模式。
代码位置:src/agents/pi-embedded-runner/run.ts
const { model, error, authStorage, modelRegistry } = resolveModel(
provider,
modelId,
agentDir,
params.config,
);
const ctxInfo = resolveContextWindowInfo({
cfg: params.config,
provider,
modelId,
modelContextWindow: model.contextWindow,
defaultTokens: DEFAULT_CONTEXT_TOKENS,
});
七、核心代码文件索引
| 文件路径 | 功能 | 重要性 |
|---|---|---|
| src/agents/pi-tools.ts | 工具定义和创建 | ⭐⭐⭐⭐⭐ |
| src/agents/context.ts | 上下文管理 | ⭐⭐⭐⭐⭐ |
| src/agents/pi-embedded-runner/run.ts | Agent 运行器 | ⭐⭐⭐⭐⭐ |
| src/agents/session-loader.ts | 会话加载 | ⭐⭐⭐⭐ |
| src/agents/prompt-builder.ts | 提示词构建 | ⭐⭐⭐⭐ |
| src/agents/memory-search.ts | 记忆检索 | ⭐⭐⭐⭐ |
| src/agents/openai-ws-connection.ts | OpenAI 连接 | ⭐⭐⭐⭐ |
| src/agents/model-resolver.ts | 模型解析 | ⭐⭐⭐⭐ |
| src/agents/bash-tools.ts | Bash 工具 | ⭐⭐⭐ |
| src/agents/sandbox.ts | 沙箱隔离 | ⭐⭐⭐ |
八、下一步
恭喜你完成了 Agent 运行机制的学习!接下来建议:
- 📖 阅读 07. 会话管理 - 了解会话生命周期
- 🔄 查看 03. 消息流转 - 理解完整消息流程
- 🛠️ 探索 message_flow/ - 查看详细步骤文档
通过理解 Agent 的工作原理,你已经掌握了 OpenClaw 的核心处理引擎!
更多推荐

所有评论(0)