乐于分享
好东西不私藏

拆解 OpenClaw架构:一条消息从发送到回复,中间经历了什么?

拆解 OpenClaw架构:一条消息从发送到回复,中间经历了什么?

拆解 OpenClaw架构:一条消息从发送到回复,中间经历了什么?

小何学AI · 2026.04.06

小何学AI|第五期 一个非技术人,用源码级视角理解 Openclaw的完整工作流程,零基础入门版


从一个场景说起

我在 Discord 上跟我的 龙虾小登说了一句:

"今天上海的天气怎么样?"

3 秒后,小登回了我一段完整的天气预报。

看起来很简单——我说话,它回话。但这 3 秒钟里,我的消息穿越了 11 个环节,经过了接收、过滤、排队、翻译、思考、调工具、组装回复等一系列流程,才变成你看到的那段回复。

今天我们就来拆解这趟旅程。


全景图:一条消息的完整旅程

入口层(Discord Adapter):①接收消息 → ②去抖 → ③预检路由 → ④排队 → ⑤标准化

核心层(Agent Runtime):⑥路由匹配 → ⑦组装提示词 → ⑧Agent Loop → ⑨Tool/Skill

出口层(Discord Adapter 反向):⑩回复投递 → ⑪状态反馈


三层架构拆解

📥 第一层:入口层 — "快递收件站"

入口层负责把外部平台的消息收进来、清洗干净、排好队。

① 接收消息

技术视角
大白话
Discord Adapter 监听 WebSocket 事件,捕获 MessageCreate
小登的"耳朵"一直竖着,听到你说话就接住

② 去抖(Debounce)

你有没有这样发过消息:先发"帮我",1 秒后发"查一下",再过 1 秒发"天气"?

技术视角
大白话
滑动窗口计时器:每条新消息重置 2 秒倒计时,静默 2 秒后才统一处理
等你说完再回,不是每个字都急着回

③ 预检 + 路由

技术视角
大白话
Pipeline Filter 模式:逐项检查(是否Bot自身消息→是否在白名单→是否需要@→频道是否已绑定Agent),任一项不通过就丢弃。通过后,用 8 级优先路由匹配目标 Agent
门卫查证:你是谁?有没有预约?找哪个部门?都对了才放行

④ 排队(Job Queue)

技术视角
大白话
KeyedAsyncQueue:用 Promise 链按 SessionKey 串行,不同 Key 天然并行
银行叫号:同一窗口排队等,不同窗口同时办

什么是 SessionKey?就是一个"对话身份证":Agent + 平台 + 频道。你在 #01 频道和 #02 频道跟小登说话,是两个不同的 Session,互不干扰。

实战对照:打开 OpenClaw 控制面板的 Sessions 面板,你就能看到——不同频道的对话是分开显示的,各自独立排队。

⑤ 消息标准化

技术视角
大白话
把 Discord 专属的 message.contentmessage.authormessage.attachments 等字段,转换为平台无关的 ctxPayload(统一结构:Body、From、To、SessionKey、ChatType...)
国际快递转运站:拆掉日本包装,贴上统一标签,国内快递员不需要懂日语就能送

这一层的意义:如果将来加飞书、微信,只需要写一个新 Adapter,核心代码一行不改。

实战对照:打开 Channels 面板,可以看到小登同时接入了 3 个平台——Discord、飞书、微信。每个平台都有自己的 Adapter,但进来之后全是同一个格式。


🧠 第二层:核心层 — "AI 的大脑"

核心层是整个系统最关键的部分——决定谁来处理、怎么思考、用什么工具。

⑥ 路由匹配

系统用 8 级优先级找到目标 Agent(比如"小登")。优先级从高到低:帖子绑定 → 服务器角色 → 服务器级 → 团队级 → 账户级 → 频道级 → 默认。

⑦ 组装提示词 — AI 的"操作手册"

在调用大模型之前,系统要给它准备一份完整的"工作包":

System Prompt =  身份声明("你是运行在 OpenClaw 里的个人助手") +  SOUL.md(人格:"温暖、有趣、像朋友") +  AGENTS.md(角色定义:在 #01 频道负责资讯采集)+  USER.md(关于用户的信息) +  工具清单(你能用 web_search、message、cron..) +  Skill 目录(你有"查天气"、"写公众号"等技能) +  历史对话(你们昨天聊了什么)+  当前消息("今天上海天气怎么样?") 

类比:你是老板,在叫员工干活之前,先把员工手册、客户档案、工具箱、今天的任务单都准备好,打包交给他。

⑧ Agent Loop — AI 自己开车

这是整个系统的灵魂。它不是传统的 if-else 程序,而是一个动态循环

想 → 做 → 看 → 再想 → 再做 → ... → 输出结果 

以"查天气"为例:

  1. LLM 看到用户问天气 → 决定调用 weather Skill
  2. 系统执行:先读 SKILL.md,再运行 curl wttr.in/Shanghai
  3. 结果返回给 LLM → LLM 看到天气数据
  4. LLM 判断信息足够了 → 输出最终回复

关键点:是 LLM 自己决定要不要调工具、调哪个工具、什么时候停下来。 系统只是执行者,LLM 才是决策者。

⑨ Tool / Skill — AI 的工具箱

Tool(内置工具)
Skill(自定义技能)
谁写的
OpenClaw 开发者
你自己
例子
read、write、web_search、cron
写公众号、发小红书、查天气
LLM 怎么知道
工具名+描述直接写在提示词里
只写名字和一句描述,用到时才读详细说明

Skill 为什么不一次性全部加载?因为你可能有 25 个 Skill,每个说明书几百字。全塞进去太浪费 token,所以用懒加载——先看目录,用到哪个再打开哪个。

实战对照:打开 Skills 面板,可以看到我装了 8 个 Skill——就是公众号推送、天气查询、画架构图这些能力的"说明书"。

📤 第三层:出口层 — "快递派送站"

⑩ 回复投递

技术视角
大白话
按 Discord 2000 字符限制分块(Chunking),Markdown 表格转换为代码块格式,媒体文件单独发送,失败自动重试
把回复拆成 Discord 能装下的"包裹"逐个寄出

⑪ 状态表情反馈

你发完消息后,有没有注意过消息上的表情在变化?

表情
含义
什么时候出现
🔍
排队中
消息刚进入队列
思考中
LLM 正在推理
搜索中
调用了 web_search
完成
回复已发送

这些表情就是小登在告诉你:"我正在干活呢,别急。"


速查表:技术名词 vs 生活类比

技术概念
生活类比
Channel Adapter
翻译官:把各国语言翻译成普通话
Debounce(去抖)
等你说完再回复,不是每打一个字就回一次
Preflight(预检)
门卫查证:有没有预约?找哪个部门?
KeyedAsyncQueue
银行叫号:同窗口排队,不同窗口并行
SessionKey
对话身份证:小登 × Discord × #01频道
ctxPayload(标准化)
统一快递单:不管哪家快递,单据格式一样
System Prompt
员工手册 + 客户档案 + 工具箱 + 任务单
Agent Loop
大脑思考循环:想→做→看→再想→输出
Tool
出厂自带的瑞士军刀
Skill
你自己买的专用工具包,按需打开说明书
Chunking(分块)
把大包裹拆成快递能装下的小件
Status Reaction
外卖进度条:已接单→制作中→配送中→已送达

一句话总结

AI Agent 不是"你问它答"那么简单。 一条消息要经过接收、去抖、验证、排队、翻译、路由、组装提示词、循环思考、调用工具、分块投递、状态反馈共 11 个环节。它的架构就像一个精密的流水线——入口层负责收件和翻译,核心层负责思考和行动,出口层负责打包和寄出。

理解了这条流水线,你就理解了所有 AI Agent 产品背后的工作原理。


系列预告

这篇是综述,后续我会逐篇深入拆解每个环节的细节:

期数
标题
聚焦环节
核心看点
系列①
消息是怎么进来的?
①② 接收 + 去抖
去抖的滑动窗口机制,为什么不是固定窗口?
系列②
谁有资格被处理?
③④ 预检 + 排队
7 层过滤器 + Promise 链串行的巧妙设计
系列③
一套核心跑多个平台
⑤ 消息标准化
Adapter 模式:加新平台为什么不用改核心代码?
系列④
AI 的操作手册长什么样?
⑦ 系统提示词
完整拆解 16 个模块,2000+ 行的提示词全貌
系列⑤
AI 怎么自己做决定?
⑧ Agent Loop
LLM 驱动的动态循环 vs 传统 if-else 程序
系列⑥
瑞士军刀 vs 专用工具包
⑨ Tool vs Skill
懒加载设计、Skill 目录注入、SKILL.md 写作指南
系列⑦
消息怎么出去的?
⑩⑪ 投递 + 反馈
分块策略、状态表情状态机、去抖防闪烁

每篇都会用"技术语言 + 大白话"双视角讲解,配流程图和源码片段。

关注「小何学AI」,跟我一起零基础借助CC拆解Agent理解被神话的技术。不写代码,就用大白话跟AI提问,就能看懂 AI 是怎么工作的。


本文基于 OpenClaw(开源 AI Agent 框架)源码分析,https://github.com/openclaw/openclaw


小何学AI · 用产品思维拆解 AI 架构

— END —