OpenClaw 快速上手(三):让 Agent 循环跑起来的六层架构

Gateway、Pi Agent、Tools、Skills、Memory、Channels——每一层在做什么、它们怎么拼在一起、以及为什么这种分层在你开始写 Skill 时会变得很重要。

OpenClaw 用几个月可以完全不读这一篇。但你第一次写 Skill、调试一个走错路的消息、或者搞不清 Agent 为什么忘事时,你会想知道每个盒子在做什么。

六层结构

        +-----------------------------------------------+
        |                  Channels                     |   ← 钉钉 / Telegram / ...
        +-----------------------------------------------+
                          |
        +-----------------------------------------------+
        |                  Gateway                      |   ← :18789,归一化消息
        +-----------------------------------------------+
                          |
        +-----------------------------------------------+
        |   Router  +  Sessions   +  Pi Agent (loop)    |   ← 决定谁来处理
        +-----------------------------------------------+
                          |
        +-----------------------------------------------+
        |   Tools (26)        Skills (53+ 内置)         |   ← "能做什么" + "怎么做"
        +-----------------------------------------------+
                          |
        +-----------------------------------------------+
        |   Memory + ContextEngine                      |   ← 持久化上下文
        +-----------------------------------------------+
                          |
        +-----------------------------------------------+
        |   LLM Provider                                |   ← DashScope / Anthropic / ...
        +-----------------------------------------------+

我从上往下走。

Channels——是适配器,不是传输

一个 Channel 就是把"一条钉钉 Stream 消息"变成"OpenClaw 标准消息"再变回去的代码。每个渠道都有自己的怪癖:钉钉用 Stream WebSocket 推事件,Telegram 走轮询或 webhook,Discord 自带一个 Gateway WebSocket。Channel 层把这些都藏起来。

要记住的是:

  • Channel 是按实例配置的。零个、一个、二十个都行。
  • 一条消息的路径是 Channel → Gateway → Agent → Gateway → Channel。Channel 不直接跟 Agent 对话。
  • 平台限流和怪癖都封装在 Channel 适配器里,这就是为什么钉钉的回复手感跟 Telegram 不一样。

Gateway——中枢神经

Gateway 跑在 :18789。它接受来自任何渠道的消息,去重(钉钉偶尔会重投),分配或恢复 Session,把消息交给 Router。

Gateway 也是唯一跟模型 Provider 通信的角色。每次工具结果、每次记忆读写、每次 Prompt 拼装都过它。这就是为什么你只需要一份 API Key 配置。

Router 与 Sessions

Router 决定哪个 Agent 来处理这条消息——只有当你配置了多个 Agent 时才有意义(默认安装就一个,叫 Pi)。Sessions 是 OpenClaw 用来区分"微信里的一个对话"和"Telegram 里的一个对话"——即使它们都打到同一个 Agent 上。Session ID 由 (channel, conversation_id) 决定。

如果你看到过"Agent 把两个对话混了",那就是 Session ID 撞了,几乎肯定是自定义渠道的 Bug。

Pi Agent——循环本体

这是真正的 Agent 循环,长这样:

while True:
    plan = LLM(messages, tools=enabled_tools, skills=hot_skills)
    if plan.is_terminal:
        return plan.reply
    for tool_call in plan.tool_calls:
        result = run_tool(tool_call)
        messages.append(result)

OpenClaw 在这里几个有意思的选择:

  • Skills 懒加载。 系统 Prompt 里只有 Manifest,正文等模型触发某个 Skill 时才加载。Token 成本因此很低。
  • 工具错误返回给模型,而不是抛出。 模型有机会自我修复。这听起来理所应当,但很多 Agent 框架直接 throw。
  • 循环有硬轮数上限。 默认 30。第 30 轮还在循环就停下,输出一句"我好像卡住了",而不是连夜烧光你的 Token 预算。

Tools——Agent 做什么

Tools 是动词。读文件、写文件、跑 shell、抓 URL、搜网页。默认安装带 26 个。每个 Tool 有:

  • 名字(read, exec, web_search 等)
  • Schema(带类型的参数)
  • Handler(实际跑的代码)
  • 权限等级

exec 是最危险的那个。它跑任意 shell。默认每次调用都需要确认;可以在 openclaw.json 里把可信模式列出来。

Skills——怎么

Skills 是"知识名词"。一个 Skill 是 ~/.openclaw/skills/<name>/SKILL.md 加可选辅助文件。文件头的 Manifest 长这样:

1
2
3
4
5
6
---
name: obsidian-notes
description: 管理 Obsidian 笔记
trigger: 当用户要求记笔记、搜笔记、关联笔记时
tools_required: [read, write, exec]
---

正文是 SOP——指令、模板、示例。Agent 启动时加载 Manifest,所以模型能看到每个 Skill 的一句话摘要。当模型决定要用某个 Skill 时,Gateway 把正文展开塞进下一轮 Prompt。

Skills 是把 LLM 变成"在你的具体任务上靠谱的工人"的方式。Tools 回答"我能不能读文件"。Skills 回答"我现在要写会议笔记,正确的模板是哪个、放哪儿、应该 link 什么"。

Memory + ContextEngine

Memory 是按用户隔离的、持久的、有类型的。常见类型:

  • user/profile.md——偏好
  • project/<name>.md——项目状态
  • feedback/*.md——你给 Agent 的反馈纠正
  • reference/*.md——希望 Agent 长期记住的事实

ContextEngine 是 v2026.3.7 加的——决定下一轮 Prompt 里塞哪些记忆片段。它按时效、当前消息相关性、显式 tag 打分。引擎可以换——有 nooprecency-only、默认的语义引擎。

这一层让 Agent 感觉它认识你。如果你的不像,几乎都是因为 ContextEngine 没拿到足够的写入机会——Agent 必须被引导去写 Memory。

这种分层的两个实际后果

  1. 你写 Skill,不写 Agent。 Agent 循环是固定的。你的定制发生在 Skill 层(知识)和 Tool 层(动词)。基本不需要碰 Gateway。

  2. 同一个 Agent 服务每个渠道。 因为循环和渠道解耦,你为终端写的生产力 Skill 在钉钉和 Telegram 上一字不变也能用。不需要移植。

下一篇讲配置——openclaw.json、模型提供商、以及在国内最划算的百炼 Coding Plan。

翻完了?

去 GitHub 关注一下,新一篇通常隔一周就到。

GitHub