
从一条消息到一次完整的 AI 推理,中间到底发生了什么?本文以 OpenClaw 开源项目为蓝本,逐层拆解一个工业级 Agent Runtime 的内部运作机制。
如果说大语言模型是 AI Agent 的「大脑」,那么 Agent Runtime 就是它的「神经系统」——负责接收外部刺激、协调大脑思考、驱动肢体行动、并将结果反馈给外部世界。
市面上讨论 AI Agent 的文章很多,但大多停留在 Prompt 编排和工具调用层面。真正决定一个 Agent 是否能在生产环境中稳定运行的,是那些不那么"性感"但至关重要的工程问题:
OpenClaw 的 Agent Runtime 模块用约 150 个源文件、数万行 TypeScript 代码,给出了一套完整的答案。
在深入细节之前,先看一条用户消息在 OpenClaw 中的完整旅程:
用户在 Telegram 发送 "帮我写一个排序算法"
│
▼
消息渠道层(Telegram/Discord/Slack/...)
│
▼
Auto-Reply 分发器 ── 确定路由、加载配置
│
▼
Agent Runner ── 获取会话锁、刷新记忆
│
▼
┌─ Agent Runtime 核心 ──────────────────┐
│ │
│ 模型解析 → 认证链 → 上下文窗口检查 │
│ │ │
│ ▼ │
│ 构建系统提示词 + 工具集 │
│ │ │
│ ▼ │
│ 调用 LLM 流式推理 │
│ │ │
│ ├── 文本流 → 分块 → 流式投递 │
│ │ │
│ ├── 工具调用 → 策略检查 → 执行 │
│ │ → 结果回传 LLM │
│ │ │
│ └── 上下文溢出 → 自动压缩 │
│ │
└────────────────────────────────────────┘
│
▼
回复投递 → Telegram 消息看起来很直白?但每一个箭头背后都藏着大量的工程决策。接下来我们逐层拆解。
Agent Runtime 的核心入口是一个名为 runEmbeddedPiAgent 的函数,它大约有 1,200 行代码。但它做的事情可以用一句话概括:
在一个带重试、带故障转移、带资源管理的循环中,反复尝试完成一次 LLM 推理。
很多项目的重试逻辑就是 for (let i = 0; i < 3; i++)。OpenClaw 的做法截然不同——重试次数是动态计算的:
最大重试次数 = min(160, max(32, 24 + 认证Profile数 × 8))为什么?因为每个认证 Profile 代表一组独立的 API 凭证。如果你配置了 5 个 OpenAI API Key,系统就有 24 + 5×8 = 64 次尝试机会,可以在不同 Key 之间轮转,最大限度地利用所有可用资源。
当 LLM 调用失败时,系统不会无脑重试,而是先对错误进行分类:
错误类型 | 对应策略 |
|---|---|
余额不足(402) | 切换到下一个认证 Profile |
频率限制(429) | 退避等待 + Profile 轮转 |
认证失败(401) | 切换 Profile |
永久拒绝(403) | 标记该 Profile 不可用,跳过 |
超时(408) | 直接重试 |
模型不存在(404) | 回退到默认模型 |
这套机制意味着:即使你的主力 API Key 被限流了,系统会自动切换到备用 Key 继续工作,而不是直接报错。
模型认证是 Agent 能否正常工作的前提。OpenClaw 设计了一个六层优先级的认证解析链:
第 1 层:显式指定的 Profile ID
↓ 未找到
第 2 层:配置文件中的认证覆盖
↓ 未找到
第 3 层:Auth Profile Store(本地存储的 Profile 列表)
↓ 未找到
第 4 层:环境变量(如 OPENAI_API_KEY)
↓ 未找到
第 5 层:配置文件中的自定义 API Key
↓ 未找到
第 6 层:AWS SDK 默认凭证链(仅 Bedrock)同时支持四种认证模式:标准 API Key、OAuth Token、特殊 Token、以及 AWS 凭证链。这意味着无论你是用 Anthropic 的 API Key,还是通过 GitHub Copilot 的 OAuth,还是 AWS Bedrock 的 IAM 角色,都能无缝接入。
工具(Tools)是 Agent 与外部世界交互的通道。OpenClaw 的工具系统不是简单的"注册一个函数",而是一条精密的工业管线。
从"定义一个工具"到"Agent 可以调用它",要经过十个步骤:
① 解析工具策略配置
② 创建基础工具(文件读写、编辑)
③ 创建 OpenClaw 专有工具(浏览器、消息、定时任务等)
④ 创建命令执行工具(Bash/Exec)
⑤ 应用 Owner-Only 授权过滤
⑥ 应用消息渠道策略(如语音渠道禁用 TTS)
⑦ 应用多层策略管线过滤
⑧ 规范化工具 Schema(适配不同 LLM 的 API 格式)
⑨ 包装 Before-Call 钩子(循环检测)
⑩ 包装 AbortSignal 处理器(超时取消)一个工具能否被 Agent 使用,要通过九层策略的层层审查:
全局 Profile 策略 → Provider Profile 策略
→ 全局 Allow 策略 → 全局 Provider 策略
→ Agent 策略 → Agent Provider 策略
→ 群组策略 → 沙箱策略 → 子代理策略为什么要这么复杂?因为不同场景对工具的需求完全不同:
子代理的深度感知策略尤其值得一提:
系统维护了两个黑名单——"始终禁止"和"叶子节点禁止"。当子代理的嵌套深度达到上限时,会自动禁用 sessions_spawn(生成新子代理)工具,从架构层面杜绝了 Agent 递归爆炸的风险。
Agent 有时候会陷入工具调用循环——反复用相同参数调用同一个工具。OpenClaw 的循环检测器会追踪每个工具调用的签名:
追踪按 10 次调用分桶,最多记录 256 个不同签名,在检测精度和内存开销之间取得平衡。
类别 | 工具 | 能力 |
|---|---|---|
文件操作 | read, write, edit | 读写编辑文件 |
代码执行 | exec, process | 运行命令、管理进程 |
浏览器 | browser | Puppeteer 自动化 |
消息 | message, tts | 跨渠道发送消息、语音合成 |
Web | web_search, web_fetch | 搜索和抓取网页 |
会话 | sessions_list/spawn/send | 管理会话、生成子代理 |
自动化 | cron | 定时任务 |
可视化 | canvas, image | 画布渲染、图像处理 |
基础设施 | gateway, nodes | 网关和节点管理 |
同时通过插件系统支持无限扩展——任何第三方都可以编写插件注册新工具。
在 ChatGPT 时代,用户已经习惯了"打字机效果"——文字一个个蹦出来。但要在一个多渠道、多工具的 Agent 系统中实现可靠的流式响应,远比想象中复杂。
OpenClaw 的流式订阅引擎(pi-embedded-subscribe.ts)大约有 2,000 行代码,核心是一个精密的状态机:
LLM Token 流
│
▼
增量缓冲(deltaBuffer)── 累积原始 Token
│
▼
块级缓冲(blockBuffer)── 识别代码块、思维块边界
│
▼
Block Chunker ── 按段落/换行/句子智能分割
│ (不会打断 Markdown 代码块)
▼
Block Reply Pipeline ── 去重 + 排队 + 超时保护
│
▼
Reply Dispatcher ── 序列化投递 + 人工延迟注入
│
▼
消息渠道 ── Telegram/Discord/Slack/...流式系统最怕的问题是重复发送。OpenClaw 设计了三重去重:
sentKeys(已发送)、pendingKeys(发送中)、bufferedKeys(缓冲中)三组状态互斥Block Chunker 不是简单地按固定长度切割文本,而是:
\n\n)处分割这确保了用户看到的每一条消息都是语义完整的。
在消息块之间,系统会注入 800-2500 毫秒的随机延迟,模拟人类打字的节奏。这不是性能问题,而是刻意的 UX 设计——避免瞬间刷出一大堆消息吓到用户。
当多个 Agent 或多个请求同时操作同一个会话时,如何保证数据一致性?OpenClaw 实现了一套基于文件的分布式锁:
.jsonl.lock,包含 PID 和时间戳这套机制确保了即使在多 Agent 并发场景下,会话文件也不会出现数据损坏。
随着对话的进行,会话历史会越来越长,终将超出模型的上下文窗口。OpenClaw 的自动压缩系统会在溢出前触发:
检测到上下文接近窗口限制
│
▼
是否最近已压缩过?── 是 → 跳过
│ 否
▼
计算可压缩条目数 ── 不足 → 跳过
│ 足够
▼
调用 LLM 生成历史摘要
│
▼
用摘要替换原始历史
│
▼
记录压缩诊断日志压缩操作有 300 秒的硬超时保护,避免压缩过程本身成为瓶颈。
每次压缩都会产出详细的诊断信息,包括压缩前的消息数、文本字符数、工具结果字符数、估计 Token 数等,方便事后分析。
Agent 需要执行代码、读写文件,这意味着它有能力搞破坏。OpenClaw 的沙箱系统在「让 Agent 有用」和「让 Agent 安全」之间找到了平衡。
模式 | 说明 |
|---|---|
off | 不使用沙箱(完全信任) |
non-main | 仅非主 Agent 使用沙箱 |
all | 所有 Agent 都在沙箱中运行 |
沙箱基于 Docker 容器,提供多维度的安全隔离:
安全维度:
├── 能力限制:capDrop: ["ALL"](丢弃所有 Linux Capabilities)
├── 网络隔离:禁止 host 网络模式
├── 文件系统:工作空间访问控制(none/只读/读写)
├── 进程限制:pidsLimit 防止 Fork 炸弹
├── 内存限制:memory + memorySwap 上限
├── CPU 限制:cpus 配额
├── 安全策略:seccomp + apparmor(禁止 unconfined)
└── 工具限制:沙箱内的工具白名单/黑名单三种容器复用策略:
├── session:每个会话一个容器(最安全)
├── agent:每个 Agent 一个容器(平衡)
└── shared:所有 Agent 共享容器(最省资源)
自动清理:
├── 空闲超时:默认 24 小时
└── 最大存活:默认 7 天某些危险配置在 Schema 验证层就被拦截了,代码都写不出来:
"host" → 验证直接拒绝"unconfined" → 验证直接拒绝"unconfined" → 验证直接拒绝这是"安全左移"理念的典型实践——在配置解析阶段就阻止危险操作,而不是等到运行时才检查。
系统提示词决定了 Agent "是谁"、"能做什么"、"该怎么做"。OpenClaw 的系统提示词不是一段静态文本,而是根据运行时上下文动态组装的:
系统提示词 =
运行时信息(宿主/OS/架构/模型/Provider)
+ 工具目录(每个工具的名称和功能摘要)
+ 工作空间注释(项目结构、约定)
+ 技能指引(可用的 Skills)
+ 记忆部分(带引用模式)
+ Owner 身份(谁是管理员)
+ 推理指引(思维深度配置)
+ 消息渠道指引(当前渠道支持的操作)
+ 沙箱信息(容器环境元数据)
+ 时间上下文(用户时区和当前时间)这种动态组装确保了 Agent 在不同场景下都能获得最相关的上下文,同时避免了静态提示词的膨胀问题。
除了内置工具,OpenClaw 还提供了完整的插件系统:
// 每个插件导出一个工具工厂函数
type PluginToolFactory = (context) => Tool | Tool[] | null;
// 上下文包含了 Agent 运行时的关键信息
context = {
config, // 全局配置
workspaceDir, // 工作空间
agentId, // 当前 Agent
sessionKey, // 当前会话
messageChannel, // 消息渠道
sandboxed, // 是否在沙箱中
};当插件工具与核心工具同名时,系统会自动检测并记录冲突,核心工具优先。
通过 optional: true 标记的插件工具,只有在白名单中明确列出时才会加载,避免不必要的工具膨胀。
在真实场景中,一个 OpenClaw 实例可能同时运行多个 Agent,每个 Agent 可能生成子代理。并发管理至关重要。
每个 Agent 并行调用上限:4
子代理生成并行上限:8
子代理嵌套深度上限:1(可配置,防止无限递归)为防止死锁,Agent Runtime 使用命名 Lane 隔离执行:
session:{sessionId}OpenClaw 在配置文件(CLAUDE.md)中明确了多 Agent 场景下的安全规范:
git pull --rebase 时不要丢弃其他 Agent 的工作回顾整个 Agent Runtime 的架构,可以提炼出几个值得借鉴的设计原则:
工具系统的九层策略管线看似复杂,但它解决了一个真实问题:不同维度的权限需求互相正交。全局策略、Agent 策略、群组策略、沙箱策略各管一面,互不干扰。
认证 Profile 轮转、模型回退、错误分类驱动恢复——系统的每一层都在努力"找到一条能走通的路",而不是遇到第一个错误就放弃。
沙箱的危险配置在 Schema 验证阶段就被拦截,而不是等到 Docker 容器启动后才报错。这大幅减少了安全漏洞的攻击面。
从 LLM Token 到用户看到消息,全链路流式传输,配合智能分块和去重,既保证了响应速度,又避免了消息碎片化。
压缩诊断、Token 用量追踪、工具调用循环检测——关键运行数据在架构设计阶段就被考虑到,而不是出问题后才想起加日志。
OpenClaw 的 Agent Runtime 模块展示了一个工业级 AI Agent 执行引擎应该长什么样。它不是一个简单的"LLM API 调用封装",而是一套涵盖了认证管理、故障转移、工具管控、安全隔离、流式传输、并发控制、会话持久化等方方面面的完整运行时系统。
对于正在构建 AI Agent 产品的团队来说,OpenClaw 的设计提供了大量可借鉴的工程实践。即使不直接使用 OpenClaw,理解它的架构决策也能帮助你避开很多"踩过的坑"。
毕竟,让 Agent 写出正确的代码只是开始,让它在生产环境中安全、稳定、高效地运行,才是真正的挑战。