OpenClaw 总体架构技术拆解:从 Gateway 到 Agent 的 WebSocket 会话链路

发布时间:2026/10/15 13:26:06

OpenClaw 总体架构技术拆解:从 Gateway 到 Agent 的 WebSocket 会话链路 1. 一次消息从进来到回复OpenClaw 到底走了哪几段路OpenClaw 是一个把 IM 消息、LLM 推理、工具调用串成一条链路的 Agent 框架。它最容易被误解的地方是很多人以为「Agent 就是那个大模型」。实际上在 OpenClaw 里真正干活的角色被拆成了四个Gateway 负责接入和路由Agent 负责思考和调工具WebSocket 负责把这两端连起来Session 负责记住「这是谁在跟谁说话」。你如果只盯着 Agent 的 prompt 调优链路一长就会发现问题根本不在 prompt而在 Session 路由或者 Gateway 的鉴权上。这篇拆解聚焦一次完整会话从客户端连上 Gateway 的 WebSocket到 Session 被创建、Agent 被加载、LLM 被调用、工具被执行、回复被分发回原渠道。中间我会给出 Gateway 与 Agent 的配置片段、WebSocket 握手与 Session 生命周期的验证步骤并说明怎么用 TaoToken 统一 Key/API 通道完成鉴权接入让你能复现一条可观测的调用链路。适合谁看已经在本地跑起 OpenClaw、但搞不清消息为什么没进对 Agent 的人想把 OpenClaw 接到自己业务渠道、需要理解鉴权与路由边界的人以及想给 Agent 加可观测性、排查「消息发出去了但没回复」这类问题的人。下面所有配置都以~/.openclaw/openclaw.json为准路径和字段名保持和官方一致你可以直接对照改。先说结论性的链路客户端 → WebSocket 握手首帧req:connect→ Gateway 鉴权 → Session Router 按 Session Key 找 Agent → Gateway 组装 Agent 装备Session Store / Skills / Tool Policy→ Agent Runner 调 LLM → Agentic Loop 执行工具 → 回复经 Gateway 分发回 Channel。这条链路里任何一环断了表现都是「消息没反应」但原因完全不同所以必须能分段验证。2. TaoToken 前置把 Key 和 API 通道统一到一处在拆链路之前先把鉴权这块讲清楚因为 Gateway 的 WebSocket 鉴权和 LLM 的 API 鉴权是两套东西很多人会混。Gateway 那层是「谁可以连我的控制平面」LLM 那层是「Agent 拿什么去调模型」。前者用gateway.auth.token后者用各 provider 的apiKey。如果你每个 provider 都单独配 KeyAgent 一多、模型一换Key 管理就会散得到处都是。我的做法是把模型调用统一走 TaoToken 的 API 通道这样 Agent 侧只需要认一个 Base URL 和一个 Key模型切换在服务端完成本地配置不用动。TaoToken 的 API 地址是https://taotoken.net/api官网在https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。它的作用是给你一个兼容 OpenAI 协议的入口OpenClaw 里api: openai-completions的 provider 可以直接指过来。为什么要在架构拆解里先讲这个因为 Gateway 到 Agent 的链路里Agent Runner 调 LLM 是最容易失败的一段而失败原因十有八九是 Key 或 Base URL 配错。把这块前置统一后面排查就能快速排除掉「模型侧」的干扰专注看 WebSocket 和 Session。具体配置上OpenClaw 的 provider 支持baseUrlapiKeyapi三件套。你可以在models.providers里加一个指向 TaoToken 的 provider然后让 Agent 的model.primary指向它。这样 Gateway 加载 Agent 装备时注入的 LLM 解析器就会用这个 provider。注意apiKey建议用环境变量引用别硬编码进openclaw.json因为 Gateway 有配置热重载文件可能被反复读取。这里有个容易踩的点OpenClaw 的 provider 配置里api字段决定用哪套协议适配器TaoToken 走 OpenAI 兼容协议所以填openai-completions。如果你填成anthropic-messages握手能过但请求体格式不对报错会出现在 Agent Runner 阶段而不是 Gateway 阶段排查时容易误判成 WebSocket 问题。另外Gateway 自身的gateway.auth.token和 TaoToken 的 Key 是两回事别把 TaoToken 的 Key 填到gateway.auth.token里。前者是控制平面准入后者是模型调用凭证。我见过有人图省事把两者设成同一个值结果 Gateway 能连上、Agent 却调不动模型因为 Gateway 拿这个 token 去当 LLM Key 用了。统一到 TaoToken 之后你的openclaw.json里模型相关的配置会收敛成一处Agent 列表里每个 Agent 只写model.primary指向 provider 别名即可。这样 Multi-Agent 场景下main、claudecode、writing 几个 Agent 共享同一个 API 通道但各自可以用不同的模型 ID切换成本很低。3. 可复制配置Gateway、WebSocket 与 Agent 三件套这一节给可直接复制的配置片段。先看 Gateway 部分它决定了 WebSocket 监听在哪、鉴权怎么做、哪些远程命令被禁。下面这段是 loopback 模式适合本地开发auth.mode用 token{ gateway: { port: 18789, mode: local, bind: loopback, auth: { mode: token, token: ${OPENCLAW_GATEWAY_TOKEN} }, nodes: { denyCommands: [ camera.snap, camera.clip, screen.record, calendar.add, contacts.add, reminders.add ] } } }注意port我写的是 18789和默认一致bind: loopback时 Auth 是可选的但强烈建议开因为 Onboarding 默认会生成一个 token。如果你改成lan或tailnetgateway.auth.token或gateway.auth.password必须设置否则 Gateway 会拒绝启动。这是硬性约束不是建议。接着是模型 provider指向 TaoToken{ models: { mode: merge, providers: { taotoken: { baseUrl: https://taotoken.net/api, apiKey: ${TAOTOKEN_API_KEY}, api: openai-completions, models: [ { id: claude-sonnet-4-6, name: Claude Sonnet 4.6 }, { id: gpt-4.1, name: GPT-4.1 } ] } } } }mode: merge表示和内置 provider 合并不是替换。apiKey用${TAOTOKEN_API_KEY}引用环境变量Gateway 启动时会解析。模型 ID 按你实际在 TaoToken 侧开通的填这里只是示例。然后是 Agent 侧把模型指向上面这个 provider并配好 Session 隔离和工具策略{ agents: { defaults: { sessionIsolation: per-channel-peer, model: { primary: taotoken/claude-sonnet-4-6, fallbacks: [taotoken/gpt-4.1] }, maxConcurrent: 4, subagents: { maxConcurrent: 8, maxSpawnDepth: 2, tools: { allow: [read, exec], deny: [browser, nodes] } } }, list: [ { id: main, workspace: ~/.openclaw/workspace, tools: { profile: messaging, deny: [browser] } } ] } }sessionIsolation: per-channel-peer是多用户场景的推荐值每个聊天对象独立会话。model.primary指向taotoken/claude-sonnet-4-6fallbacks是备用模型主模型失败时自动降级。subagents.tools默认收回敏感工具这是框架层面的安全边界别轻易放开。最后是 Channel 和 bindings决定消息怎么路由到 Agent{ channels: { feishu: { enabled: true, groupPolicy: open, dmPolicy: pairing, allowFrom: [*], connectionMode: websocket, accounts: { default: { appId: ${FEISHU_APP_ID}, appSecret: ${FEISHU_APP_SECRET}, domain: feishu } } } }, bindings: [ { agentId: main, match: { channel: feishu, accountId: default } } ] }connectionMode: websocket表示 Channel 和 Gateway 之间也走 WebSocket不是 HTTP 回调。bindings把 feishu 的 default 账户绑到 main Agent。如果你有多个 Agent就加多条 binding按accountId区分。这三段配置合起来就是「Gateway 监听 模型通道 Agent 装备 消息路由」的完整闭环。改完openclaw.json后Gateway 会按gateway.reload.mode决定热更新还是重启。模型和 Agent 配置一般能热更新Gateway 的port、bind改动需要重启。4. 验证请求WebSocket 握手与 Session 生命周期配置写完得能验证链路真的通了。分三步先验 WebSocket 握手再验 Session 创建最后验一次完整请求。第一步验 WebSocket 握手。Gateway 的 endpoint 是ws://127.0.0.1:18789首帧必须是req:connect。你可以用wscat或任意 WebSocket 客户端连上去发第一帧{ type: req, id: conn-1, method: connect, params: { token: 你的 gateway.auth.token } }如果鉴权通过Gateway 会回一个res帧ok: truepayload里带当前支持的 RPC 方法和事件列表。如果 token 错回ok: falseerror里会有鉴权失败信息。这一步过了说明 Gateway 控制平面是活的。第二步验 Session 创建。握手成功后发一条消息触发 Session 创建。Session Key 的格式是agent:[agentId]:[mainKey]比如agent:main:feishu:default:peer:ou_xxx。你可以通过 Gateway 的sessions_list方法查看当前有哪些 Session{ type: req, id: list-1, method: sessions_list, params: {} }返回的payload里会列出所有活跃 Session 及其 Key。如果消息发出去了但这里没有新 Session说明 Session Router 没匹配到 binding回去检查bindings的channel和accountId是否和消息来源一致。第三步验完整请求。在 IM 里发一条消息观察 Gateway 日志。正常链路会依次出现收到 Message event → Session Router 匹配到 Agent → 加载 Session Store → 构建 Skills Snapshot → 计算 Tool Policy → Agent Runner 调 LLM → Agentic Loop 执行 → 回复分发。你可以在 Gateway 日志里看到每个阶段的耗时。如果卡在「调 LLM」之前是装备加载问题卡在「调 LLM」之后是模型或工具问题。Session 的生命周期也值得单独看。Session Store 在~/.openclaw/agents/[agentId]/sessions/下每个 Session 一个session.jsonl。第一行是 Session Header带id、cwd、timestamp。后面是消息记录。你可以直接cat这个文件看对话历史有没有写进去。如果文件创建了但没内容说明 Agent 没真正执行。Session 有 reset 机制配置在session.reset里比如mode: daily、atHour: 4表示每天凌晨 4 点重置。重置后旧文件会加.reset.date后缀。验证时可以手动触发一次 reset看文件是否按预期归档。Skills Snapshot 只在 New Session 第一轮构建后续同 Session 复用。所以如果你更新了 Skills 列表但没生效先 New Session 再试。这个行为在验证时很容易被忽略导致误以为 Skills 没加载。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth链路跑不通时报错信息是最直接的线索。这一节对照几个真实报错讲排查思路。401 Unauthorized分两种。如果出现在 WebSocket 握手阶段是gateway.auth.token不对检查客户端发的params.token和配置里的是否一致。如果出现在 Agent Runner 调 LLM 阶段是 TaoToken 的apiKey不对或过期检查${TAOTOKEN_API_KEY}环境变量有没有被 Gateway 进程读到。注意 Gateway 是守护进程环境变量要在启动它的 shell 里 export不是在你当前终端 export 就行。local proxy failed这个报错通常出现在 Gateway 尝试连外部服务时。如果你配了baseUrl指向 TaoToken但网络层有本地代理拦截就会报这个。排查方法是先用curl https://taotoken.net/api确认基础连通性再看 Gateway 进程的网络环境是否和你的终端一致。注意别在配置里写任何代理相关的字段OpenClaw 的 provider 配置不支持代理参数写了也不生效。reading choices这个报错来自 LLM 响应解析阶段通常是返回体格式和api适配器不匹配。如果你把 TaoToken 的 provider 配成了anthropic-messages但 TaoToken 返回的是 OpenAI 格式解析choices字段就会失败。改回openai-completions即可。这个错在 Agent Runner 阶段抛出不在 Gateway 阶段所以 WebSocket 握手是正常的别往那个方向查。OAuth 相关报错如果你用的是需要 OAuth 的 provider比如某些需要设备码登录的报错会提示 token 过期或 refresh 失败。OpenClaw 的 provider 配置里OAuth 类 provider 和 API Key 类 provider 走不同分支。TaoToken 走 API Key不涉及 OAuth所以如果你看到 OAuth 报错说明 Agent 的model.primary指向了错误的 provider检查是不是指向了内置的 OAuth provider 而不是taotoken。排查时有个通用方法把agents.defaults.model.primary临时改成一个确定可用的 provider看链路是否通。如果通了说明问题在模型侧如果不通问题在 Gateway 或 Session 侧。这样能快速二分定位。另外sessions_send相关的报错常伴随tools.sessions.visibility没配。Agent-to-Agent 通信需要visibility: all否则 A 的会话写不进 B 的session.jsonl。这个配置特别容易漏报错信息也不直观建议配 Agent 间通信时先检查这一项。6. 把链路跑通之后怎么继续用起来链路验证通过后你可以开始做可观测性。Gateway 的事件流里有agent、chat、health、heartbeat等事件类型订阅这些事件就能拿到每个阶段的耗时和状态。我一般会在客户端订阅agent事件记录每次 Agent 执行的开始和结束时间这样哪一段慢一目了然。如果你想长期跑编码或 Agent 任务可以考虑用 Coding Plan 把模型调用额度固定下来避免按次计费的不确定性。接入文档在https://taotoken.net/docAPI Keys 管理在https://taotoken.net/api-keys模型对话调试在https://taotoken.net/chat。这几个入口分别对应「查文档」「管 Key」「验模型」三个动作排查时按需取用。最后留一个实操建议把openclaw.json纳入版本管理但apiKey和gateway.auth.token用环境变量引用。这样配置改动可追溯密钥不落盘。Gateway 的热重载机制会在文件变化时按规则处理模型和 Agent 配置能热更新端口和绑定改动需要重启心里有数就不会被「改了没生效」困扰。
延伸阅读

更多相关文章

2026/10/15 13:26:06

STM32F103ZET6结合CubeMX的GPS例程:串口DMA与NMEA解析实战

简介:STM32F103ZET6结合CUBE的GPS例程是一份面向嵌入式初学者的完整工程资源,核心解决如何借助STM32CubeMX生成底层初始化代码,并通过UART与GPS模块交互、解析NMEA协议数据的问题。压缩包共188个文件,大小约8.58MB,其中…

2026/10/15 13:26:06

ResNet中downsample的原理、形态与梯度影响分析

1. 为什么ResNet的downsample不是“简单下采样”,而是个精密开关?第一次在某高校实验室跑通ResNet-18时,我盯着BasicBlock里那个downsample参数发了三分钟呆——它既不是卷积层,也不是池化层,更不是可学习参数&#xf…

2026/10/15 13:21:00

Context Mode深度解析:从交互范式到工程落地的完整避坑指南

做过几年C端应用或AI产品的人,大概率都碰过同一个词:context-mode。翻译成大白话就是“上下文模式”,但这个词在很多团队里其实是被轻拿轻放的——产品经理把它当成一个“记住用户上次操作”的开关,后端同学把它当作一个“传参数”…

2026/10/15 14:31:47

Intel SGX入门:硬件级可信执行环境原理与落地实践

1. 从一个真实困惑说起:为什么需要关注SGX我第一次接触Intel SGX是在做一个跨平台数据协作项目的时候。当时的需求很朴素:多个参与方想联合计算一个统计结果,但谁都不愿意把原始数据交出去。我们试过同态加密,性能损耗大到没法接受…

2026/10/15 14:31:47

Android SQLite数据库查看与调试全指南

1. 为什么一个SQLite数据库查看问题,会让80%的Android开发者卡在调试第一关 “Android开发中你是怎么查看sqlite数据库的”——这句看似平平无奇的提问,背后藏着整个Android本地数据调试链中最脆弱的一环。我带过三届某高校移动开发实训班,每…

2026/10/15 14:31:47

C99标准全面解析:语法特性、编译器差异与迁移踩坑指南

简介:C99 标准中文版(对应 ISO/IEC 9899:1999)是一份面向 C 语言开发者、编译器实现者和计算机专业学生的规范文档。该标准在 C89 基础上细化了对基本数据类型的规定,包括整型、浮点型、字符型的字节大小、表示范围与对齐要求&…

2026/10/15 14:26:45

收藏 _ 运维转行网络安全:从零基础到高薪之路,小白也能学!

收藏 | 运维转行网络安全:从零基础到高薪之路,小白也能学! 文章讲述了作者从运维转向网络安全的心路历程,强调了随着技术发展,运维人员面临被替代的风险。作者建议运维人员可以通过学习网络安全来提升自身竞争力&…

2026/10/14 11:31:03

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/14 17:41:07

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/15 13:42:16

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/15 0:02:22

防关联浏览器哪个好?三款产品实测差异解析

新手做多店铺,最纠结的就是防关联浏览器选哪个。飞跨、网易、站斧这三款被问得最多,先给结论:要一体化省心、长期便宜,选站斧;要网易招牌和稳,选网易;预算紧做东南亚 Lazada,选飞跨。…

2026/10/15 0:02:22

影刀RPA深度实战:大模型Fine-tuning定制RPA专用Prompt与指令生成

影刀RPA深度实战:大模型Fine-tuning定制RPA专用Prompt与指令生成 一、技术背景 大模型(LLM)在通用场景下表现强大,但当我们将 GPT-4 或 Qwen 直接用于生成影刀RPA操作指令和 XPath 定位时,准确率通常只有 40%-60%。原因…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑