OpenClaw Agent Loop 机制源码深度分析(一)

OpenClaw Agent Loop 机制源码深度分析

基于源码的全面解析,帮助你深入理解 OpenClaw 的 Agent 循环执行机制

目录


概述

OpenClaw 的 Agent Loop(代理循环) 是系统的核心执行引擎,负责接收消息、构建上下文、调用 LLM、执行工具、处理响应,形成一个完整的对话循环。

核心特性

支持功能
流式响应
上下文窗口管理
工具策略控制
错误恢复
Agent Loop


接收消息
构建上下文
调用 LLM
有工具调用?
执行工具
返回结果
压缩上下文

循环流程





开始
接收消息
构建系统提示词
加载会话历史
调用 LLM
工具调用?
执行工具
生成回复
压缩会话
继续?
结束


架构设计

模块结构

复制代码
src/agents/pi-embedded-runner/
├── run.ts                          # 主运行入口
├── run/
│   ├── params.ts                  # 运行参数
│   ├── attempt.ts                 # 单次执行尝试
│   ├── payloads.ts                # 载荷构建
│   └── images.ts                  # 图片处理
├── compact.ts                      # 会话压缩
├── runs.ts                         # 运行状态管理
├── history.ts                      # 历史管理
├── lanes.ts                        # 执行队列通道
├── system-prompt.ts               # 系统提示词构建
├── tool-split.ts                  # 工具拆分
├── tool-result-truncation.ts      # 工具结果截断
├── types.ts                       # 类型定义
└── utils.ts                       # 工具函数

核心类型定义

typescript 复制代码
// types.ts

export type EmbeddedPiRunResult = {
  success: boolean;
  reply?: string;
  usage?: Usage;
  error?: string;
};

export type EmbeddedPiAgentMeta = {
  runId: string;
  sessionId: string;
  provider: string;
  modelId: string;
  thinkLevel: ThinkLevel;
};

// 运行状态
export type EmbeddedPiRunStatus =
  | { status: "idle" }
  | { status: "streaming" }
  | { status: "compacting" }
  | { status: "completed" }
  | { status: "error"; error: string };

核心组件

运行器入口

文件 : run.ts

主入口函数,处理整个运行生命周期。

typescript 复制代码
export async function runEmbeddedPiAgent(
  params: RunEmbeddedPiAgentParams,
): Promise<EmbeddedPiRunResult> {
  const sessionLane = resolveSessionLane(params.sessionKey || params.sessionId);
  
  return enqueueSession(() =>
    enqueueGlobal(async () => {
      // 1. 准备工作区
      const workspaceResolution = resolveRunWorkspaceDir({...});
      const resolvedWorkspace = workspaceResolution.workspaceDir;
      
      // 2. 解析模型配置
      const { model, error, authStorage } = resolveModel(
        provider, modelId, agentDir, params.config
      );
      
      if (!model) {
        throw new Error(error ?? `Unknown model: ${provider}/${modelId}`);
      }
      
      // 3. 检查上下文窗口
      const ctxInfo = resolveContextWindowInfo({...});
      const ctxGuard = evaluateContextWindowGuard({...});
      
      // 4. 执行循环
      const result = await runEmbeddedAttempt({
        ...params,
        model,
        authStorage,
        workspaceDir: resolvedWorkspace,
        sessionId: redactedSessionId,
      });
      
      return result;
    })
  );
}

参数定义:

typescript 复制代码
type RunEmbeddedPiAgentParams = {
  message: string;              // 用户消息
  sessionId: string;            // 会话 ID
  sessionKey?: string;         // 会话 Key
  agentId?: string;            // Agent ID
  provider?: string;           // 模型提供商
  model?: string;             // 模型名称
  workspaceDir?: string;      // 工作区目录
  config?: OpenClawConfig;    // 配置
  messageChannel?: string;   // 消息通道
  messageProvider?: string;   // 消息提供商
  // ... 更多参数
};

执行尝试

文件 : run/attempt.ts

单个执行尝试,包含完整的 LLM 调用和工具执行循环。

typescript 复制代码
export async function runEmbeddedAttempt(
  params: EmbeddedRunAttemptParams,
): Promise<EmbeddedRunAttemptResult> {
  const workspace = resolveUserPath(params.workspaceDir);
  
  // 1. 解析沙箱配置
  const sandbox = await resolveSandboxContext({
    config: params.config,
    sessionKey: params.sessionKey || params.sessionId,
    workspaceDir: workspace,
  });
  
  // 2. 加载 Skills
  const skillEntries = loadWorkspaceSkillEntries(workspace);
  const skillsPrompt = resolveSkillsPromptForRun({...});
  
  // 3. 构建系统提示词
  const { systemPrompt, snapshot } = buildEmbeddedSystemPrompt({...});
  
  // 4. 准备会话管理器
  const sessionManager = await prepareSessionManagerForRun({
    sessionId: params.sessionId,
    sessionKey: params.sessionKey,
    systemPrompt,
    workspaceDir: workspace,
    config: params.config,
  });
  
  // 5. 构建工具定义
  const tools = await toClientToolDefinitions({
    config: params.config,
    sessionManager,
    sandbox,
  });
  
  // 6. 注册运行状态
  const handle = registerRun({
    sessionId: params.sessionId,
    sessionManager,
  });
  
  try {
    // 7. 发送用户消息
    await sessionManager.appendUserMessage(params.message);
    
    // 8. 执行主循环
    while (true) {
      // 调用 LLM
      const response = await sessionManager.complete({
        model: params.modelId,
        tools,
        thinking: params.thinkLevel,
      });
      
      // 检查是否有工具调用
      if (response.tool_calls?.length > 0) {
        // 执行工具
        for (const toolCall of response.tool_calls) {
          const result = await executeTool(toolCall);
          await sessionManager.appendToolResult(toolCall.id, toolCall.name, result);
        }
        continue;  // 继续循环
      }
      
      // 没有工具调用,返回结果
      return {
        success: true,
        reply: response.content,
        usage: response.usage,
      };
    }
  } finally {
    unregisterRun(params.sessionId);
  }
}
相关推荐
知了一笑15 小时前
企业的卷味,组织的AI味
人工智能·ai·ai工作流
icsocket16 小时前
国内测试稳定可靠的AI算力芯片测试座厂家
ai
西索斯coding16 小时前
doubao-seed-2.1-turbo 调用一直 401 怎么办?pro 版同样的 Key 却正常——5 分钟排查定位指南
java·服务器·数据库·ai
俊哥V18 小时前
每日 AI 研究简报 · 2026-09-01
人工智能·ai
Wendy不吃榴莲18 小时前
# AI短剧教程 - 《后西游记》开播后,AI影视为什么更考验“连续讲故事”?
人工智能·笔记·学习·ai·视频
木圭的AI时代指南18 小时前
AI江湖录①·斩杀线
人工智能·ai
我才是银古18 小时前
让大模型"看懂"工程图纸:SVG + MD 双载体记录方法论
ai·cad·dwg
数字游民952718 小时前
史诗级更新:微信小程序支持个人主体接入虚拟支付
ai·微信小程序·小程序·opc·数字游民9527
lifallen19 小时前
长任务怎样选择遗忘:clearing、compaction 与 memory
人工智能·学习·ai·ai编程
Luhui Dev19 小时前
大角几何如何保证图片导出尺寸一致性?
人工智能·数学·ai·luhuidev