Agent Loop 核心
src/agents/ 目录下是 OpenClaw 的核心代理循环实现。
主入口:pi-embedded-runner/run.ts
职责: 执行完整的 Agent 对话循环,包含重试、降级、压缩的完整逻辑。
关键函数: runEmbeddedPiAgent(params)
执行流程
runEmbeddedPiAgent
├── 解析 workspace, provider, modelId
├── resolveModel() → 获取模型实例
├── resolveContextWindowInfo() → 检查上下文窗口大小
├── evaluateContextWindowGuard() → 阻止过小的模型
├── resolveAuthProfileOrder() → 认证 profile 排序
├── applyApiKeyInfo() → 设置 API Key
└── while(true) 主循环:
├── runEmbeddedAttempt() → 实际 LLM 调用
├── 上下文溢出? → compactEmbeddedPiSessionDirect()
├── 工具结果过大? → truncateOversizedToolResults()
├── 认证失败? → advanceAuthProfile() 轮转
├── Thinking 不支持? → pickFallbackThinkingLevel()
├── Failover 错误? → throw FailoverError → 外层模型降级
└── 成功 → buildEmbeddedRunPayloads() → 返回设计亮点
- Lane 队列化: 使用
enqueueCommandInLane(sessionLane)+enqueueCommandInLane(globalLane)双层队列,确保同一 session 的请求串行执行 - Auth Profile 轮转: 支持多个 API key profile,一个失败自动切换到下一个
- Anthropic 反拒绝:
scrubAnthropicRefusalMagic()清理 Anthropic 的 magic string 避免误触发拒绝 - UsageAccumulator: 跨重试累计 token 使用量
单次尝试:pi-embedded-runner/run/attempt.ts
职责: 执行一次完整的 LLM 请求(包含 system prompt 构建、工具注入、streaming 订阅)。
关键函数: runEmbeddedAttempt(params)
流程
- 解析 workspace → sandbox 环境
- 加载技能 (skills),应用环境变量覆盖
- 构建引导上下文 (bootstrap context files)
- 创建工具集 →
createOpenClawCodingTools() - 构建 system prompt →
buildEmbeddedSystemPrompt() - 创建 session →
createAgentSession() - 历史清理 →
sanitizeSessionHistory(),limitHistoryTurns() - 提交 prompt →
subscribeEmbeddedPiSession()(streaming)
工具分割: splitSdkTools() 将工具分为 builtInTools 和 customTools,SDK 内置工具走内部路径,自定义工具走外部路径。
System Prompt 构建:system-prompt.ts
职责: 组装完整的 system prompt,包含所有运行时信息。
模式
"full": 完整模式(主代理),包含所有 section"minimal": 精简模式(子代理),只保留 Tooling, Workspace, Runtime"none": 最小模式,仅身份行
Section 组成
- Skills section(强制读取 SKILL.md 指令)
- Memory section(memory_search 调用指引)
- User Identity
- Time section
- Reply Tags
- Messaging section
- Tooling section
- Runtime info(host, os, arch, node, model, shell, channel, capabilities)
- Context Files(AGENTS.md, TOOLS.md 等引导文件)