万字解析 OpenClaw 源码架构-工具与自动化

工具与自动化

  • 文档层:以"工具""自动化""平台""节点"等维度组织,覆盖浏览器、Canvas、节点、Cron、钩子、Webhook、Poll、技能等。
  • 工具层:浏览器、Canvas、节点、Cron、消息、会话、网关等工具统一暴露给代理调用。
  • 自动化层:Cron 调度、钩子事件、Webhook 入口、轮询发送等。
  • 平台层:macOS Canvas、iOS/Android 节点、远程节点主机、权限与配对。
graph TB subgraph "文档与概念" A["工具索引
docs/tools/index.md"] B["自动化总览
docs/automation/*"] C["平台与节点
docs/platforms/* + docs/nodes/index.md"] end subgraph "核心能力" D["浏览器工具
docs/tools/browser.md"] E["Canvas/A2UI
docs/platforms/mac/canvas.md"] F["节点系统
docs/nodes/index.md"] G["Cron 调度
docs/automation/cron-jobs.md"] H["钩子系统
docs/automation/hooks.md"] I["Webhook 入口
docs/automation/webhook.md"] J["轮询发送
docs/automation/poll.md"] K["技能平台
docs/tools/skills.md"] end A --> D A --> E A --> F A --> G A --> H A --> I A --> J A --> K B --> G B --> H B --> I C --> E C --> F

核心组件

  • 浏览器工具(browser):基于 CDP 的受控浏览器实例,支持多配置文件、本地/远程/扩展中继模式,提供快照、截图、动作、PDF、状态控制等。
  • Canvas/A2UI:macOS 应用内嵌 WKWebView,支持导航、JS 求值、快照;A2UI v0.8 推送消息。
  • 节点系统(nodes):设备配对、能力描述、权限映射;macOS 可作为节点模式;远程节点主机可执行 system.run 等命令。
  • Cron 调度:网关内置调度器,持久化存储,支持主会话事件与隔离会话运行,带交付策略(公告/网页钩子/无)。
  • 钩子系统(hooks):事件驱动自动化,支持命令、消息、会话、代理生命周期等事件,可打包分发。
  • Webhook 入口:受令牌保护的 HTTP 端点,支持"唤醒"和"隔离代理运行"两类入口。
  • 轮询发送(poll):跨渠道轮询创建与参数差异。
  • 技能平台(skills):AgentSkills 兼容的技能目录,支持安装、 gating、环境注入、热更新。

架构总览

下图展示"工具与自动化"的端到端交互:代理通过工具调用浏览器、Canvas、节点;网关调度 Cron、响应钩子与 Webhook;节点承载设备能力与系统命令。

graph TB subgraph "代理侧" Agent["代理/提示词"] end subgraph "网关控制面" WS["WebSocket 控制面"] Tools["工具层
browser/canvas/nodes/cron/message/sessions/gateway"] Scheduler["Cron 调度器"] Hooks["钩子系统"] Webhook["Webhook 入口"] end subgraph "平台与节点" Browser["浏览器CDP"] Canvas["CanvasWKWebView"] Nodes["节点macOS/iOS/Android/远程主机"] end Agent --> Tools Tools --> WS WS --> Scheduler WS --> Hooks WS --> Webhook Scheduler --> Tools Hooks --> Tools Webhook --> Tools Tools --> Browser Tools --> Canvas Tools --> Nodes

组件深度解析

浏览器控制(CDP 驱动)

  • 多配置文件:openclaw(受控独立实例)、chrome(扩展中继)、remote(CDP 远程)、自定义命名。
  • 本地/远程/扩展中继:默认 openclaw 独立启动;chrome 通过扩展中继;remote 通过 CDP URL;Node 主机可代理。
  • 功能集:状态/启动/停止、标签页、打开/聚焦/关闭、快照(AI/ARIA)、截图、导航、动作(点击/输入/拖拽/选择)、PDF、对话框/上传、等待/断言、控制台/错误/请求/存储/设置等。
  • 安全与隐私:Loopback 仅、SSRF 策略、私有网络访问白名单、远程 CDP 认证、禁用 evaluate 的安全开关。
  • CLI 与工具:统一 --browser-profile 选择;Playwright 可选增强能力;下载/追踪路径受限于临时根。
flowchart TD Start(["开始"]) --> CheckProfile["选择配置文件
openclaw/chrome/remote"] CheckProfile --> Mode{"本地/远程/扩展中继?"} Mode --> |本地| Launch["启动受控浏览器实例"] Mode --> |远程| Attach["连接远端 CDP"] Mode --> |扩展中继| Relay["通过扩展中继驱动"] Launch --> Capabilities["可用能力:快照/动作/截图/PDF"] Attach --> Capabilities Relay --> Capabilities Capabilities --> Snapshot["快照AI/ARIA"] Capabilities --> Act["动作点击/输入/选择"] Capabilities --> Screenshot["截图元素/整页"] Capabilities --> PDF["生成 PDF"] Snapshot --> End(["结束"]) Act --> End Screenshot --> End PDF --> End

Canvas 与 A2UI(macOS)

  • Canvas:WKWebView 嵌入,自定义 openclaw-canvas:// 协议;支持 present/hide/navigate/eval/snapshot;A2UI v0.8 推送/重置。
  • 与节点协作:nodes canvas 提供相同能力,便于在远程节点上渲染与交互。
  • 安全:自定义协议限制目录穿越,仅允许会话根目录内文件。
sequenceDiagram participant Agent as "代理" participant Gateway as "网关" participant Node as "节点macOS/远程" participant WebView as "Canvas WKWebView" Agent->>Gateway : 调用 canvas.present/navigate/eval/snapshot Gateway->>Node : 节点命令转发如 nodes canvas present Node->>WebView : 执行 present/hide/navigate/eval/snapshot WebView-->>Node : 返回结果如 snapshot 图像数据 Node-->>Gateway : 结果回传 Gateway-->>Agent : 工具返回MEDIA : 或 JSON

节点系统(配对、权限与命令)

  • 设备配对:WS 连接携带设备身份,网关创建节点配对请求,批准后成为已配对节点。
  • 能力与权限:节点描述包含能力清单与权限映射(如 screenRecording/accessibility),用于安全决策。
  • 远程节点主机:在不同机器上运行节点主机,网关通过 WS 转发 system.run 等命令;需配对与鉴权。
  • 常用命令:canvas.、camera.、screen.record、location.get、system.run/notify、设备健康/通知/联系人/日历等。
sequenceDiagram participant GW as "网关" participant Node as "节点macOS/iOS/Android/远程主机" participant User as "用户/代理" User->>GW : 请求节点能力nodes status/describe GW-->>User : 节点列表与能力描述 User->>GW : 发起节点命令如 nodes canvas present GW->>Node : node.invoke 转发 Node-->>GW : 执行结果 GW-->>User : 工具返回MEDIA/JSON

Cron 作业调度(定时与唤醒)

  • 存储与持久化:~/.openclaw/cron/jobs.json;运行历史 ~/.openclaw/cron/runs/.jsonl。
  • 两种执行模式:
    • 主会话(main):入队系统事件,按心跳或立即触发。
    • 隔离会话(isolated):在 cron: 会话中独立运行,可选公告/网页钩子/无交付。
  • 调度类型:一次性 at、固定间隔 every、Cron 表达式(含秒级字段与 IANA 时区)。
  • 交付策略:公告(目标频道/话题)、网页钩子(Bearer 令牌)、无交付。
  • 重试策略:一次性任务对瞬时错误指数退避重试;周期性任务连续失败后指数退避,成功后恢复。
  • CLI 快速入门:add/run/list/runs/edit 等;维护建议:合理设置 sessionRetention 与 runLog 规整。
flowchart TD Add["添加/编辑作业"] --> Schedule{"调度类型"} Schedule --> |at| Once["一次性UTC/本地"] Schedule --> |every| Interval["固定间隔"] Schedule --> |cron| Expr["Cron 表达式含秒/时区"] Once --> Target{"执行目标"} Interval --> Target Expr --> Target Target --> |main| Main["主会话事件心跳触发"] Target --> |isolated| Isolated["隔离会话独立会话"] Isolated --> Delivery{"交付策略"} Main --> Wake{"唤醒模式"} Delivery --> |announce| Announce["公告到目标频道/话题"] Delivery --> |webhook| Hook["POST 到 webhook URLBearer"] Delivery --> |none| Internal["内部运行,不公告"] Wake --> Heartbeat["立即心跳/等待下次心跳"] Announce --> Sum["主会话摘要可选"] Hook --> Sum Internal --> End(["结束"]) Sum --> End

钩子系统(事件驱动自动化)

  • 事件类型:命令(/new、/reset、/stop)、会话(compact 前后)、代理(bootstrap)、网关(startup)、消息(received/transcribed/preprocessed/sent)。
  • 发现与加载:工作空间 hooks、托管 hooks、内置包;支持 npm 包形式的钩子包。
  • 配置:新格式(推荐)与旧格式兼容;可为钩子设置 env、路径等;支持额外加载目录。
  • 最佳实践:轻量处理、错误兜底、早期过滤事件、具体事件键优于通用键。
sequenceDiagram participant Event as "事件源命令/消息/会话/代理/网关" participant Hooks as "钩子系统" participant Handler as "钩子处理器" Event->>Hooks : 触发事件type/action + 上下文 Hooks->>Handler : 调用匹配处理器 Handler-->>Hooks : 可写入消息/修改上下文 Hooks-->>Event : 后续流程如发送消息/记录日志

Webhook 入口(外部触发)

  • 启用与鉴权:hooks.enabled=true 且必须提供 hooks.token;支持 Authorization: Bearer 或 x-openclaw-token。
  • 端点:
    • POST /hooks/wake:向主会话入队系统事件,可立即心跳。
    • POST /hooks/agent:隔离会话运行,可指定 agentId、会话键、交付策略、模型/思考级别、超时等。
    • POST /hooks/:通过 hooks.mappings 将任意载荷映射为 wake/agent。
  • 安全:令牌鉴权、速率限制、请求会话键前缀白名单、可禁用请求覆盖、可开启危险内容包装豁免(谨慎)。
sequenceDiagram participant Ext as "外部系统" participant GW as "网关 HTTP/Webhook" participant Tools as "工具层" participant Cron as "Cron/钩子" Ext->>GW : POST /hooks/wake 或 /hooks/agentBearer GW->>Tools : 解析并校验令牌/参数 Tools->>Cron : 入队/调度主会话/隔离会话 Cron-->>Tools : 运行完成可交付 Tools-->>GW : 结果异步接受/同步摘要 GW-->>Ext : 200 OK

轮询发送(Poll)

  • 支持渠道:Telegram、WhatsApp(web)、Discord、MS Teams(Adaptive Cards)。
  • 参数差异:Telegram 支持匿名/公开、秒级时长;WhatsApp 支持多选;Discord 支持小时时长与多选;Teams 以卡片渲染。
  • 工具调用:message 工具的 poll 动作,或 CLI message poll。

技能平台(AgentSkills 兼容)

  • 加载顺序:工作空间 skills > 托管/本地 skills > 内置技能;插件可自带 skills。
  • gating:基于 OS、PATH 二进制、环境变量、配置路径、primaryEnv 等;可强制 always。
  • 注入与热更新:运行时注入 env/apiKey;watcher 可在变更后热刷新;会话开始时快照技能列表。
  • ClawHub:注册表安装/更新/同步;注意第三方技能信任与沙箱。

依赖关系分析

  • 工具层依赖网关控制面(WebSocket)与节点/浏览器进程;Cron/钩子/Webhook 作为外部触发器与调度器接入工具层。
  • 节点系统依赖设备配对与权限映射;远程节点主机依赖网关鉴权与 SSH 隧道(必要时)。
  • 技能平台与工具层解耦:技能影响提示词与可用工具集合,但不改变工具调用协议。
graph LR Tools["工具层"] --> WS["网关控制面"] Cron["Cron"] --> Tools Hooks["钩子"] --> Tools Webhook["Webhook"] --> Tools Nodes["节点系统"] --> Tools Browser["浏览器CDP"] --> Tools Canvas["CanvasWKWebView"] --> Tools Skills["技能平台"] --> Tools

性能考量

  • Cron 高频场景:合理设置 cron.sessionRetention 与 runLog.maxBytes/keepLines,避免 IO 压力。
  • 浏览器:Playwright 增强能力需安装;下载/追踪输出受限临时目录,避免大文件写盘。
  • 节点:远程节点主机需考虑网络延迟与鉴权;system.run 在允许列表与安全模式下运行。
  • 技能:XML 技能列表注入字符数与 token 成本相关,建议精简描述与按需启用。

技能平台

OpenClaw 将"技能"作为扩展代理能力的核心机制:每个技能是一个目录,包含描述与工具定义的 SKILL.md 文件,以及可选的脚本与资源。技能来源包括:

  • 内置(打包)技能
  • 本地托管(~/.openclaw/skills)
  • 工作区(/skills)
  • 插件自带技能(通过 openclaw.plugin.json 声明)

加载时按优先级合并,并在会话启动时快照缓存以提升性能;支持监视器自动刷新。

graph TB A["内置技能
打包"] --> D["技能索引与快照"] B["本地托管技能
~/.openclaw/skills"] --> D C["工作区技能
/skills"] --> D E["插件技能
openclaw.plugin.json 声明"] --> D D --> E2["会话快照
同一会话复用"] E2 --> F["代理构建提示词
格式化技能列表"]

核心组件

  • 技能元数据与触发规则
    • SKILL.md 使用 YAML frontmatter 定义 name 与 description,决定何时被触发与如何展示。
    • metadata.openclaw 字段用于声明加载门禁(如 os、requires.bins、requires.env、requires.config)、主密钥注入(primaryEnv)、安装器清单(install)等。
  • 加载与过滤
    • 按 OS、二进制、环境变量、配置项进行门禁过滤;未满足条件的技能不参与提示词构建。
  • 配置与注入
    • 通过 ~/.openclaw/openclaw.json 的 skills.entries 覆盖启用状态、环境变量与密钥;运行时注入到进程环境,仅作用于当前代理回合。
  • 提示词注入
    • 将"可用技能"的精简 XML 列表注入系统提示词,影响 token 成本与上下文窗口占用。
  • 生命周期与热重载
    • 会话开始时快照技能集合;支持监视器自动刷新,变更生效于下一次回合或新会话。

架构总览

技能平台围绕"发现---过滤---注入---执行---反馈"闭环工作:

sequenceDiagram participant U as "用户" participant GW as "网关/代理" participant SK as "技能索引" participant RT as "运行时" participant PL as "插件SDK" U->>GW : 发送消息/触发命令 GW->>SK : 加载并快照技能按优先级与门禁 SK-->>GW : 返回可用技能列表 GW->>RT : 注入环境变量/构建提示词 RT-->>GW : 执行工具/脚本可能跨节点 GW-->>U : 返回结果/输出 Note over SK,RT : 监视器可触发热重载下次回合生效

详细组件分析

组件A:技能发现与优先级

  • 来源与优先级
    • 工作区技能 > 本地托管技能 > 内置技能(最低)
    • 可通过 skills.load.extraDirs 添加额外扫描目录(最低优先级)
  • 多代理场景
    • 每个代理有独立工作区,工作区技能仅该代理可见;共享技能位于本地托管目录,对本机所有代理可见。
  • 插件技能
    • 插件可在 openclaw.plugin.json 中声明 skills 目录;启用插件时参与加载与优先级判定。

组件B:加载门禁与安装器

  • 门禁字段(metadata.openclaw)
    • os:限定平台列表
    • requires.bins/anyBins:PATH 中必须存在或至少一个存在
    • requires.env:环境变量存在或可通过配置提供
    • requires.config:配置路径为真值
    • always:跳过其他门禁强制包含
    • primaryEnv:与 skills.entries..apiKey 对应的主密钥名
    • install:安装器清单(brew/node/go/download),用于 UI 引导安装
  • 沙箱注意事项
    • 若代理在沙箱中运行,容器内也需具备所需二进制;可通过 agents.defaults.sandbox.docker.setupCommand 安装。

组件C:配置覆盖与环境注入

  • 配置位置
    • ~/.openclaw/openclaw.json 下的 skills.entries. 覆盖启用、环境变量与密钥
  • 运行时注入
    • 启动回合时应用覆盖的 env/apiKey 到进程环境,构建提示词后恢复原环境
  • 全局与沙箱差异
    • 沙箱会话中,技能进程运行在容器内,不继承宿主进程环境;需通过 agents.defaults.sandbox.docker.env 或自定义镜像注入

组件D:提示词注入与 token 影响

  • 注入策略
    • 将"可用技能"的精简 XML 列表注入系统提示词,用于指导模型选择合适技能
  • token 成本估算
    • 基础开销:≥1 技能时固定 195 字符
    • 每技能:约 97 字符 + 名称/描述/位置的 XML 转义长度
  • 建议
    • 控制技能数量与描述长度,避免过度膨胀上下文

组件E:热重载与会话快照

  • 快照机制
    • 会话开始时快照可用技能列表,后续回合复用,避免重复解析
  • 自动刷新
    • 可启用监视器,当 SKILL.md 变更时触发快照更新,下一次回合生效
  • 远程节点
    • 在 Linux 网关上,若连接了允许 system.run 的 macOS 节点,且探测到所需二进制,则可将 macOS 专属技能视为可用(通过 nodes 工具执行)

组件F:插件技能与技能注册表

  • 插件技能
    • 插件通过 openclaw.plugin.json 声明 skills 目录;启用插件时参与加载与优先级
  • 技能注册表(ClawHub)
    • 提供技能浏览、安装、更新与备份;默认安装到当前工作目录下的 skills 子目录

组件G:自定义技能开发与模板

  • 开发流程
    • 创建工作区技能目录,编写 SKILL.md(frontmatter + 指令),按需添加 scripts/references/assets
    • 使用监视器或重启网关使变更生效
  • 模板与脚手架
    • 提供 init_skill.py 生成模板目录与占位内容
    • 提供 package_skill.py 将技能打包为 .skill 文件,内置校验与安全检查(拒绝符号链接、排除版本控制目录等)
flowchart TD Start(["开始"]) --> CreateDir["创建技能目录
工作区"] CreateDir --> WriteMD["编写 SKILL.md
frontmatter + 指令"] WriteMD --> AddRes{"是否需要资源?"} AddRes --> |是| GenRes["生成 scripts/
references/"] AddRes --> |否| Watch["启用监视器/重启网关"] GenRes --> Watch Watch --> Validate["验证与测试"] Validate --> Package{"需要分发?"} Package --> |是| Zip["打包为 .skill 文件"] Package --> |否| End(["完成"]) Zip --> End

组件H:技能与代理系统的集成

  • 触发与路由
    • 模型根据系统提示词中的技能列表选择合适工具;工具调用可能在主机或节点侧执行
  • 执行边界
    • 主机权限与沙箱策略由 agents.defaults.sandbox.* 控制;非主会话默认沙箱隔离
  • 远程执行
    • 通过 nodes 工具在远程 macOS 节点上执行受限命令(如 system.run)

依赖关系分析

  • 技能来源依赖
    • 工作区技能覆盖本地托管技能;本地托管技能覆盖内置技能
    • 插件技能在插件启用时参与加载
  • 配置依赖
    • skills.entries. 依赖 metadata.openclaw.primaryEnv 与配置项
  • 运行时依赖
    • 沙箱模式下,容器内需具备所需二进制;通过 setupCommand 安装
  • 插件 SDK 依赖
    • 插件通过 openclaw.plugin.json 声明技能目录,由插件 SDK 管理生命周期
graph LR P["插件 openclaw.plugin.json"] --> S["技能目录"] S --> IDX["技能索引"] CFG["~/.openclaw/openclaw.json"] --> IDX IDX --> SNAP["会话快照"] SNAP --> PROMPT["系统提示词"] PROMPT --> EXEC["工具/脚本执行"]

性能考量

  • 上下文成本控制
    • 通过精简 XML 列表注入技能信息;减少不必要的技能数量与冗长描述
  • 会话快照
    • 会话内复用技能快照,避免重复解析
  • 监视器去抖
    • 通过 skills.load.watchDebounceMs 控制刷新频率,降低频繁 IO
  • 沙箱安装
    • 在 setupCommand 中集中安装依赖,避免每回合重复安装

节点管理系统

OpenClaw 项目采用模块化架构设计,主要包含以下核心部分:

graph TB subgraph "应用层" IOS[iOS 应用] ANDROID[Android 应用] MAC[macOS 应用] end subgraph "网关层" GATEWAY[网关服务] DISCOVERY[发现服务] PAIRING[配对管理] end subgraph "协议层" WS[WebSocket 协议] AUTH[认证机制] CAPS[能力声明] end IOS --> WS ANDROID --> WS MAC --> WS WS --> GATEWAY DISCOVERY --> IOS DISCOVERY --> ANDROID PAIRING --> GATEWAY

核心组件

节点系统架构

节点系统由三个主要层次组成:

  1. 设备层:iOS、Android、macOS 设备作为节点运行
  2. 网关层:核心控制平面,负责设备管理、认证和会话处理
  3. 协议层:基于 WebSocket 的统一通信协议

主要功能特性

  • 设备发现:支持 Bonjour/mDNS、Tailnet DNS-SD 和手动连接
  • 安全配对:基于设备身份的配对机制,支持令牌轮换
  • 跨平台兼容:统一的节点接口,支持多平台能力扩展
  • 远程控制:支持本地和远程网关访问模式

架构概览

系统采用分层架构设计,确保各组件职责清晰、耦合度低:

sequenceDiagram participant Client as 客户端应用 participant Discovery as 发现服务 participant Gateway as 网关服务 participant Pairing as 配对管理 participant Node as 节点服务 Client->>Discovery : 发现网关 Discovery->>Client : 返回可用网关列表 Client->>Gateway : 建立连接请求 Gateway->>Pairing : 创建配对请求 Pairing->>Client : 显示配对提示 Client->>Pairing : 用户批准/拒绝 Pairing->>Gateway : 更新配对状态 Gateway->>Node : 分配节点权限 Node->>Client : 连接建立完成

详细组件分析

iOS 节点实现

iOS 节点应用实现了完整的设备连接和管理功能:

连接控制器架构

classDiagram class GatewayConnectionController { +gateways : [DiscoveredGateway] +discoveryStatusText : String +pendingTrustPrompt : TrustPrompt? -discovery : GatewayDiscoveryModel +connectWithDiagnostics() +acceptPendingTrustPrompt() +declinePendingTrustPrompt() -resolveServiceEndpoint() -makeConnectOptions() } class TrustPrompt { +stableID : String +gatewayName : String +host : String +port : Int +fingerprintSha256 : String +isManual : Bool } class GatewayDiscoveryModel { +discoveries : [DiscoveredGateway] +statusText : String +debugLog : [DebugLogEntry] +start() +stop() } GatewayConnectionController --> TrustPrompt : manages GatewayConnectionController --> GatewayDiscoveryModel : uses

能力路由机制

iOS 节点使用能力路由器来处理不同类型的命令:

flowchart TD Request[节点调用请求] --> Router[NodeCapabilityRouter] Router --> Handler1{查找处理器} Handler1 --> |canvas.*| CanvasHandler[画布处理器] Handler1 --> |camera.*| CameraHandler[相机处理器] Handler1 --> |screen.*| ScreenHandler[屏幕处理器] Handler1 --> |location.*| LocationHandler[位置处理器] Handler1 --> |system.*| SystemHandler[系统处理器] Handler1 --> |未知命令| ErrorHandler[错误处理] CanvasHandler --> Response[返回响应] CameraHandler --> Response ScreenHandler --> Response LocationHandler --> Response SystemHandler --> Response ErrorHandler --> ErrorResponse[返回错误]

Android 节点实现

Android 节点应用提供了强大的设备管理和连接功能:

发现服务架构

classDiagram class GatewayDiscovery { +gateways : StateFlow~List~ +statusText : StateFlow~String~ -localById : ConcurrentHashMap -unicastById : ConcurrentHashMap -nsd : NsdManager -dns : DnsResolver +startLocalDiscovery() +startUnicastDiscovery() +resolve() -refreshUnicast() } class NodeRuntime { +isConnected : StateFlow~Boolean~ +nodeConnected : StateFlow~Boolean~ +statusText : StateFlow~String~ -connectionManager : ConnectionManager -invokeDispatcher : InvokeDispatcher +connect() +disconnect() +refreshGatewayConnection() } class NodeForegroundService { +start() +stop() -notificationJob : Job -didStartForeground : Boolean } GatewayDiscovery --> NodeRuntime : provides NodeRuntime --> NodeForegroundService : manages

连接管理流程

Android 节点的连接管理采用了状态驱动的设计模式:

stateDiagram-v2 [*] --> Offline Offline --> Searching : 启动发现 Searching --> Discovering : 发现网关 Discovering --> Connecting : 选择目标网关 Connecting --> VerifyingTLS : 建立连接 VerifyingTLS --> Connected : TLS 验证通过 VerifyingTLS --> Offline : TLS 验证失败 Connected --> NodeConnected : 节点连接建立 NodeConnected --> Connected : 操作端连接保持 Connected --> Offline : 连接断开 NodeConnected --> Offline : 节点连接断开

macOS 节点实现

macOS 应用作为节点时,提供了系统级的设备控制能力:

节点服务架构

macOS 节点通过本地 Unix Socket 与系统交互,实现了安全的系统命令执行:

graph LR subgraph "macOS 节点" APP[macOS 应用] UDS[Unix Domain Socket] TCC[TCC 权限系统] SYSTEM[系统命令执行] end subgraph "安全层" TOKEN[访问令牌] HMAC[HMAC 验证] TTL[时间戳限制] end APP --> UDS UDS --> TOKEN UDS --> HMAC UDS --> TTL UDS --> TCC TCC --> SYSTEM

组件间依赖关系

graph TB subgraph "发现层" BONJOUR[Bonjour/mDNS] TAILNET[Tailnet DNS-SD] SSH[SSH 隧道] end subgraph "连接层" WS[WebSocket 连接] TLS[TLS 加密] AUTH[认证机制] end subgraph "业务层" NODE[节点管理] PAIRING[设备配对] CAPABILITIES[能力管理] end BONJOUR --> WS TAILNET --> WS SSH --> WS WS --> AUTH AUTH --> NODE NODE --> PAIRING NODE --> CAPABILITIES

平台特定依赖

不同平台的节点实现具有特定的系统依赖:

平台 系统依赖 权限要求 特殊功能
iOS Network.framework, AVFoundation, Photos 访问控制、屏幕录制、相机 语音唤醒、后台音频
Android NSD (mDNS), DnsResolver 相机、录音、位置 前台服务、通知
macOS CoreLocation, EventKit TCC 权限 系统集成、无障碍

浏览器控制

浏览器控制子系统由"本地/远程浏览器控制服务""Playwright CDP 会话层""Chrome 扩展中继"三部分组成,并通过统一的 HTTP 控制接口对外提供能力。

graph TB subgraph "网关/节点主机" GW["浏览器控制服务
HTTP 路由注册"] CFG["浏览器配置解析
端口/策略/驱动"] BR["桥接服务器
loopback + 认证"] end subgraph "浏览器侧" PW["Playwright CDP 会话
连接/断开/目标定位"] CH["本地 Chrome 启动/停止
参数/沙箱/无头模式"] end subgraph "扩展中继" EXT["Chrome MV3 扩展
调试器/转发/重连"] RELAY["本地 CDP 中继服务
WebSocket 桥接"] end GW --> CFG GW --> BR BR --> RELAY RELAY --> EXT PW --> CH GW --> PW

核心组件

  • 浏览器配置解析:负责默认端口派生、CDP 端点解析、多配置文件(profiles)合并、SSRF 策略等。
  • 本地 Chrome 启动/停止:在受控环境启动/停止 Chromium(Chrome/Brave/Edge/Chromium),支持 headless/no-sandbox、平台差异处理。
  • Playwright CDP 会话:建立/复用/断开 CDP 连接,目标页定位,页面状态收集(控制台/错误/网络请求)。
  • 桥接服务器:提供 loopback HTTP 接口,安装认证中间件,注册路由;可选暴露 noVNC 观察入口。
  • Chrome 扩展中继:MV3 扩展作为调试器客户端,转发 CDP 命令/事件到本地 relay,实现对现有 Chrome 标签页的接管。
  • 客户端动作与状态:提供 cookies/storage/geolocation/media 等设置接口,配合控制服务完成状态注入。
  • 节点主机代理:在远端机器上运行的节点主机,将浏览器工具调用代理回传至本地控制服务或扩展中继。

架构总览

下图展示从"代理调用"到"浏览器控制"的完整链路,包括本地/远程 CDP、扩展中继与 Playwright 的协作。

sequenceDiagram participant Agent as "代理/工具" participant GW as "网关/节点主机" participant BR as "桥接服务器(HTTP)" participant RELAY as "扩展中继(WS)" participant EXT as "Chrome 扩展" participant CH as "Chromium 实例" Agent->>GW : "browser 工具调用" GW->>BR : "HTTP 路由分发" alt "扩展驱动" BR->>RELAY : "转发 CDP 事件/命令" RELAY->>EXT : "CDP 命令/事件" EXT->>CH : "chrome.debugger 调试" CH-->>EXT : "CDP 事件/结果" EXT-->>RELAY : "转发事件/结果" else "Playwright 驱动" BR->>CH : "connectOverCDP / Target API" end CH-->>BR : "CDP 响应" BR-->>GW : "HTTP 响应" GW-->>Agent : "结果/文件路径"

详细组件分析

组件一:CDP 连接与会话管理(Playwright 层)

  • 连接缓存与重试:按 CDP 地址缓存连接,失败时指数退避重试,避免并发风暴。
  • 目标页定位:支持通过 Target.list 或单页回退策略定位目标页;扩展中继场景下采用 Target.list 匹配。
  • 页面状态采集:记录控制台消息、页面错误、网络请求,限制最大条目数,避免内存膨胀。
  • 强制断开与终止执行:在长任务阻塞时,通过关闭连接并终止目标执行上下文,快速恢复后续请求。
  • 多上下文/多页面观察:为每个上下文/页面注册监听,确保状态一致性。
flowchart TD Start(["进入 connectBrowser"]) --> Normalize["规范化 CDP URL"] Normalize --> Cached{"已缓存连接?"} Cached --> |是| ReturnCached["返回缓存连接"] Cached --> |否| Retry["重试循环(最多3次)"] Retry --> FetchWS["获取 WebSocket URL"] FetchWS --> Connect["connectOverCDP(带超时/认证头)"] Connect --> Observe["观察浏览器/上下文/页面"] Observe --> Cache["写入缓存并注册断开回调"] Cache --> Done(["返回 ConnectedBrowser"]) Retry --> Fail{"全部失败?"} Fail --> |是| Throw["抛出错误"] Fail --> |否| Retry

组件二:本地 Chrome 启动与可达性探测

  • 可达性探测:支持 HTTP /json/version 与 WebSocket 握手两种方式,确保 CDP 就绪。
  • 启动参数:自动注入无头/沙箱/禁用同步/设备共享区等参数;支持额外自定义参数。
  • 启动流程:首次启动引导生成偏好文件,再进行装饰(如 UI 颜色),最后以受控参数启动。
  • 停止流程:先 SIGTERM,若长时间未退出则 SIGKILL;探测退出窗口避免僵尸进程。
flowchart TD Launch["启动本地 Chrome"] --> Args["组装启动参数"] Args --> Bootstrap["首次启动引导偏好文件"] Bootstrap --> Decorate["装饰用户数据目录"] Decorate --> Spawn["spawn 进程"] Spawn --> Probe["轮询可达性/握手测试"] Probe --> Ready{"就绪?"} Ready --> |是| Log["记录 PID/端口/路径"] Ready --> |否| Kill["终止并报错(含 stderr 提示)"] Log --> End(["完成"]) Kill --> End

组件三:浏览器配置与策略

  • 默认端口派生:基于网关端口推导控制端口与 CDP 端口范围,避免冲突。
  • CDP 端点解析:支持 HTTP/WS/WSS,保留原始查询参数与鉴权;WebSocket 直连无需 /json/version。
  • 多配置文件(profiles):内置 openclaw 与 chrome(扩展中继)配置,支持远程 CDP 端点。
  • SSRF 策略:默认信任内网模式,可显式收紧;支持主机白名单与私有网络访问开关。
  • 其他:颜色、headless/noSandbox、attachOnly、可执行路径、额外参数、relay 绑定主机等。
flowchart TD In["输入 browser.* 配置"] --> Derive["派生控制/CDP 端口范围"] Derive --> Merge["合并/补全 profiles"] Merge --> Policy["解析 SSRF 策略"] Policy --> Resolve["解析默认 profile/驱动"] Resolve --> Out["输出 ResolvedBrowserConfig"]

组件四:桥接服务器与 HTTP 控制接口

  • 仅绑定 loopback 主机,强制鉴权(token/password),注册通用中间件与路由。
  • 可选 noVNC 观察入口,携带一次性密码或令牌,用于沙箱观察。
  • 启停:启动时安装鉴权中间件,停止时清理鉴权注册表并关闭服务。
sequenceDiagram participant Admin as "管理员/CLI" participant BR as "桥接服务器" participant MW as "中间件" participant R as "路由" Admin->>BR : "启动(start)" BR->>MW : "安装通用/鉴权中间件" BR->>R : "注册路由" Admin->>BR : "停止(stop)" BR->>MW : "删除鉴权注册" BR-->>Admin : "OK"

组件五:Chrome 扩展中继(MV3)

  • 权限与宿主权限:debugger、tabs、activeTab、storage、alarms、webNavigation;允许访问 127.0.0.1:* 与 localhost:*。
  • 连接与握手:预检本地 relay 可达性,建立 WebSocket;收到 connect.challenge 后发起握手并校验 token。
  • 事件/命令转发:将 Target.attached/detached 等事件转发给 relay;接收 forwardCDPCommand 请求后通过 chrome.debugger 发送。
  • 重连与持久化:指数退避重连;服务工作线程重启后从 session storage 恢复状态;导航后支持重新附着。
  • 特殊命令:Runtime.enable 保护性切换;Target.createTarget/activateTarget/closeTarget 的安全实现(避免关闭最后一个标签)。
sequenceDiagram participant EXT as "扩展" participant WS as "本地 WS(127.0.0.1 : relay)" participant RELAY as "中继" EXT->>WS : "连接(带 token)" WS-->>RELAY : "connect.challenge" RELAY-->>EXT : "握手响应" EXT->>RELAY : "forwardCDPEvent(Target.*)" RELAY-->>EXT : "forwardCDPCommand 响应" EXT->>RELAY : "ping" RELAY-->>EXT : "pong"

组件六:客户端动作与状态注入

  • Cookie/Storage:支持按 targetId/profile 清理/读取/设置;提供本地/会话存储操作。
  • 地理位置/媒体/时区/语言/设备:通过控制服务注入,便于模拟不同环境。
  • 代理/凭据/离线/自定义头:支持在线/离线切换、HTTP 基本认证、自定义请求头。

组件七:节点主机代理与远程控制

  • 在远端机器上运行节点主机,将浏览器工具调用代理回传至本地控制服务或扩展中继。
  • 支持按 profile 白名单过滤,保障安全边界。
  • 文件读取:对代理返回的文件路径进行安全读取与打包。

组件八:测试与可测性(控制服务)

  • 提供测试钩子:可设置 createTargetId/attachOnly/evaluateEnabled/reachable 状态,以及 CDP mock。
  • 便于在单元测试中隔离外部依赖,验证控制服务行为。

依赖关系分析

  • 配置层:config.ts 为所有模块提供统一的 ResolvedBrowserConfig/ResolvedBrowserProfile。
  • 控制层:bridge-server.ts 注册路由,routes/index.ts 组织各子路由。
  • 会话层:pw-session.ts 依赖 chrome.ts 的 CDP URL 解析与可达性探测。
  • 扩展层:background.js 依赖 background-utils.js 的 token 派生与重连策略。
  • 工具层:agents/tools/browser-tool.ts 与 node-host/invoke-browser.ts 作为调用入口。
graph LR CFG["config.ts"] --> BR["bridge-server.ts"] CFG --> CH["chrome.ts"] BR --> RT["routes/index.ts"] RT --> PW["pw-session.ts"] PW --> CH EXT["background.js"] --> BU["background-utils.js"] BT["agents/tools/browser-tool.ts"] --> NH["node-host/invoke-browser.ts"] BR --> EXT

性能考量

  • 连接复用与缓存:通过按 CDP 地址缓存连接,减少重复握手与启动成本。
  • 超时与退避:CDP 连接与重连采用指数退避,避免雪崩效应。
  • 内存控制:页面状态(控制台/错误/网络)限制最大条目数,定期丢弃旧项。
  • 无头/沙箱:在容器/CI 环境启用 headless/no-sandbox,降低资源占用与启动失败率。
  • 代理与直连:优先使用直连 WebSocket(如 wss://)以减少一次 HTTP 探测步骤。
  • 观察入口:noVNC 观察入口仅在需要时开启,避免额外网络暴露。

命令执行器

命令执行器由"工具层""运行时层""进程管理层""安全与策略层"四部分协同构成:

  • 工具层:对外暴露 exec 与 process 两个工具,前者负责执行命令并可后台化;后者负责会话查询、日志、输入注入、终止等。
  • 运行时层:封装执行流程、环境变量清洗与校验、PTY 支持、超时与输出截断、会话状态维护。
  • 进程管理层:通过统一的进程监管器启动/监控/取消子进程,支持 PTY 模式与非 PTY 模式。
  • 安全与策略层:主机环境变量安全检查、执行审批与白名单策略、沙箱容器参数构建、路径与工作目录解析。
graph TB subgraph "工具层" EX["exec 工具
参数校验/预检/调度"] PR["process 工具
会话管理/日志/输入/终止"] end subgraph "运行时层" RT["exec 运行时
环境清洗/超时/输出/通知"] REG["会话注册表
运行中/已完成会话"] end subgraph "进程管理层" SUP["进程监管器
spawn/wait/cancel"] PTY["PTY 处理
光标响应/DSR 请求"] end subgraph "安全与策略层" APP["执行审批/策略
host/security/ask"] SEC["主机环境安全
危险变量/PATH 校验"] PATHP["PATH 前缀合并
安全注入"] SHELL["Shell 环境
登录 Shell 解析"] end EX --> RT PR --> REG RT --> SUP RT --> PTY EX --> APP EX --> SEC EX --> PATHP EX --> SHELL SUP --> REG

核心组件

  • exec 工具:统一入口,负责参数解析、预检(脚本语法)、主机/安全/审批策略、工作目录与 PATH 合并、沙箱参数构建、会话创建与后台化、超时与输出截断、退出通知。
  • process 工具:对会话进行列表、轮询、日志截取、写入标准输入、发送按键序列、粘贴文本、终止或移除。
  • 运行时函数:环境变量清洗与校验、PTY 光标响应处理、超时与输出聚合、系统事件通知、会话状态持久化。
  • 进程监管器:抽象 spawn/wait/cancel,支持 PTY 与非 PTY,统一超时与输出捕获。
  • 安全与策略:主机环境变量黑名单、禁止自定义 PATH;执行审批 ask/host/security;沙箱容器参数构建与工作目录映射。

架构总览

下图展示从工具调用到进程执行、输出处理与会话管理的关键交互:

sequenceDiagram participant U as "调用方" participant EX as "exec 工具" participant RT as "运行时" participant SUP as "进程监管器" participant REG as "会话注册表" U->>EX : 调用 exec(命令, 参数) EX->>EX : 参数校验/预检/策略解析 EX->>RT : runExecProcess(命令, 环境, 超时, 输出限制) RT->>REG : 创建会话/记录状态 RT->>SUP : spawn(PTY 或 非PTY) SUP-->>RT : onStdout/onStderr 回调 RT->>REG : 追加输出/更新尾部 SUP-->>RT : wait() 返回退出原因/码 RT->>REG : 标记退出/统计耗时 RT-->>EX : 返回结果(成功/失败/超时) EX-->>U : 返回工具结果

详细组件分析

组件一:exec 工具(命令执行)

  • 功能职责
    • 参数校验与默认值合并(超时、后台窗口、安全模式、ask、host、elevated 等)。
    • 预检:检测脚本文件中的 Shell 变量泄漏与常见误用(如 JS 文件以 NODE 开头),避免模型生成错误命令导致的资源浪费。
    • 主机选择:sandbox/gateway/node;当 elevated 为 full 时强制 gateway。
    • 安全策略:host 为 sandbox 时默认 deny,gateway 默认 allowlist;elevated 为 full 时强制 full。
    • 执行审批:ask 模式(off/on-miss/always)与审批超时;elevated 为 full 时绕过审批。
    • 环境变量:沙箱透传原始 env;主机侧先清洗再合并,严格禁止危险变量与自定义 PATH。
    • 工作目录与 PATH:沙箱工作目录映射与容器内路径解析;非沙箱场景 PATH 合并与登录 Shell PATH 注入。
    • 后台化:根据 allowBackground/yieldMs 控制是否立即返回"运行中",否则等待完成。
    • 输出与通知:按最大字符限制分块输出,支持尾部摘要与退出通知。
  • 关键流程图(预检与策略)
flowchart TD S["开始"] --> P1["解析参数/默认值"] P1 --> P2{"是否 elevated 且允许?"} P2 --> |是| H1["host 强制 gateway"] P2 --> |否| H2["host 来自配置/请求"] H1 --> S1["计算 security/ask/host"] H2 --> S1 S1 --> E1{"host 是否 sandbox?"} E1 --> |是| W1["解析并映射工作目录"] E1 --> |否| W2["解析工作目录(回退到当前/家目录)"] W1 --> ENV["构建/清洗环境变量"] W2 --> ENV ENV --> PATH["合并 PATH(沙箱/主机差异)"] PATH --> PREF["预检: 脚本语法/首行检查"] PREF --> RUN["runExecProcess 执行"] RUN --> OUT["聚合输出/超时/退出码"] OUT --> R["返回结果"]

组件二:运行时执行(runExecProcess)

  • 功能职责
    • 会话创建与状态初始化(PID、输出缓冲、尾部、截断标记、退出标志)。
    • PTY 与非 PTY 分支:PTY 失败自动降级为非 PTY;处理 DSR 请求并注入光标响应。
    • 输出处理:二进制内容清洗、按固定块大小分片、追加到会话并触发增量更新。
    • 超时与退出:区分 shell 基础错误(126/127)与普通退出;超时/无输出超时/信号中断等。
    • 通知与心跳:退出时按需推送系统事件并唤醒心跳。
  • 关键流程图(执行与降级)
flowchart TD A["spawnSpec 决策"] --> B{"host 为 sandbox?"} B --> |是| C["docker exec 参数构建"] B --> |否| D{"pty=true?"} D --> |是| E["PTY 模式 spawn"] D --> |否| F["非PTY 子进程 spawn"] C --> G["监管器 spawn"] E --> G F --> G G --> H{"PTY 成功?"} H --> |否| I["记录警告并重试(非PTY)"] H --> |是| J["监听 stdout/stderr"] I --> K["监管器 spawn(非PTY)"] K --> J J --> L["wait() 获取退出码/信号/原因"] L --> M["标记退出/统计耗时/聚合输出"] M --> N["返回结果(成功/失败/超时)"]

组件三:process 工具(进程管理)

  • 功能职责
    • 列表:按时间倒序列出运行中与最近完成的会话,显示名称、PID、运行时长、尾部摘要。
    • 轮询:在指定超时内等待会话退出,返回新输出与最终状态。
    • 日志:按偏移/限制截取历史输出,支持默认尾部展示提示。
    • 输入:向后台会话标准输入写入数据、发送按键序列、提交回车、粘贴文本。
    • 终止/移除:优先通过监管器取消,否则尝试进程树终止;移除时清理注册表。
  • 关键流程图(轮询与日志)
flowchart TD L1["action=log/poll"] --> L2{"找到活动会话?"} L2 --> |是| L3["截取聚合输出/统计总数/截断标记"] L2 --> |否| L4{"找到已完成会话?"} L4 --> |是| L5["截取已完成输出/附加退出码/信号"] L4 --> |否| L6["返回未找到"] L3 --> L7["返回日志/状态"] L5 --> L7 L6 --> L7

组件四:安全与策略(主机环境、审批、沙箱)

  • 主机环境安全
    • 清洗危险变量名(黑名单)与禁止自定义 PATH,防止二进制劫持与环境污染。
  • 执行审批与策略
    • host:sandbox/gateway/node;security:deny/allowlist/full;ask:off/on-miss/always。
    • elevated:支持 on/off/ask/full,full 时强制 gateway 且绕过 ask。
  • 沙箱参数构建
    • 容器 exec 参数组装(-i/-t/-w/-e),PATH 通过环境变量注入并在容器内追加。
    • 工作目录映射:将容器内相对路径映射回宿主工作区,确保访问合法性。
  • PATH 合并与 Shell 环境
    • 非沙箱场景可将登录 Shell 的 PATH 注入到执行环境,避免工具不可用。
    • 支持 pathPrepend,默认仅在 gateway/sandbox 生效,node 忽略以避免误导。

组件五:权限与作用域(operator scope)

  • 角色与作用域
    • operator/admin/read/write 前缀作用域;admin 授予所有 operator.* 权限;read 可升级为 write。
    • 对非 operator 角色,要求请求的作用域完全在允许集合内。
  • 应用场景
    • 在工具调用前校验角色与作用域,决定是否允许 elevated、host 选择、ask/host/security 等默认策略。

依赖关系分析

  • 工具层依赖运行时层与进程监管器;运行时层依赖安全与策略模块;process 工具依赖会话注册表与监管器。
  • 关键耦合点
    • exec 与 process 共享会话注册表,保证状态一致性。
    • 运行时与监管器解耦,便于扩展不同后端(如容器/远程节点)。
    • 安全策略集中于 exec 层,避免在运行时重复判断。
graph LR EX["exec 工具"] --> RT["运行时"] PR["process 工具"] --> REG["会话注册表"] RT --> SUP["进程监管器"] EX --> APP["执行审批/策略"] EX --> SEC["主机环境安全"] EX --> PATHP["PATH 合并"] EX --> SHELL["Shell 环境"] PR --> SUP PR --> REG

性能考量

  • 输出分块与截断
    • 使用固定块大小分片输出,避免单次回调过大;提供 pending 与总输出上限,防止内存膨胀。
  • 超时与无输出超时
    • 支持总体超时与"无输出超时",避免僵尸进程与长时间无进展任务占用资源。
  • PTY 降级
    • PTY 失败自动回退至非 PTY,减少失败重试成本。
  • 后台化与轮询
    • 后台化可显著降低工具调用阻塞;轮询支持可控等待与指数退避建议,避免频繁轮询。
  • 路径与工作目录解析
    • 沙箱工作目录映射与宿主校验,避免无效路径导致的多次重试。

自动化触发器

自动化触发器相关文档集中在 docs/automation 下,核心源码位于 src/cron、src/hooks、src/auto-reply 等目录;外设集成通过 hooks 子系统对接 Gmail Pub/Sub、Webhook 入口等。

graph TB subgraph "文档" D1["cron-jobs.md"] D2["hooks.md"] D3["webhook.md"] D4["cron-vs-heartbeat.md"] D5["poll.md"] D6["gmail-pubsub.md"] D7["troubleshooting.md"] end subgraph "源码" C1["src/cron/isolated-agent.ts"] H1["src/hooks/hooks.ts"] H2["src/hooks/gmail.ts"] A1["src/auto-reply/dispatch.ts"] end D1 --> C1 D2 --> H1 D3 --> H1 D6 --> H2 D4 --> C1 D5 --> A1 D7 --> C1 D7 --> H1 D7 --> A1

核心组件

  • Cron 调度器:在网关内持久化存储任务,按计划唤醒代理或直接运行,支持主会话事件与隔离会话独立运行,并可选择公告或 Webhook 交付。
  • 钩子系统:自动发现与注册事件处理器,支持内置钩子、托管包与插件钩子,覆盖命令、会话、代理、网关与消息事件。
  • 自动回复:入站消息上下文归一化与回复派发器,支持带打字态的缓冲派发器,确保并发安全与资源回收。

架构总览

下图展示自动化触发器的整体交互:外部系统通过 Webhook 或 Gmail Pub/Sub 推送事件,经由钩子入口进入网关;Cron 负责定时唤醒与执行;自动回复负责入站消息的智能派发与回复。

graph TB Ext["外部系统
Gmail Pub/Sub / Webhook"] --> W["Webhook 入口
/hooks/*"] Ext --> P["Gmail Pub/Sub 订阅"] P --> G["gog gmail watch serve"] G --> W W --> HK["钩子系统
事件发现/注册/触发"] HK --> CR["Cron 调度器
主会话/隔离会话"] HK --> AR["自动回复
入站消息派发"] CR --> |公告/无模型| CH["渠道适配器"] CR --> |Webhook| WH["外部回调端点"] AR --> CH

详细组件分析

Cron 作业调度

  • 调度类型:一次性(at)、固定间隔(every)、标准 Cron 表达式(含秒级字段)与可选时区;对整点表达式默认进行确定性抖动以削峰。
  • 执行模式:
    • 主会话:入队系统事件,按唤醒策略立即或下次心跳执行。
    • 隔离会话:在独立会话中运行,支持模型与思考层级覆盖、轻量引导上下文、公告或 Webhook 交付。
  • 交付策略:公告(直发渠道)、Webhook(HTTP 回调)、内部仅记录(none);可配置最佳努力投递与主会话摘要。
  • 存储与历史:任务存储于本地 JSON 文件,运行历史为 JSONL 并具备裁剪策略;隔离会话可配置保留窗口。
  • 重试策略:瞬时错误指数回退重试;永久错误直接禁用;一次性任务默认最多 3 次,周期性任务失败后按指数回退等待下次计划执行。
  • 配置项:启用开关、存储路径、并发限制、重试策略、Webhook 地址与令牌、会话保留与运行日志裁剪等。
flowchart TD Start(["开始"]) --> Parse["解析计划与负载"] Parse --> Mode{"执行模式?"} Mode --> |主会话| Main["入队系统事件
按唤醒策略执行"] Mode --> |隔离会话| Iso["隔离会话运行
模型/思考覆盖"] Main --> Deliver{"是否需要交付?"} Iso --> Deliver Deliver --> |公告| Ann["渠道公告/摘要"] Deliver --> |Webhook| WB["HTTP 回调"] Deliver --> |内部| LogOnly["仅记录"] Ann --> End(["结束"]) WB --> End LogOnly --> End

钩子系统(事件驱动)

  • 发现与加载:从工作区、用户级与内置目录自动发现钩子,支持包形式的钩子包与插件钩子。
  • 事件类型:命令(/new、/reset、/stop)、会话(压缩前后)、代理(引导)、网关(启动)、消息(接收/转录/预处理/发送)。
  • 处理器:每个钩子包含元数据与处理器实现,事件上下文包含会话键、时间戳、消息数组与丰富的内容上下文。
  • 配置:新格式推荐使用 hooks.internal.entries 控制启用状态与环境变量;支持额外加载目录与兼容旧格式。
  • 最佳实践:保持处理器轻量、错误容错、早期过滤事件、使用具体事件键、避免阻塞命令处理。
sequenceDiagram participant Sys as "系统事件" participant Reg as "钩子注册表" participant H1 as "钩子A" participant H2 as "钩子B" Sys->>Reg : 触发事件 Reg->>H1 : 分发事件 Reg->>H2 : 分发事件 H1-->>Reg : 返回结果 H2-->>Reg : 返回结果 Reg-->>Sys : 合并消息/后续动作

Webhook 入口与外部集成

  • 网关暴露 HTTP 端点用于外部触发:
    • /hooks/wake:向主会话入队系统事件并按模式唤醒。
    • /hooks/agent:隔离会话运行,支持模型/思考覆盖、通道与目标、超时控制与摘要投递。
    • /hooks/:通过映射将任意载荷转换为 wake 或 agent 动作,支持模板与转换模块。
  • 安全与策略:共享密钥认证、请求会话键前缀白名单、显式 agentId 路由白名单、默认会话键策略、不安全外部内容开关。
  • Gmail 集成:通过 gogcli 将 Gmail Watch 推送到 OpenClaw Webhook,支持预设映射、模板与交付到聊天表面。
sequenceDiagram participant Ext as "外部系统" participant GW as "网关Webhook" participant HK as "钩子系统" participant CR as "Cron/代理" Ext->>GW : POST /hooks/wake 或 /hooks/agent GW->>HK : 校验令牌/解析载荷 HK->>CR : 触发主会话事件或隔离会话 CR-->>HK : 运行完成/摘要 HK-->>GW : 响应200/错误码 GW-->>Ext : 返回响应

自动回复与入站消息派发

  • 上下文归一化:将入站消息上下文标准化,便于模板与规则匹配。
  • 派发器:提供普通与带打字态的缓冲派发器,确保并发安全与资源释放。
  • 生命周期:在每次运行结束后释放预留资源,等待空闲后再执行收尾逻辑。
  • 适用场景:基于规则的自动回复、模板化应答、多通道统一派发。
sequenceDiagram participant In as "入站消息" participant FD as "上下文归一化" participant RD as "回复派发器" participant AR as "自动回复引擎" In->>FD : 归一化上下文 FD->>RD : 生成最终上下文 RD->>AR : 触发回复计算 AR-->>RD : 返回回复内容 RD-->>In : 发送/缓冲/打字态

选择 Cron 还是心跳?

  • 心跳:适合批量检查(邮件、日历、通知、项目状态),共享主会话上下文,自然抑制无事不报,降低 API 调用成本。
  • Cron:适合精确时间点、隔离会话、不同模型/思考级别、一次性提醒、外部触发与高频噪音任务。
  • 组合策略:心跳批处理常规监控,Cron 处理精确与隔离任务;必要时结合 Lobster 实现多步骤审批流程。

投票消息(Poll)能力

  • 支持 Telegram、WhatsApp、Discord、MS Teams 等渠道的投票创建与管理。
  • 参数差异:选项数量、持续时间、匿名/公开(Telegram)、群组/话题(Telegram Forum)等。
  • 网关 RPC 与 CLI 提供一致的调用方式,便于在自动化中复用。

依赖关系分析

  • Webhook 与 Cron:Webhook 可作为外部触发器,将事件注入 Cron 或直接触发代理运行;Cron 的公告与 Webhook 交付分别对接渠道与外部系统。
  • 钩子与 Cron:钩子可监听命令与消息事件,动态触发 Cron 任务或直接运行代理;Gmail Pub/Sub 通过钩子映射桥接至 Webhook。
  • 自动回复与钩子:钩子可记录命令审计、保存会话记忆,辅助自动回复的上下文理解与策略制定。
graph LR WH["Webhook 入口"] --> HK["钩子系统"] HK --> CR["Cron 调度器"] HK --> AR["自动回复"] GM["Gmail Pub/Sub"] --> WH CR --> CH["渠道适配器"] CR --> WB["Webhook 回调"]

性能考量

  • Cron 高频场景:
    • 缩短会话保留窗口与限制运行日志大小,避免 IO 压力。
    • 将噪音任务迁移到隔离会话并设置公告/最佳努力投递,减少主会话负担。
    • 对整点表达式使用默认抖动,避免集中峰值。
  • 钩子处理器:
    • 异步后台处理,避免阻塞命令处理;尽早返回与错误捕获。
    • 使用具体事件键,减少通用事件带来的开销。
  • 自动回复:
    • 使用带打字态的缓冲派发器,合理安排并发与资源回收,避免阻塞后续消息。

Canvas A2UI 系统

Canvas A2UI 系统由三部分组成:

  • Swift SDK(OpenClawKit):定义命令、参数、动作格式化、JSONL 解析与 WebView 调用桥接。
  • Canvas 主机(Node.js):提供静态资源服务、热重载、WebSocket 升级与请求路由。
  • HTML 模板与样式:提供 Canvas 基础骨架、平台适配与调试状态显示。
graph TB subgraph "Swift SDKOpenClawKit" S1["CanvasA2UIAction.swift"] S2["CanvasA2UICommands.swift"] S3["CanvasA2UIJSONL.swift"] S4["CanvasCommands.swift"] S5["CanvasCommandParams.swift"] S6["WebViewJavaScriptSupport.swift"] S7["scaffold.html"] end subgraph "Canvas 主机Node.js" N1["server.ts"] N2["a2ui.ts"] N3["file-resolver.ts"] N4["a2ui/index.html"] end S1 --> N1 S2 --> N1 S3 --> N1 S4 --> N1 S5 --> N1 S6 --> N1 S7 --> N1 N1 --> N2 N1 --> N3 N2 --> N4

核心组件

  • 动作与消息格式化:在 Swift 中将用户动作封装为标准化字符串,便于注入到 WebView 并回传到主机。
  • 命令与参数:定义 Canvas 与 A2UI 的推送、重置、导航、JS 执行、快照等命令及参数模型。
  • JSONL 解析:严格校验 A2UI v0.8 消息集,支持从 JSONL 流解码与数组编码。
  • WebView 桥接:在 WKWebView 中注入调试状态与安全调用 JS 的工具方法。
  • Canvas 主机:提供静态资源服务、自动注入热重载脚本、WebSocket 升级与文件解析器。
  • HTML 模板:提供基础画布、状态面板、平台适配与样式变量。

架构总览

Canvas A2UI 的端到端流程如下:

  • 客户端(iOS/Android WebView)通过注入的桥接脚本发送用户动作到主机。
  • 主机解析动作并触发 A2UI 推送或重置命令。
  • A2UI JSONL 数据流经解析器验证后进入渲染管线。
  • HTML 模板与样式在 Canvas 上绘制 UI,支持调试状态与平台适配。
sequenceDiagram participant App as "应用 WebView" participant Host as "Canvas 主机(server.ts)" participant A2UI as "A2UI 注入(a2ui.ts)" participant HTML as "模板与样式(index.html/scaffold.html)" participant Renderer as "渲染管线" App->>A2UI : "注入桥接脚本
postMessage/sendUserAction" App->>Host : "HTTP 请求 /__openclaw__/a2ui/*" Host->>A2UI : "返回带热重载的 HTML" Host-->>App : "HTML + WebSocket 升级" App->>Host : "发送用户动作(JSON)" Host->>Host : "格式化动作/校验 JSONL" Host->>Renderer : "推送/重置 A2UI" Renderer-->>HTML : "更新 DOM/Canvas" HTML-->>App : "调试状态与平台样式"

详细组件分析

组件一:动作与消息格式化(Swift)

flowchart TD Start(["输入用户动作字典"]) --> Extract["提取动作名
extractActionName"] Extract --> Sanitize["清理标签值
sanitizeTagValue"] Sanitize --> Compact["压缩 JSON
compactJSON"] Compact --> Format["格式化代理消息
formatAgentMessage"] Format --> JS["生成 JS 回调
jsDispatchA2UIActionStatus"] JS --> End(["输出用于 WebView 的字符串"])

组件二:命令与参数(Swift)

组件三:JSONL 解析与校验(Swift)

  • 功能要点
    • 将文本按行解析为 AnyCodable 对象,记录行号。
    • 校验 A2UI v0.8 消息集合:仅允许 beginRendering、surfaceUpdate、dataModelUpdate、deleteSurface;禁止 v0.9 的 createSurface。
    • 支持将消息数组编码为 JSON 字符串。
  • 关键路径
flowchart TD In(["输入 JSONL 文本"]) --> Parse["逐行解析为 AnyCodable
parse"] Parse --> Validate["校验 v0.8 合法性
validateV0_8"] Validate --> |通过| Decode["映射为消息数组
decodeMessagesFromJSONL"] Validate --> |失败| Throw["抛出错误含行号与原因"] Decode --> Out(["输出消息数组"])

组件四:WebView 桥接与调试(Swift)

  • 功能要点
    • 在 WKWebView 中注入调试状态开关与状态文案设置。
    • 安全地将字符串转义为 JS 字面量。
    • 异步执行 JS 并返回字符串结果。
  • 关键路径

组件五:Canvas 主机(Node.js)

sequenceDiagram participant Client as "客户端" participant Server as "HTTP 服务器(server.ts)" participant A2UI as "A2UI 处理器(a2ui.ts)" participant Resolver as "文件解析(file-resolver.ts)" Client->>Server : "GET /__openclaw__/a2ui/*" Server->>A2UI : "委托处理 A2UI 请求" A2UI->>Resolver : "解析相对路径并打开文件" Resolver-->>A2UI : "返回真实路径与句柄" A2UI-->>Server : "读取内容并注入热重载脚本" Server-->>Client : "返回 HTML/资源" Note over Server : "WebSocket 升级用于热重载"

组件六:HTML 模板与样式(Swift/Node)

  • Swift 资源模板(scaffold.html)
    • 设置 viewport、平台数据属性、背景动画、Canvas 与状态面板结构。
    • 注入调试状态控制与尺寸适配逻辑。
  • Node A2UI 模板(a2ui/index.html)
    • 引入样式变量、容器 openclaw-a2ui-host、Canvas 与状态面板。
    • 加载 a2ui.bundle.js 并初始化全局 __openclaw API。
  • 关键路径

依赖关系分析

  • Swift SDK 依赖
    • OpenClawProtocol:协议与模型基座。
    • ElevenLabsKit:语音相关能力(在 OpenClawKit 中引入)。
    • Textual:在 macOS/iOS 平台启用聊天 UI 组件(与 Canvas 互补)。
  • Canvas 主机
    • 使用 ws、chokidar 实现 WebSocket 与文件监控。
    • 通过 MIME 检测与安全文件打开保障资源服务。
graph LR OC["OpenClawKit"] --> OP["OpenClawProtocol"] OC --> ELK["ElevenLabsKit"] OCU["OpenClawChatUI"] --> OC OCU --> TXT["Textual"] HS["server.ts"] --> WS["ws"] HS --> CK["chokidar"] HS --> FR["file-resolver.ts"] HS --> AT["a2ui.ts"] AT --> IDX["a2ui/index.html"]

性能考虑

  • 资源加载
    • 静态资源禁用缓存(no-store),确保开发期可即时更新。
    • 仅在 HTML 返回时注入热重载脚本,减少非必要开销。
  • 文件监控
    • 使用 awaitWriteFinish 降低频繁写入导致的重复广播。
    • 测试模式下缩短稳定阈值与轮询间隔,提升反馈速度。
  • 渲染与调试
    • Canvas 尺寸根据 devicePixelRatio 计算,避免模糊。
    • 调试状态面板按需显示,避免常驻 DOM 带来的布局压力。
  • JSONL 处理
    • 逐行解析与严格校验,避免一次性大对象带来的内存峰值。
    • 编码阶段进行 UTF-8 校验,防止异常序列化。
相关推荐
不可能的是1 小时前
彻底搞懂 Module Federation(中中):MF 模块加载(上)
前端·webpack
毛骗导演1 小时前
万字解析 OpenClaw 源码架构-代理系统(一)
前端·架构
波哥学开发1 小时前
🎯 Canvas 箭头绘制算法(附完整源码)
前端·计算机图形学
拖拉斯旋风1 小时前
从零到一:用 Node.js + LangChain + Milvus 打造《天龙八部》专属 RAG 问答机器人
前端
不可能的是1 小时前
彻底搞懂 Module Federation(中下):MF 模块加载(下)
前端·webpack
独特的账号1 小时前
前端浏览器插件的开发一步搞定
前端·react.js
李剑一1 小时前
超实用!数字孪生 Cesium 园区 3D 模型加载,一次学会的保姆级教程
前端·vue.js·cesium
游魂Andy1 小时前
零成本搭建专属AI助手:OpenClaw永久免费部署全攻略
前端·人工智能·ai编程
wuhen_n2 小时前
动态组件与 keep-alive:如何优化页面切换体验与性能?
前端·javascript·vue.js