OpenClaw 源码拆解:一个开源 Coding Agent 的架构全景

OpenClaw 源码拆解:一个开源 Coding Agent 的架构全景

OpenClaw 是目前最活跃的开源 AI 助手项目之一,面试中被高频问到"你看过源码吗"。本文基于对 OpenClaw 源码的完整阅读,拆解其核心架构------从 Agent 循环、工具系统、上下文管理、记忆体系到插件机制,逐模块分析设计决策和工程取舍。

项目概览

OpenClaw 是一个基于 TypeScript 的 AI 个人助手框架,采用 pnpm monorepo 结构。它不只是一个 Coding Agent,更是一个支持 25+ 消息通道(Telegram、Discord、Slack、飞书等)、93 个扩展插件、53 个内置 Skill 的通用 Agent 平台。

先看整体架构:
插件生态
记忆体系
上下文运行时
Agent 核心
用户层
CLI 终端
Web UI
消息通道

Telegram/Discord/Slack...
Agentic Loop

pi-embedded-runner
System Prompt

构建器
工具系统

Tool Catalog + 多层策略
ContextEngine

(可插拔)
Compaction

分块摘要 + 三级降级
SessionManager

会话历史
memory_search / memory_get
Dreaming 做梦机制

短期→长期自动提升
LanceDB 向量存储
SOUL.md / MEMORY.md
Provider 插件

Anthropic/OpenAI/Ollama...
Channel 插件

25+ 通道
Skill 系统

53 个内置技能
MCP 工具


一、Agentic Loop:不只是 ReAct 循环

大多数介绍 Agent 的文章把 Agentic Loop 简化为"Think → Act → Observe → Repeat"。OpenClaw 的实现远比这复杂------它在经典 ReAct 循环外面包了一层弹性重试循环,处理真实生产环境中的各种故障。

双层循环架构

内层:ReAct 循环 runEmbeddedAttempt()
外层:弹性重试循环 runEmbeddedPiAgent()


成功
上下文溢出
超时
认证失败
速率限制
计费错误
接收用户消息
调用 runEmbeddedAttempt()
检查结果
上下文溢出?

→ 自动压缩,最多3次
超时?

→ token使用率>65%则先压缩
认证失败?

→ 轮转 auth profile
速率限制?

→ profile轮转或模型降级
计费错误?

→ 触发 FailoverError
成功返回
初始化:沙箱、Skills、工具集、System Prompt
LLM 流式推理
工具调用?
执行工具
结果回灌
最终回复

外层循环的核心逻辑在 run.ts(1441 行),内层在 attempt.ts(2072 行)。几个值得注意的设计:

1. Auth Profile 轮转

OpenClaw 支持配置多个 API Key,当一个 Key 被限流或认证失败时,自动切换到下一个。这在个人使用中不常见,但在团队或多通道场景下很实用。

2. 上下文溢出的智能处理

不是简单地报错,而是检测到溢出后自动触发 compaction(压缩),然后重新尝试。最多压缩 3 次,每次都能腾出更多空间。

3. 超时时的启发式判断

超时不一定意味着失败。如果 token 使用率已经超过 65%,说明可能是上下文太长导致推理变慢,此时先压缩再重试,而不是直接放弃。


二、工具系统:多层策略管道

工具目录

OpenClaw 的工具分为 11 个类别:

类别 核心工具 说明
Files read, write, edit, apply_patch 文件操作
Runtime exec, process, code_execution 命令执行
Web web_search, web_fetch 网络访问
Memory memory_search, memory_get 记忆检索
Sessions sessions_list, sessions_spawn, subagents 多会话/子Agent
UI browser, canvas 界面交互
Messaging message 跨通道消息
Automation cron, gateway 定时任务/网关
Nodes - 节点管理
Agents - Agent 管理
Media image, image_generate, tts 多媒体

多层策略过滤

工具不是一股脑全给模型的。OpenClaw 设计了一条六层策略管道,逐层过滤出当前场景应该暴露的工具:
全量工具集
Profile 策略

minimal/coding/messaging/full
Provider 策略

按 LLM 提供商过滤
Agent 策略

按 Agent 类型过滤
Group 策略

群聊场景过滤
Sandbox 策略

沙箱模式限制
Subagent 策略

子Agent权限收窄
最终工具集

四种 Profile 预设:

  • minimal:只有 session_status------用于状态检查场景
  • coding:文件、运行时、Web、记忆、会话、自动化、媒体
  • messaging:会话和消息工具------用于纯聊天场景
  • full:所有工具

为什么这样设计? 工具数量直接影响模型的工具选择准确率。研究表明,当可用工具超过 15-20 个时,模型选错工具的概率显著上升。通过策略管道,不同场景下模型看到的工具集是精简且相关的。

MCP 工具集成

除了内置工具,OpenClaw 还通过 materializeBundleMcpToolsForRun 加载 MCP 工具。MCP(Model Context Protocol)是 Anthropic 提出的开放协议,让外部工具通过标准接口接入 Agent。OpenClaw 的 MCP 集成意味着任何实现了 MCP Server 的工具都可以被 OpenClaw 调用。


三、上下文管理:可插拔引擎 + 分块摘要压缩

ContextEngine 接口

这是 OpenClaw 上下文管理的核心抽象。通过定义一套标准接口,允许不同的上下文管理策略以插件形式接入:
ContextEngine 生命周期
正常
超限
bootstrap()

初始化会话状态
ingest()

逐条消息摄入
assemble()

在 token 预算内组装上下文
afterTurn()

turn 后处理
maintain()

转录维护
compact()

压缩上下文
ingestBatch()

批量摄入完成的 turn

接口中有几个精妙的设计:

1. assemble() 返回 systemPromptAddition

引擎不仅组装消息历史,还可以向 System Prompt 注入额外指令。这意味着上下文引擎可以根据当前对话状态,动态调整模型的行为指导。

2. maintain() 的安全重写机制

引擎可以通过 runtimeContext.rewriteTranscriptEntries() 安全地重写会话转录。注意是"安全重写"------引擎决定"改什么",运行时负责"怎么改",避免引擎直接操作底层存储导致数据不一致。

3. ownsCompaction 标志

引擎可以声明自己管理压缩(ownsCompaction: true),此时外层循环不会自动触发压缩,完全由引擎内部决定压缩时机和策略。

压缩算法:三级降级

当上下文超限时,OpenClaw 的压缩算法(compaction.ts,531 行)采用三级降级策略:




上下文超限
第一级:完整摘要

分块 → 逐块摘要 → 合并

每块3次重试
成功?
第二级:排除超大消息

过滤掉占窗口50%+的单条消息

只摘要小消息

附加 [Large xxx (~NNK tokens) omitted]
成功?
第三级:纯文本降级

返回 'Context contained N messages

(M oversized). Summary unavailable.'
压缩完成

几个关键的工程细节:

自适应分块

不是固定大小切分,而是根据平均消息大小动态调整:

复制代码
当平均消息大小 > 上下文窗口的 10% 时:
  reduction = min(avgRatio × 2, BASE_CHUNK_RATIO - MIN_CHUNK_RATIO)
  chunkRatio = max(0.15, 0.4 - reduction)

消息越大,分块越小,避免单个分块超出模型处理能力。

标识符保留策略

这是我在源码中看到的一个非常实用的设计:摘要时严格保留 UUID、哈希、API Key、URL、文件路径等不可重构的标识符。因为标识符一旦被摘要改写(比如把一个 UUID 缩写成"之前提到的那个 ID"),后续所有引用都会断链。

20% 安全边际

SAFETY_MARGIN = 1.2------token 估算使用 chars/4 的启发式方法,但这会低估多字节字符(中文、emoji)和特殊 token 的实际消耗。20% 的安全缓冲确保分块不会意外超限。

合并摘要时的信息保留清单

多段摘要合并为最终摘要时,明确要求保留:

  • 活跃任务状态和批处理进度
  • 用户的最后请求
  • 关键决策及其理由
  • TODO 和开放问题
  • 承诺的后续行动

这不是随便写的 Prompt,而是从大量真实对话中提炼出的"压缩时最容易丢失但最影响后续对话质量的信息类型"。


四、记忆体系:从"做梦"到长期记忆

OpenClaw 的记忆系统是我认为最有创意的模块。它不只是"存储和检索",而是构建了一个记忆生命周期管理系统

存储层

层级 存储方式 说明
瞬时 会话上下文 当前对话中的工具结果,可被压缩回收
短期 召回追踪记录 每次 memory_search 的查询和命中结果
长期 MEMORY.md / memory/*.md 文件级持久化记忆
人格 SOUL.md 用户定义的 Agent 人格和行为偏好
向量 LanceDB(可选) 语义向量索引,支持高效相似搜索

memory_search:强制语义召回

memory_search 工具的描述是 "Mandatory recall step" ------在回答关于过去工作、决策、日期、人物、偏好或 TODO 的问题之前,Agent 被强制要求先搜索记忆。这不是建议,是指令。

执行流程:
召回追踪器 记忆后端 memory_search Agent 召回追踪器 记忆后端 memory_search Agent 记录 query + 命中结果 用于后续"做梦"提升决策 search("上次讨论的部署方案") 语义搜索 MEMORY.md + memory/*.md 返回匹配片段(path + lines + score) 按 maxInjectedChars 裁剪结果 装饰引用信息(citations) 返回结果 异步记录召回(fire-and-forget)

最后一步是关键:异步记录召回,永远不阻塞主流程。这些召回记录是"做梦"机制的数据来源。

Dreaming:模拟人类睡眠记忆巩固

这是 OpenClaw 记忆系统最有创意的设计------模拟人类"做梦"过程,在空闲时段自动将高频/高权重的短期记忆提升为长期记忆。
做梦(cron 定时触发)
日常使用
数据积累
memory_search 被调用
异步记录召回

query + 命中结果 + 分数
凌晨 3:00 触发
修复无效条目和过期锁
按权重排序候选记忆

score × recallCount × uniqueQueries
写入 MEMORY.md

三种"做梦"预设:

预设 触发频率 最低分数 最少召回次数 最少唯一查询数 适用场景
core 每天凌晨3点 默认 默认 默认 日常使用
deep 每12小时 0.8 3 3 中度使用
rem 每6小时 0.85 4 3 高频使用

提升条件的设计逻辑

不是"被搜索到就提升",而是要同时满足三个条件:

  1. 分数够高(minScore):语义匹配质量好
  2. 被召回次数够多(minRecallCount):不是偶然命中
  3. 被不同查询召回过(minUniqueQueries):不是同一个问题反复问

第三个条件最精妙------它区分了"用户反复问同一个问题"(可能是系统没回答好)和"这个知识在多个不同场景下都有用"(真正值得长期记住的信息)。

SOUL.md:Agent 的人格文件

如果工作空间根目录存在 SOUL.md,OpenClaw 会在 System Prompt 中注入指令,让 Agent 采用其中定义的人格和语气。这不是简单的"角色扮演 Prompt",而是作为 Project Context 的一部分注入,与项目上下文同级。


五、System Prompt:高度结构化的 25+ 章节

OpenClaw 的 System Prompt 构建器(system-prompt.ts,764 行)生成的 Prompt 包含 25+ 个结构化章节。这不是一段自然语言,而是一份精心组织的"操作手册":
动态层(不缓存)
用户层(用户级缓存)
稳定层(全局缓存)
身份声明

Tooling - 工具列表

Tool Call Style

Safety - 安全规则

Skills - 技能目录

Memory - 记忆使用指南

Workspace

Documentation

Authorized Senders

Current Date & Time

Workspace Files - 注入文件

Project Context

AGENTS.md / SOUL.md / TOOLS.md

CACHE_BOUNDARY

Anthropic 缓存分界线

Group Chat Context

Subagent Context

Heartbeats

Runtime - 运行时信息

缓存边界设计

[CACHE_BOUNDARY] 标记是专门为 Anthropic 的 Prompt Cache 设计的。标记之上的内容变化频率低,可以被缓存复用;标记之下的内容(群聊上下文、子Agent上下文、运行时信息)每次可能不同,不缓存。

这个设计直接影响成本------Anthropic 的缓存命中 token 成本是未命中的 1/10。如果 System Prompt 占输入 token 的 60%(在工具多的场景下很常见),合理的缓存边界能降低约 50% 的输入成本。

三种 Prompt 模式

模式 包含内容 使用场景
full 全部 25+ 章节 主 Agent
minimal 去掉 Memory/Skills/Docs/Silent Replies 子 Agent(减少 token 消耗)
none 仅身份声明一行 极简场景

子 Agent 使用 minimal 模式是一个务实的取舍:子 Agent 通常执行特定任务,不需要完整的技能目录和记忆系统,精简 Prompt 可以把更多窗口留给任务本身。


六、插件系统:三层扩展机制

OpenClaw 的可扩展性通过三层机制实现:

1. Plugin(插件)

93 个扩展插件,通过 definePluginEntry 注册:
注册 API
插件类型
Provider 插件(40+)

Anthropic / OpenAI / Google

Ollama / DeepSeek / Groq...
Channel 插件(20+)

Telegram / Discord / Slack

飞书 / QQ / WhatsApp...
Tool 插件

Tavily / Firecrawl / Browser
Memory 插件

memory-core / memory-lancedb
UI 插件

diffs / canvas
registerTool()
registerCli()
registerHook()
registerMemoryRuntime()

2. Skill(技能)

53 个内置 Skill,每个 Skill 是一个包含 SKILL.md 的目录。Skill 的加载有严格的优先级(低到高):

  1. extra dirs --- 配置的额外目录
  2. openclaw-bundled --- 内置 skills/ 目录
  3. openclaw-managed --- ~/.openclaw/skills/
  4. agents-skills-personal --- ~/.agents/skills/
  5. agents-skills-project --- 项目 .agents/skills/
  6. openclaw-workspace --- 项目 skills/

高优先级覆盖低优先级的同名 Skill。项目级 Skill 优先级最高,意味着每个项目可以定制自己的技能集。

Skill 的加载方式 :Skill 目录和描述以 XML 格式注入 System Prompt 的 <available_skills> 标签。Agent 在回答前扫描匹配的 Skill,然后用 read 工具加载对应的 SKILL.md 获取完整指令。

这是一种渐进式加载策略------不是把所有 Skill 的完整内容都塞进 System Prompt(那样会撑爆窗口),而是先给目录,按需加载。

3. MCP(Model Context Protocol)

通过 materializeBundleMcpToolsForRun 加载 MCP 工具。任何实现了 MCP Server 的外部服务都可以被 OpenClaw 作为工具调用,无需编写插件代码。


七、消息规范化与转录修复

流式事件处理

Agent 的流式响应不是简单的文本拼接。OpenClaw 处理以下事件类型:

事件 处理逻辑
text_delta 增量文本累积
text_end 最终文本处理 + 清洗
tool_call_start/end 工具调用追踪和去重
message_end 消息完成
compaction_start/end 压缩事件

文本清洗管线

原始 LLM 输出
stripBlockTags()

移除 think/final 标签
stripDowngradedToolCallText()

移除降级的工具调用文本
解析回复指令

reply_to_current / reply_to:id
提取媒体 URL
干净的回复文本

转录修复

session-transcript-repair.ts 处理一个微妙但重要的问题:tool_use 和 tool_result 的配对修复

在正常流程中,每个 tool_use 消息都应该有对应的 tool_result。但在上下文压缩、会话恢复、异常中断等场景下,可能出现:

  • 孤立的 tool_result(对应的 tool_use 被压缩掉了)
  • 缺失的 tool_result(工具执行中断)

OpenClaw 在每次组装上下文前都会运行修复,确保 API 收到的消息序列是格式正确的。


八、多通道架构:一个 Agent 服务所有平台

通道抽象

OpenClaw 支持 25+ 消息通道,通过统一的通道注册表管理:
通道能力
通道注册表
消息路由
Session Key 解析
Account ID
DM / Group / Thread
getActivePluginRegistry().channels
markdownCapable

是否支持 Markdown
inlineButtons

内联按钮
reactions

表情反应
threadCreate

线程创建
approvals

审批机制

每个通道声明自己的能力(是否支持 Markdown、内联按钮、表情反应等),Agent 的回复格式会根据通道能力自动适配。比如在 Telegram 上可以用 Markdown 格式化代码块,在 SMS 上就只能发纯文本。

统一消息发送

message 工具提供统一的跨通道消息发送接口,支持:

  • send:发送消息
  • thread-create:创建线程
  • react:添加表情反应

消息自动路由到源通道,Agent 不需要关心底层是 Telegram 还是 Discord。


九、设计哲学总结

读完 OpenClaw 的源码,我总结出它的几个核心设计哲学:

1. 可插拔优先于深度优化

ContextEngine、Provider、Channel、Memory 全部采用注册表 + 接口模式。这意味着任何模块都可以被替换,但也意味着默认实现可能不如深度定制的方案(比如 Claude Code 的上下文管理)。这是广度 vs 深度的取舍。

2. 弹性优先于性能

外层循环的 auth 轮转、模型降级、自动压缩、三级降级摘要------到处都是 fallback。这反映了一个在 25+ 通道上运行的系统的现实需求:不能因为一个 API Key 过期就整个系统挂掉。

3. 渐进式加载优先于全量注入

Skill 只注入目录不注入全文、记忆只在需要时搜索不全量注入、工具按策略过滤不全量暴露。这是在有限上下文窗口下的务实选择。

4. 记忆是一等公民

"做梦"机制、强制召回、短期到长期的自动提升------OpenClaw 把记忆当作核心特性来建设,而不是事后加的功能。这跟大多数 Coding Agent(包括 Codex CLI)形成鲜明对比。

与 Claude Code 的差异

维度 OpenClaw Claude Code
定位 通用 AI 助手(25+ 通道) 专注编码(终端原生)
上下文管理 可插拔接口,实现深度有限 工业级精密管理(三路缓存、四级压缩)
记忆 做梦机制 + LanceDB 向量搜索 五层记忆 + AutoDream + 语义召回
工具 多层策略过滤 按语义分类(只读并行/写入独占)
扩展性 93 个插件 + 53 个 Skill + MCP 相对封闭
核心优势 广度(通道 × 插件 × 通道) 深度(上下文管理精度)

写在最后

OpenClaw 的源码质量在开源 Agent 项目中属于上乘。它不是一个"能跑就行"的 demo,而是一个经过深思熟虑的生产级系统。特别值得学习的几个点:

  1. 多层策略管道:工具过滤不是一个 if-else,而是一条可组合的策略链
  2. 做梦机制:把"记忆管理"从被动存取升级为主动整理,这个思路可以迁移到任何 Agent 系统
  3. 标识符保留策略:压缩时保留 UUID/URL 等不可重构信息,这个细节在其他系统中很少见
  4. 弹性重试循环:把 auth 轮转、模型降级、自动压缩统一在外层循环中处理,比分散在各处的 try-catch 优雅得多

如果你正在做自己的 Agent 系统,OpenClaw 的源码值得通读一遍------不是为了复制它的实现,而是理解它在每个设计决策点上的取舍逻辑。

相关推荐
一个处女座的程序猿2 小时前
Agent之skills:colleague-skill的简介、安装和使用方法、案例应用之详细攻略
agent·skill· llms·colleague-skill
薛定猫AI2 小时前
【技术干货】2026 大模型战局前瞻:从 OpenAI SPUD 到 Gemma 4,本地与云端的架构选择与实战接入
架构
tHeya06II2 小时前
.NET AI 核心构建块:重塑智能应用开发的架构范式与生态
人工智能·架构·.net
永霖光电_UVLED3 小时前
生物技术公司 BiomX 进军国防市场,计划收购 DFSL
人工智能·架构·汽车
我不会写代码njdjnssj3 小时前
Windows版Claude Code环境部署
ai
handsomestWei4 小时前
sqlbot智能问数使用简介
ai·大模型·llm·智能问数·sqlbot
CoderJia程序员甲4 小时前
GitHub 热榜项目 - 日榜(2026-04-05)
人工智能·ai·大模型·github·ai教程
国科安芯4 小时前
面向商业航天的高可靠电机控制系统:从环境约束到芯片实现
单片机·嵌入式硬件·架构·risc-v·安全性测试
javgo.cn4 小时前
我把 Claude Code 的一场打包事故,做成了 Refinex-Code
ai