工具与自动化
- 文档层:以“工具”“自动化”“平台”“节点”等维度组织,覆盖浏览器、Canvas、节点、Cron、钩子、Webhook、Poll、技能等。
- 工具层:浏览器、Canvas、节点、Cron、消息、会话、网关等工具统一暴露给代理调用。
- 自动化层:Cron 调度、钩子事件、Webhook 入口、轮询发送等。
- 平台层:macOS Canvas、iOS/Android 节点、远程节点主机、权限与配对。
graph TB
subgraph "文档与概念"
A["工具索引<br/>docs/tools/index.md"]
B["自动化总览<br/>docs/automation/*"]
C["平台与节点<br/>docs/platforms/* + docs/nodes/index.md"]
end
subgraph "核心能力"
D["浏览器工具<br/>docs/tools/browser.md"]
E["Canvas/A2UI<br/>docs/platforms/mac/canvas.md"]
F["节点系统<br/>docs/nodes/index.md"]
G["Cron 调度<br/>docs/automation/cron-jobs.md"]
H["钩子系统<br/>docs/automation/hooks.md"]
I["Webhook 入口<br/>docs/automation/webhook.md"]
J["轮询发送<br/>docs/automation/poll.md"]
K["技能平台<br/>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["工具层<br/>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["选择配置文件<br/>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 : <path> 或 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["内置技能<br/>打包"] --> D["技能索引与快照"]
B["本地托管技能<br/>~/.openclaw/skills"] --> D
C["工作区技能<br/><workspace>/skills"] --> D
E["插件技能<br/>openclaw.plugin.json 声明"] --> D
D --> E2["会话快照<br/>同一会话复用"]
E2 --> F["代理构建提示词<br/>格式化技能列表"]
核心组件
- 技能元数据与触发规则
- 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["创建技能目录<br/>工作区"]
CreateDir --> WriteMD["编写 SKILL.md<br/>frontmatter + 指令"]
WriteMD --> AddRes{"是否需要资源?"}
AddRes --> |是| GenRes["生成 scripts/<br/>references/<assets/>"]
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
核心组件
节点系统架构
节点系统由三个主要层次组成:
- 设备层:iOS、Android、macOS 设备作为节点运行
- 网关层:核心控制平面,负责设备管理、认证和会话处理
- 协议层:基于 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["浏览器控制服务<br/>HTTP 路由注册"]
CFG["浏览器配置解析<br/>端口/策略/驱动"]
BR["桥接服务器<br/>loopback + 认证"]
end
subgraph "浏览器侧"
PW["Playwright CDP 会话<br/>连接/断开/目标定位"]
CH["本地 Chrome 启动/停止<br/>参数/沙箱/无头模式"]
end
subgraph "扩展中继"
EXT["Chrome MV3 扩展<br/>调试器/转发/重连"]
RELAY["本地 CDP 中继服务<br/>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 工具<br/>参数校验/预检/调度"]
PR["process 工具<br/>会话管理/日志/输入/终止"]
end
subgraph "运行时层"
RT["exec 运行时<br/>环境清洗/超时/输出/通知"]
REG["会话注册表<br/>运行中/已完成会话"]
end
subgraph "进程管理层"
SUP["进程监管器<br/>spawn/wait/cancel"]
PTY["PTY 处理<br/>光标响应/DSR 请求"]
end
subgraph "安全与策略层"
APP["执行审批/策略<br/>host/security/ask"]
SEC["主机环境安全<br/>危险变量/PATH 校验"]
PATHP["PATH 前缀合并<br/>安全注入"]
SHELL["Shell 环境<br/>登录 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["外部系统<br/>Gmail Pub/Sub / Webhook"] --> W["Webhook 入口<br/>/hooks/*"]
Ext --> P["Gmail Pub/Sub 订阅"]
P --> G["gog gmail watch serve"]
G --> W
W --> HK["钩子系统<br/>事件发现/注册/触发"]
HK --> CR["Cron 调度器<br/>主会话/隔离会话"]
HK --> AR["自动回复<br/>入站消息派发"]
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["入队系统事件<br/>按唤醒策略执行"]
Mode --> |隔离会话| Iso["隔离会话运行<br/>模型/思考覆盖"]
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 : "注入桥接脚本<br/>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)
- 功能要点
- 提供提取动作名、清理标签值、压缩 JSON、格式化代理消息等能力。
- 生成标准化字符串,包含 action、session、surface、component、host、instance 与上下文。
- 生成 JS 回调以通知前端动作执行结果。
- 关键路径
flowchart TD
Start(["输入用户动作字典"]) --> Extract["提取动作名<br/>extractActionName"]
Extract --> Sanitize["清理标签值<br/>sanitizeTagValue"]
Sanitize --> Compact["压缩 JSON<br/>compactJSON"]
Compact --> Format["格式化代理消息<br/>formatAgentMessage"]
Format --> JS["生成 JS 回调<br/>jsDispatchA2UIActionStatus"]
JS --> End(["输出用于 WebView 的字符串"])
组件二:命令与参数(Swift)
- 命令枚举
- canvas.a2ui.push:向设备 Canvas 推送 A2UI 内容。
- canvas.a2ui.pushJSONL:向设备 Canvas 推送 JSONL。
- canvas.a2ui.reset:重置 A2UI 渲染器状态。
- 参数模型
- Push/PushJSONL:分别携带消息数组与 JSONL 字符串。
- Canvas 基础命令:present/hide/navigate/evalJS/snapshot 及对应参数。
- 关键路径
组件三:JSONL 解析与校验(Swift)
- 功能要点
- 将文本按行解析为 AnyCodable 对象,记录行号。
- 校验 A2UI v0.8 消息集合:仅允许 beginRendering、surfaceUpdate、dataModelUpdate、deleteSurface;禁止 v0.9 的 createSurface。
- 支持将消息数组编码为 JSON 字符串。
- 关键路径
flowchart TD
In(["输入 JSONL 文本"]) --> Parse["逐行解析为 AnyCodable<br/>parse"]
Parse --> Validate["校验 v0.8 合法性<br/>validateV0_8"]
Validate --> |通过| Decode["映射为消息数组<br/>decodeMessagesFromJSONL"]
Validate --> |失败| Throw["抛出错误含行号与原因"]
Decode --> Out(["输出消息数组"])
组件四:WebView 桥接与调试(Swift)
- 功能要点
- 在 WKWebView 中注入调试状态开关与状态文案设置。
- 安全地将字符串转义为 JS 字面量。
- 异步执行 JS 并返回字符串结果。
- 关键路径
组件五:Canvas 主机(Node.js)
- 功能要点
- 提供静态资源服务与自动注入热重载脚本。
- 支持 WebSocket 升级,实现文件变更时的自动刷新。
- 安全解析 URL 路径,避免越权访问。
- 关键路径
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 校验,防止异常序列化。