万字解析 OpenClaw 源码架构-代理系统(二)

模型集成与选择

简介

本文聚焦于"模型集成与选择"的完整实现,覆盖以下关键主题:

  • 模型目录管理:本地与远程模型目录的加载、缓存与回退策略
  • 能力检测与兼容性验证:基于目录条目的输入类型、推理能力与上下文窗口等属性进行校验
  • 模型选择算法:别名解析、默认模型推断、允许列表与白名单控制
  • 负载均衡与性能评估:通过基准脚本与使用聚合统计进行评估
  • 配置合并与认证管理:提供者配置合并、密钥与基础 URL 的保留策略、认证存储与发现
  • 动态切换机制:会话级模型覆盖、回调数据构建与 UI 展示
  • 故障转移策略、降级处理与错误恢复:失败原因分类、超时识别与错误包装
  • 模型发现机制、自动配置与版本管理:PI SDK 发现、合成回退、版本兼容
  • 模型集成指南、自定义模型添加与性能监控技巧

模型集成与选择

围绕模型集成与选择的关键模块分布如下:

  • 选择与解析:model-selection.ts(模型引用解析、别名索引、默认模型推断)
  • 目录与发现:model-catalog.ts(目录加载、PI SDK 发现、合成回退)、pi-model-discovery.ts(认证与模型注册表发现)
  • 配置与合并:models-config.merge.ts(提供者与模型字段合并、密钥与基础 URL 保留)、models-config.plan.ts(生成 models.json 计划)
  • 列表与可用性:commands/models/list.rows.ts、list.registry.ts(模型行构建、可用性判断、过滤)
  • 会话与覆盖:gateway/sessions-patch.ts(会话模型覆盖、允许模型解析)
  • 媒体理解:media-understanding/resolve.ts(按能力筛选媒体理解模型)
  • 性能与监控:scripts/bench-model.ts(基准测试)、usage-aggregates.ts 与 usage-render-overview.ts(使用统计与可视化)
graph TB subgraph "模型选择与目录" MSel["model-selection.ts"] MCat["model-catalog.ts"] PIdx["pi-model-discovery.ts"] end subgraph "配置与合并" Mrg["models-config.merge.ts"] Plan["models-config.plan.ts"] end subgraph "命令行与可用性" LRows["commands/models/list.rows.ts"] LReg["commands/models/list.registry.ts"] end subgraph "运行时集成" Sess["gateway/sessions-patch.ts"] Media["media-understanding/resolve.ts"] end subgraph "性能与监控" Bench["scripts/bench-model.ts"] Usage["usage-aggregates.ts"] UIV["ui/views/usage-render-overview.ts"] end MSel --> MCat MCat --> PIdx Mrg --> Plan LRows --> LReg Sess --> MSel Media --> MSel Bench --> MSel Usage --> UIV

核心组件

  • 模型选择与解析:负责模型引用字符串解析、别名索引、默认模型推断、允许列表与白名单控制、思考级别与推理默认值解析。
  • 模型目录与发现:负责从 PI SDK 加载模型目录、合并配置化模型、应用合成回退、支持图像/文档输入能力查询。
  • 配置合并与计划:负责隐式与显式提供者配置合并、密钥与基础 URL 的保留策略、生成 models.json 写入计划。
  • 列表与可用性:负责模型行构建、可用性判断(优先模型级,其次提供者级认证启发式)、过滤与展示。
  • 会话与覆盖:负责会话级模型覆盖、允许模型解析、默认模型回退。
  • 媒体理解:根据能力筛选媒体理解模型,支持共享与能力配置两种来源。
  • 性能与监控:基准脚本用于评估延迟与用量,使用聚合与 UI 视图用于成本、吞吐、错误率与缓存命中率等指标。

架构总览

模型集成与选择的整体流程包括:配置加载与隐式/显式提供者合并、模型目录加载与可用性探测、模型选择与会话覆盖、能力筛选与兼容性验证、故障转移与降级、性能评估与监控。

sequenceDiagram participant CLI as "命令行/工具" participant Plan as "配置计划(models-config.plan)" participant Merge as "配置合并(models-config.merge)" participant Catalog as "模型目录(model-catalog)" participant Sel as "模型选择(model-selection)" participant Reg as "注册表(list.registry)" participant Rows as "模型行(list.rows)" participant Sess as "会话覆盖(sessions-patch)" CLI->>Plan : 生成models.json计划 Plan->>Merge : 合并隐式/显式提供者 Merge-->>Plan : 返回合并后的提供者 CLI->>Catalog : 加载模型目录(含PI发现/回退) Catalog-->>CLI : 返回目录与可用性 CLI->>Sel : 解析默认/允许列表/别名 Sel-->>CLI : 返回最终模型引用 CLI->>Reg : 获取可用模型集合 Reg-->>CLI : 返回可用键集 CLI->>Rows : 构建模型行(含标签/别名/可用性) Rows-->>CLI : 返回行集合 CLI->>Sess : 应用会话模型覆盖 Sess-->>CLI : 返回覆盖结果

详细组件分析

组件A:模型选择与解析(model-selection)

  • 关键职责
    • 解析模型引用字符串(provider/model 或别名),标准化提供者 ID 与模型 ID
    • 构建别名索引,支持按别名解析
    • 默认模型推断:优先代理覆盖,其次配置默认,最后回退到硬编码默认
    • 允许列表与白名单:允许任意或受控集合,合成未在目录中的条目
    • 思考级别与推理默认值:基于模型目录与配置综合判定
  • 数据结构与复杂度
    • 别名索引:Map 查询 O(1),构建 O(N)
    • 允许集合:Set 查询 O(1),构建 O(M)
  • 依赖关系
    • 依赖模型目录条目以判定允许性与合成条目
    • 依赖代理作用域与默认配置
  • 错误处理
    • 对空引用、无效引用返回错误;对不可解析引用给出警告并回退
flowchart TD Start(["入口: 解析模型引用"]) --> Parse["解析字符串为provider/model或别名"] Parse --> HasAlias{"是否别名?"} HasAlias --> |是| AliasLookup["别名索引查找"] HasAlias --> |否| Normalize["标准化provider/model"] AliasLookup --> Found{"找到别名?"} Found --> |是| ReturnRef["返回模型引用"] Found --> |否| Normalize Normalize --> BuildAllow["构建允许集合(含默认)"] BuildAllow --> Allowed{"在允许集合内?"} Allowed --> |是| ReturnRef Allowed --> |否| Error["返回错误: 不被允许"]

组件B:模型目录与发现(model-catalog + pi-model-discovery)

  • 关键职责
    • 通过 PI SDK 动态导入模型注册表,加载模型目录
    • 合并配置化提供者模型(非 PI 原生提供者)
    • 应用合成回退:当目录缺失时,基于模板 ID 推导
    • 提供能力查询:图像/文档输入、推理能力、上下文窗口
  • 缓存与容错
    • 目录加载结果缓存,失败不污染缓存,避免安装过程临时失败导致的持续失败
  • 依赖关系
    • 依赖认证存储与模型注册表类
    • 依赖配置以决定是否合并配置化模型
sequenceDiagram participant Cat as "model-catalog" participant PIdx as "pi-model-discovery" participant FS as "文件系统" participant Reg as "模型注册表" Cat->>FS : 确保models.json存在 Cat->>PIdx : discoverAuthStorage(agentDir) PIdx-->>Cat : 返回认证存储 Cat->>PIdx : discoverModels(authStorage, agentDir) PIdx-->>Cat : 返回注册表实例 Cat->>Reg : getAll()/getAvailable() Reg-->>Cat : 返回模型条目 Cat->>Cat : 合并配置化模型/应用合成回退 Cat-->>Cat : 缓存结果(可选)

组件C:配置合并与计划(models-config.merge + models-config.plan)

  • 关键职责
    • 合并隐式与显式提供者配置,优先显式,保留隐式模型字段(如上下文窗口、推理标记)
    • 保留现有密钥与基础 URL,避免覆盖由 secret-ref 管理的凭据
    • 生成 models.json 写入计划(跳过/无操作/写入)
  • 复杂度
    • 合并提供者:O(P)(P 为提供者数量)
    • 保留策略:O(P)(逐提供者检查)
flowchart TD Start(["开始: 合并提供者"]) --> Implicit["读取隐式提供者"] Implicit --> Explicit["读取显式提供者"] Explicit --> Merge["逐提供者合并模型字段"] Merge --> Preserve["保留现有密钥/基础URL(条件)"] Preserve --> Plan["生成models.json计划"] Plan --> End(["结束"])

组件D:列表与可用性(list.rows + list.registry)

  • 关键职责
    • 加载模型注册表与可用模型集合
    • 构建模型行:标签、别名、可用性、本地标识
    • 可用性优先使用模型级 getAvailable(),否则回退到提供者级认证启发式
  • 过滤与排序
    • 支持按提供者与本地过滤,按提供者与 ID 排序
flowchart TD Load(["加载注册表"]) --> GetAll["getAll()"] GetAll --> GetAvail["getAvailable()"] GetAvail --> AvailKeys["构建可用键集"] AvailKeys --> ToRow["构建模型行(含标签/别名/可用性)"] ToRow --> Filter["按提供者/本地过滤"] Filter --> Sort["排序输出"]

组件E:会话与覆盖(sessions-patch)

  • 关键职责
    • 会话 patch 中的 model 字段支持 null(重置为默认)、未提供(保持不变)、字符串(解析为允许模型)
    • 解析允许模型引用,若目录不可用则返回 UNAVAILABLE 错误
    • 将解析结果应用到会话条目,并标记是否为默认模型
sequenceDiagram participant Sess as "会话" participant Patch as "patch.model" participant Cat as "模型目录" participant Sel as "模型选择" Sess->>Patch : 读取model字段 alt null Patch-->>Sess : 应用默认模型(标记为默认) else 未提供 Patch-->>Sess : 保持原模型 else 字符串 Patch->>Cat : 加载目录(若需要) Patch->>Sel : 解析允许模型引用 Sel-->>Patch : 返回引用或错误 Patch-->>Sess : 应用覆盖(标记默认/非默认) end

组件F:媒体理解模型筛选(media-understanding/resolve)

  • 关键职责
    • 合并能力配置与共享模型配置
    • 若共享模型未声明能力,则尝试从提供者注册表解析能力
    • 仅保留具备指定能力的模型条目

组件G:故障转移与错误恢复(failover-error)

  • 关键职责
    • 将通用错误归类为故障转移原因(超时、配额、鉴权、格式、模型不存在等)
    • 提供错误描述与状态码映射
    • 将错误转换为 FailoverError 以便上层统一处理
flowchart TD Err(["输入错误"]) --> Classify["按HTTP状态/错误码/消息分类"] Classify --> Timeout{"是否超时?"} Timeout --> |是| Mark["标记为timeout"] Timeout --> |否| Other["其他原因分类"] Mark --> Wrap["包装为FailoverError"] Other --> Wrap Wrap --> Out(["输出FailoverError"])

组件H:性能评估与监控(bench-model + usage-aggregates + usage-render-overview)

  • 关键职责
    • 基准脚本:多次运行取中位数,统计耗时与用量
    • 使用聚合:按渠道、每日、模型维度聚合成本、延迟、错误率
    • UI 视图:展示吞吐、错误率、缓存命中率等指标

依赖关系分析

  • 组件耦合
    • model-selection 依赖 model-catalog 以进行允许性与合成条目判定
    • list.rows/list.registry 依赖 model-catalog 与 PI SDK 注册表
    • sessions-patch 依赖 model-selection 与 model-catalog
    • failover-error 为上层统一错误处理提供抽象
  • 外部依赖
    • PI SDK:认证存储与模型注册表发现
    • 文件系统:models.json 与认证存储文件
graph LR MCat["model-catalog.ts"] --> MSel["model-selection.ts"] PIdx["pi-model-discovery.ts"] --> MCat LReg["list.registry.ts"] --> LRows["list.rows.ts"] MCat --> LReg MSel --> Sess["sessions-patch.ts"] MCat --> Sess MSel --> Media["media-understanding/resolve.ts"] Bench["bench-model.ts"] --> MSel Usage["usage-aggregates.ts"] --> UIV["usage-render-overview.ts"]

性能考量

  • 目录加载缓存:避免重复动态导入与文件系统访问
  • 合并策略:优先显式配置,减少回退路径
  • 可用性探测:优先模型级可用性,必要时回退至认证启发式
  • 基准测试:多轮运行取中位数,降低异常波动影响
  • 监控指标:吞吐、错误率、缓存命中率、平均时延,辅助定位瓶颈

认证与权限管理

认证与权限管理相关代码主要分布在以下模块:

  • 认证档案与存储:src/agents/auth-profiles/*
  • 认证健康检查:src/agents/auth-health.ts
  • OAuth 实现与刷新:src/agents/auth-profiles/oauth.ts
  • 令牌有效期与资格评估:src/agents/auth-profiles/credential-state.ts
  • 配置与密钥管理:src/secrets/*
  • 文档与概念说明:docs/concepts/oauth.md、docs/gateway/authentication.md
  • 系统服务与监控脚本:scripts/systemd/*、scripts/auth-monitor.sh
  • 扩展插件 OAuth:extensions/*/oauth.ts
graph TB subgraph "认证核心" A["auth-profiles/types.ts
类型定义"] B["auth-profiles/store.ts
存储加载/合并/保存"] C["auth-profiles/oauth.ts
OAuth解析/刷新/故障转移"] D["auth-profiles/credential-state.ts
令牌有效期/资格评估"] E["auth-health.ts
健康检查汇总"] end subgraph "配置与密钥" F["secrets/configure.ts
密钥配置解析"] G["secrets/configure-plan.ts
配置变更计划"] H["secrets/credential-matrix.ts
凭证矩阵"] end subgraph "文档与脚本" I["docs/concepts/oauth.md"] J["docs/gateway/authentication.md"] K["scripts/systemd/*.service/*.timer"] L["scripts/auth-monitor.sh"] end A --> B --> C --> D C --> E F --> G --> H I --> C J --> C K --> L

核心组件

  • 认证档案类型与使用统计:定义 api_key、token、oauth 三种凭证类型,以及每档案的使用统计(冷却、禁用、失败计数等),用于轮转与故障转移。
  • 存储加载/合并/保存:支持主代理与子代理的认证档案合并;兼容旧版 auth.json 迁移;写入时对明文敏感字段进行清理。
  • OAuth 解析与刷新:统一解析并生成可用的 API Key;在过期时加锁刷新;针对特定提供商提供专用刷新逻辑;失败时执行多级故障转移(主代理继承、备用档案、提示诊断)。
  • 令牌有效期与资格评估:判断 access/token/expires 的有效性;为健康检查与轮转提供依据。
  • 健康检查汇总:按档案与提供商聚合状态(ok/expiring/expired/missing/static),并格式化剩余时间。
  • 配置与密钥管理:解析 SecretRef(env/file/exec)、构建配置变更计划、生成严格用户提供的凭证矩阵,确保只纳入不可运行时生成或轮换的凭证。

架构总览

认证系统围绕"认证档案存储"和"凭证解析/刷新"两条主线展开,并通过"健康检查"和"配置计划"实现可观测性与可维护性。

sequenceDiagram participant Caller as "调用方" participant Store as "认证存储
store.ts" participant OAuth as "OAuth解析/刷新
oauth.ts" participant Provider as "提供商刷新器
provider refreshers" participant Health as "健康检查
auth-health.ts" Caller->>Store : 加载/合并认证档案 Store-->>Caller : 返回合并后的档案 Caller->>OAuth : 解析指定档案的API Key OAuth->>OAuth : 检查有效期/兼容性 alt 已过期 OAuth->>Provider : 刷新令牌(带文件锁) Provider-->>OAuth : 新令牌/凭证 OAuth->>Store : 写回新凭证 end OAuth-->>Caller : 返回可用API Key Caller->>Health : 生成健康摘要 Health-->>Caller : 汇总状态与剩余时间

详细组件分析

组件A:认证档案与存储(合并、迁移、持久化)

  • 加载与合并:支持主代理与子代理的档案合并;若子代理无档案则从主代理继承;运行时可合并多个代理快照。
  • 兼容与迁移:自动识别并迁移旧版 auth.json;将外部 CLI 凭证同步到当前存储;删除迁移后遗留的旧文件。
  • 安全写入:保存时对明文密钥进行清理,仅保留引用(keyRef/tokenRef),避免明文泄露。
  • 文件锁保护:所有写操作使用文件锁,重试策略避免并发冲突。
flowchart TD Start(["开始"]) --> Load["加载auth-profiles.json"] Load --> Exists{"存在?"} Exists --> |否| Legacy["尝试加载auth.json(旧版)"] Exists --> |是| Merge["合并主/子代理档案"] Legacy --> ApplyLegacy["应用旧版条目到新格式"] ApplyLegacy --> Merge Merge --> Sync["同步外部CLI凭证"] Sync --> Save{"是否需要写入?"} Save --> |是| Clean["清理明文密钥"] Clean --> Persist["保存到磁盘(带文件锁)"] Save --> |否| End(["结束"]) Persist --> End

组件B:OAuth 解析、刷新与故障转移

  • 模式兼容:允许 token 与 oauth 在某些场景互换(Bearer 场景)。
  • 解析流程:先检查本地有效期,未过期直接返回;过期则加锁刷新。
  • 提供商专用刷新:针对 chutes、qwen-portal 等提供专用刷新逻辑;通用提供商通过统一接口刷新。
  • 故障转移:
    • 若刷新失败且存在较新的主代理凭证,则采用主代理凭证;
    • 尝试备用档案(基于默认档案修复建议);
    • 若仍失败,尝试从主代理复制新鲜凭证到当前代理;
    • 特定提供商(如 openai-codex)在特定错误条件下使用缓存的 access token 作为回退;
    • 最终抛出带诊断提示的错误信息。
sequenceDiagram participant API as "调用方" participant OA as "OAuth解析
oauth.ts" participant Lock as "文件锁" participant Prov as "提供商刷新器" participant Main as "主代理存储" API->>OA : 解析档案API Key OA->>OA : 检查有效期 alt 未过期 OA-->>API : 直接返回 else 已过期 OA->>Lock : 获取文件锁 Lock-->>OA : 成功 OA->>Prov : 刷新令牌 alt 刷新成功 Prov-->>OA : 新凭证 OA->>OA : 写回存储 OA-->>API : 返回新API Key else 失败 OA->>Main : 检查主代理是否有更新凭证 alt 主代理有更新 Main-->>OA : 返回新凭证 OA-->>API : 返回新API Key else 回退策略 OA-->>API : 抛出错误(含诊断提示) end end end

组件C:令牌有效期与资格评估

  • 令牌状态:缺失、有效、已过期、无效(非数值/非正数)。
  • 资格评估:对 api_key/token/oauth 分别校验是否存在有效凭据;对 token 还需检查 expires 字段有效性与是否过期。
flowchart TD S(["开始"]) --> Type{"凭证类型?"} Type --> |api_key| CheckAK["校验key或keyRef是否存在"] Type --> |token| CheckTok["校验token或tokenRef
并检查expires"] Type --> |oauth| CheckOauth["校验access或refresh是否存在"] CheckAK --> AKOK{"有效?"} CheckTok --> TokOK{"有效?"} CheckOauth --> OauthOK{"有效?"} AKOK --> |是| OK["返回可用"] AKOK --> |否| Err["返回不可用及原因"] TokOK --> |是| OK TokOK --> |否| Err OauthOK --> |是| OK OauthOK --> |否| Err

组件D:认证健康检查与状态监控

  • 按档案与提供商聚合状态,区分 ok/expiring/expired/missing/static。
  • 对 OAuth 与 token:当存在有效 refresh_token 时,即使 access 过期也不警告,因为会自动续期。
  • 支持自定义告警阈值(默认 24 小时),并提供短格式剩余时间展示。
flowchart TD HStart(["开始"]) --> Build["构建档案健康列表"] Build --> Group["按提供商分组"] Group --> Status["计算提供商状态"] Status --> Warn{"是否接近过期?"} Warn --> |是| Expiring["标记为即将过期"] Warn --> |否| Ok["标记为正常"] Expiring --> HEnd(["输出汇总"]) Ok --> HEnd

组件E:API 密钥轮换与实时认证键处理

  • 轮换顺序(网关环境变量):OPENCLAW_LIVE__KEY > _API_KEYS > _API_KEY > API_KEY*。
  • 仅在速率限制类错误(如 429、rate_limit、quota、resource exhausted)时进行轮换。
  • 合法性与去重:轮换前对密钥列表去重,最终失败返回最后一次尝试的错误。

组件F:认证配置合并、优先级排序与故障恢复

  • 合并策略:主代理与子代理档案合并,后者覆盖前者同名项;版本取较大者。
  • 优先级排序:支持 per-agent 的 auth.order 覆盖全局配置,按 provider 分组的 profileId 列表决定首选顺序。
  • 故障恢复:当某档案不可用时,系统尝试备用档案或从主代理继承;若仍失败,输出诊断提示并抛错。

组件G:安全策略、令牌管理与访问控制

  • 凭证表面:严格限定"用户直接提供"的凭证,不包含运行时生成或轮换的凭证;生成严格凭证矩阵,标注排除项。
  • 权限审计:对凭据目录进行权限检查(可写/可读),给出修复建议(POSIX 权限模式 0700)。
  • 机密输入:支持 env/file/exec 三类 SecretRef;在保存时清理明文,仅保留引用。

依赖关系分析

  • 类型依赖:types.ts 为其他模块提供统一的数据结构;store.ts 依赖 types.ts;oauth.ts 依赖 store.ts 与 credential-state.ts。
  • 外部集成:oauth.ts 依赖 @mariozechner/pi-ai 的 OAuth 提供商能力;针对特定提供商(如 qwen-portal、chutes)有专用刷新器。
  • 配置与密钥:configure.ts 与 configure-plan.ts 依赖 secrets 解析与凭证矩阵,确保变更可控与可审计。
graph LR Types["types.ts"] --> Store["store.ts"] Store --> OAuth["oauth.ts"] State["credential-state.ts"] --> OAuth OAuth --> Health["auth-health.ts"] SecCfg["secrets/configure.ts"] --> Plan["secrets/configure-plan.ts"] Plan --> Matrix["secrets/credential-matrix.ts"]

性能考量

  • 文件锁与重试:写操作采用指数回退与最大超时,降低并发写入冲突概率。
  • 运行时快照:支持多代理运行时快照合并,减少重复 IO。
  • 健康检查:按提供商聚合状态,避免对每个档案单独检查带来的开销。
  • 轮换策略:仅在速率限制错误时切换密钥,避免不必要的网络往返。

沙箱与安全机制

围绕"沙箱与安全"的关键模块分布于 agents/sandbox 及其子模块,配合配置校验、路径与媒体处理、工具策略与文件系统策略等模块协同工作,形成从配置到运行时的完整安全闭环。

graph TB subgraph "沙箱核心" A["validate-sandbox-security.ts
安全校验与拒绝列表"] B["host-paths.ts
主机路径归一化/解析"] C["constants.ts
默认镜像/前缀/端口/注册表路径"] D["network-mode.ts
网络模式阻断判定"] E["bind-spec.ts
绑定规范解析"] F["docker.ts
构建创建参数/执行docker"] G["sandbox-paths.ts
沙箱路径解析/边界检查"] H["sandbox-media-paths.ts
媒体路径解析/桥接"] I["sandbox-tool-policy.ts
工具策略合并"] J["tool-fs-policy.ts
工具文件系统策略"] end subgraph "配置与测试" K["zod-schema.agent-runtime.ts
Zod配置校验"] L["config.sandbox-docker.test.ts
配置测试"] M["sandbox-create-args.test.ts
创建参数测试"] N["sandbox-paths.test.ts
路径测试"] O["sandbox-media-paths.test.ts
媒体路径测试"] P["sandbox-tool-policy.test.ts
工具策略测试"] Q["tool-fs-policy.test.ts
工具FS策略测试"] R["validate-sandbox-security.test.ts
安全校验测试"] end A --> F B --> A C --> F D --> A E --> A G --> H I --> J K --> A K --> F L --> K M --> F N --> G O --> H P --> I Q --> J R --> A

核心组件

  • 安全校验与拒绝列表:对绑定挂载、网络模式、安全配置(seccomp/AppArmor)进行严格校验,阻止高危配置。
  • 主机路径处理:路径归一化、通过现有祖先解析以规避符号链接逃逸。
  • 常量与默认值:默认镜像、容器前缀、工作目录、浏览器专用网络与端口、注册表路径等。
  • 网络模式阻断:禁止 host 模式与容器命名空间加入,确保网络隔离。
  • 绑定规范解析:解析 host:container[:options] 规范,支持 Windows 驱动器前缀。
  • Docker 创建参数构建:将安全校验结果与资源限制、能力(drop/no-new-privileges)、安全选项(seccomp/apparmor)、DNS/hosts 等注入到 docker create 参数。
  • 路径与媒体策略:路径边界检查、相对路径展开、file:// 与 http:// 处理、临时媒体目录白名单。
  • 工具策略与文件系统策略:允许/拒绝工具集合的合并与生效;工具仅限工作区访问的策略解析。

架构总览

下图展示沙箱创建与安全校验在运行时的关键交互流程。

sequenceDiagram participant Caller as "调用方" participant Builder as "buildSandboxCreateArgs" participant Validator as "validateSandboxSecurity" participant Docker as "execDocker" participant FS as "宿主机文件系统" Caller->>Builder : 提供SandboxDockerConfig与上下文 Builder->>Validator : 传入binds/network/seccomp/apparmor等 Validator-->>Builder : 返回校验结果或抛出错误 Builder->>Docker : 生成docker create参数并执行 Docker->>FS : 写入标签/挂载/安全选项 Docker-->>Caller : 返回容器名/状态

详细组件分析

安全校验与拒绝列表

  • 目标:阻止危险的 Docker 配置,包括系统路径暴露、保留容器目标路径、非绝对源路径、host 网络、容器命名空间加入、禁用 seccomp/AppArmor 等。
  • 关键点:
    • BLOCKED_HOST_PATHS:禁止挂载 /etc、/proc、/sys、/dev、/root、/boot、常见 Docker 套接字路径等。
    • BLOCKED_SECCOMP_PROFILES/BLOCKED_APPARMOR_PROFILES:禁用 unconfined。
    • RESERVED_CONTAINER_TARGET_PATHS:禁止覆盖 /workspace 与代理工作区挂载点。
    • getBlockedBindReason/getOutsideAllowedRootsReason/getReservedTargetReason:三类拒绝原因。
    • enforceSourcePathPolicy:结合 allowedRoots 与 allowSourcesOutsideAllowedRoots 进行策略判断。
    • validateNetworkMode:阻断 host 与 container:*(除非显式允许)。
    • validateSeccompProfile/validateApparmorProfile:阻断禁用配置。
flowchart TD Start(["进入 validateBindMounts"]) --> CheckEmpty{"binds为空?"} CheckEmpty --> |是| EndOK["返回"] CheckEmpty --> |否| Loop["遍历每个bind"] Loop --> FastCheck["字符串级阻断检查
getBlockedBindReason"] FastCheck --> Blocked{"被拒绝?"} Blocked --> |是| ThrowFast["抛出错误"] Blocked --> |否| Reserved{"允许保留目标?"} Reserved --> |否| CheckReserved["getReservedTargetReason"] CheckReserved --> ReservedBlocked{"命中保留目标?"} ReservedBlocked --> |是| ThrowReserved["抛出错误"] ReservedBlocked --> |否| Normalize["normalizeHostPath"] ReservedBlocked --> |是| Normalize Normalize --> Policy["enforceSourcePathPolicy"] Policy --> Ancestor["通过现有祖先解析
resolveSandboxHostPathViaExistingAncestor"] Ancestor --> Policy2["再次 enforceSourcePathPolicy"] Policy2 --> Next["下一个bind"] Next --> Loop Loop --> EndOK

主机路径处理与符号链接硬防

  • 归一化:POSIX 路径规范化(.、..、//、尾部斜杠),Windows 前缀剥离与 UNC 规范化。
  • 解析:通过现有祖先解析,即使最终叶子不存在也能正确识别真实父链,防止符号链接逃逸。
flowchart TD A["输入原始路径"] --> B["stripWindowsNamespacePrefix"] B --> C["posix.normalize + 去除尾斜杠"] C --> D{"是否为空?"} D --> |是| E["返回'/'"] D --> |否| F["返回规范化路径"]

常量与默认值

  • 默认镜像、容器前缀、工作目录、空闲/最大存活时间。
  • 默认工具允许/拒绝清单(如 exec、process、read/write/edit、apply_patch、image、会话相关工具等)。
  • 浏览器沙箱镜像与通用镜像、浏览器网络与端口、自动启动超时。
  • 代理工作区挂载点、状态目录与注册表路径。

网络模式阻断

  • 归一化网络模式后,阻断 host 与 container:*(除非允许容器命名空间加入)。
  • isDangerousNetworkMode 提供快速判定。

绑定规范解析

  • 支持 host:container[:options],兼容 Windows 驱动器前缀与 UNC。
  • 用于解析源/目标路径与可选挂载选项。

Docker 创建参数构建与执行

  • 构建阶段:
    • 先执行 validateSandboxSecurity,再拼装标签、只读根文件系统、tmpfs、网络、用户、环境变量(含敏感项阻断/告警)、能力 drop、no-new-privileges、seccomp/apparmor、DNS/hosts、PID/内存/CPU/ulimit、binds。
    • 自动追加工作区挂载与自定义 binds。
  • 执行阶段:
    • 确保镜像存在,创建容器并启动;可选执行 setupCommand。
    • 注册表更新与热容器窗口提示。
sequenceDiagram participant Cfg as "SandboxDockerConfig" participant Args as "buildSandboxCreateArgs" participant Sec as "validateSandboxSecurity" participant Exec as "execDocker" participant Reg as "注册表" Cfg->>Args : 传入配置与上下文 Args->>Sec : 安全校验 Sec-->>Args : 通过或抛错 Args->>Exec : docker create + start Exec-->>Reg : 更新容器信息 Reg-->>Args : 返回容器名

沙箱路径管理

  • 输入路径解析:支持 / 前缀展开、相对路径转绝对、Unicode 空格规范化。
  • 边界检查:assertSandboxPath 确保相对路径不逃逸沙箱根,使用路径别名守卫避免符号/硬链接逃逸。
  • 媒体路径处理:
    • 不支持 data: URL;file:// URL 与 http:// URL 分别处理。
    • 将容器内 /workspace 映射回宿主机工作区或临时媒体目录(受控白名单)。
    • 临时媒体目录必须位于 OpenClaw 临时目录内且不逃逸。
flowchart TD S["输入媒体路径"] --> T{"是否为file://或http://?"} T --> |http://| U["直接返回URL"] T --> |file://| V["尝试映射容器/workspace"] V --> W{"映射成功?"} W --> |是| X["返回映射后的宿主机路径"] W --> |否| Y["fileURLToPath转换"] Y --> Z["映射容器/workspace或临时目录"] T --> |都不是| Z Z --> A{"是否在临时目录?"} A --> |是| B["校验不逃逸临时根"] A --> |否| C["assertSandboxPath校验"] B --> D["返回宿主机路径"] C --> D

工具策略与文件系统策略

  • 工具策略:
    • pickSandboxToolPolicy 合并 allow/alsoAllow/deny,支持通配符与 apply_patch 特例。
  • 文件系统策略:
    • resolveEffectiveToolFsWorkspaceOnly 基于全局与代理配置解析 workspaceOnly 策略,强制工具仅访问工作区。

依赖关系分析

  • validateSandboxSecurity 依赖:
    • bind-spec:解析绑定规范
    • host-paths:路径归一化与祖先解析
    • network-mode:网络模式阻断
    • constants:代理工作区挂载常量
  • docker.ts 依赖:
    • validateSandboxSecurity:运行时安全校验
    • constants:默认镜像/前缀/注册表路径
    • sanitize-env-vars:环境变量阻断/告警
  • sandbox-paths 与 sandbox-media-paths 依赖:
    • path-alias-guards/path-guards:边界与别名检查
    • tmp-openclaw-dir:临时目录解析
graph LR VS["validate-sandbox-security.ts"] --> BS["bind-spec.ts"] VS --> HP["host-paths.ts"] VS --> NM["network-mode.ts"] VS --> CT["constants.ts"] DK["docker.ts"] --> VS DK --> CT DK --> EV["sanitize-env-vars.js"] SP["sandbox-paths.ts"] --> PG["path-guards.js"] SP --> PA["path-alias-guards.js"] SP --> TMP["tmp-openclaw-dir.js"] SMP["sandbox-media-paths.ts"] --> SP

性能考量

  • 路径解析与边界检查为纯字符串与少量文件系统 I/O,开销较低。
  • 安全校验在创建前集中执行,避免运行期反复校验。
  • 通过只读根文件系统、tmpfs、ulimit、CPU/内存限制降低容器资源占用风险。
  • 热容器窗口(最近使用)提示减少频繁重建带来的开销。

AI 代理系统

OpenClaw 采用"网关控制平面 + 多通道接入 + 代理运行时"的分层架构:

  • 网关(Gateway)作为统一控制平面,承载会话、路由、事件与工具调用编排;
  • 代理运行时以 Pi 代理为核心,支持嵌入式运行、工具流式与块流式输出;
  • 通过插件化渠道适配器连接 WhatsApp、Telegram、Discord、iMessage 等消息平台;
  • 提供 CLI、Web 控制台与移动端节点,形成完整的本地优先、自托管智能体生态。
graph TB subgraph "客户端与入口" UI["Web 控制台"] CLI["命令行(openclaw ...)"] Nodes["iOS/Android 节点"] end subgraph "网关控制平面" GW["Gateway WebSocket 控制面"] Sessions["会话与路由"] Tools["工具与动作编排"] end subgraph "代理运行时" Pi["Pi 代理(嵌入式)"] Streams["工具流式/块流式输出"] end subgraph "渠道适配" WA["WhatsApp 插件"] TG["Telegram 插件"] DC["Discord 插件"] IM["iMessage/BlueBubbles 插件"] end UI --> GW CLI --> GW Nodes --> GW GW --> Sessions GW --> Tools GW --> Pi Pi --> Streams Tools --> WA Tools --> TG Tools --> DC Tools --> IM

核心组件

  • 代理运行时与生命周期
    • 嵌入式 Pi 代理运行器负责执行推理、工具调度、流式输出与运行状态管理。
    • 关键导出包括运行控制(启动/队列/中止/等待结束)、历史限制与会话车道解析、沙箱信息构建、系统提示覆盖与工具拆分等。
  • 消息与工具
    • 统一的消息工具识别与发送判定逻辑,支持核心消息工具与各渠道插件的动作提取。
    • 块级回复载荷结构用于组织文本、媒体、语音与回执标记。
  • 认证与凭据
    • 将认证档案转换为 Pi 代理可用的 API Key 或 OAuth 凭据映射,并进行相等性比较。
  • 辅助与错误分类
    • 错误分类与降级策略、图像与转录内容清洗、Turn 序列校验、思维层级降级等。
  • 运行时环境
    • 标准 I/O 输出与退出行为封装,便于测试与非退出模式使用。

架构总览

下图展示从消息入口到代理执行、工具调用与响应返回的端到端流程,强调会话与上下文在代理运行时中的作用。

sequenceDiagram participant User as "用户" participant Channel as "渠道插件(如 Telegram)" participant GW as "网关控制平面" participant Runner as "Pi 代理运行器" participant Tools as "工具/动作编排" participant Out as "外部服务/渠道" User->>Channel : 发送消息 Channel->>GW : 解析并转发消息事件 GW->>Runner : 触发会话上下文加载与推理 Runner->>Runner : 工具调用计划与流式/块式生成 Runner->>Tools : 执行具体工具(消息发送/节点动作/浏览器控制等) Tools->>Out : 调用外部接口或设备能力 Out-->>Tools : 返回结果 Tools-->>Runner : 工具执行结果 Runner-->>GW : 流式/块式输出与最终回复 GW-->>Channel : 将回复投递至对应渠道 Channel-->>User : 展示最终消息

详细组件分析

代理运行时与生命周期

  • 运行器职责
    • 启动/排队/中止/等待嵌入式 Pi 代理运行,维护运行元数据与结果。
    • 历史回合限制与会话车道解析,确保上下文规模可控与并发会话隔离。
    • 沙箱信息构建与系统提示覆盖,满足不同场景下的安全与提示一致性。
    • 工具拆分与额外参数应用,提升跨模型兼容性与运行稳定性。
  • 生命周期管理
    • 通过运行状态查询与等待结束,实现对长尾任务的可观测与可中断。
    • 结合会话修剪与紧凑化策略,降低上下文开销并维持长期对话质量。
flowchart TD Start(["开始运行"]) --> Load["加载会话上下文
解析历史限制/车道"] Load --> Plan["生成工具调用计划"] Plan --> Stream{"是否需要流式输出?"} Stream --> |是| Chunk["块流式/工具流式输出"] Stream --> |否| Final["生成最终回复"] Chunk --> Monitor["监控运行状态/队列"] Final --> Monitor Monitor --> Done(["结束/等待下一轮"])

会话管理与上下文保持

  • 会话键与历史限制
    • 支持基于会话键的历史回合裁剪,兼顾 DM 与群组场景的差异化上限。
  • 上下文紧凑化
    • 提供紧凑化能力以减少上下文长度,缓解超限风险并保持语义连贯。
  • 会话车道
    • 会话车道解析用于区分不同运行路径或优先级,保障资源分配与隔离。

工具流式传输与块流式处理

  • 工具与消息工具识别
    • 统一识别核心消息工具与各渠道插件的动作,确保发送类工具被正确提取与执行。
  • 块级回复载荷
    • 文本、媒体 URL、音频转语音、推理标记、回执标识与回复目标等字段构成块级输出的基础结构。
  • 流式输出
    • 在工具执行与模型生成过程中,按块推送中间结果,提升交互体验与可观测性。
classDiagram class MessagingToolSend { +tool : string +provider : string +accountId? : string +to? : string +threadId? : string } class BlockReplyPayload { +text? : string +mediaUrls? : string[] +audioAsVoice? : boolean +isReasoning? : boolean +replyToId? : string +replyToTag? : boolean +replyToCurrent? : boolean } MessagingToolSend <.. BlockReplyPayload : "组合/传递"

代理配置、模型选择与认证轮换

  • 模型选择
    • 通过标准化的提供方 ID 归一化与凭据映射,支持多提供商与多模型的灵活切换。
  • 认证轮换
    • 将认证档案转换为 API Key 或 OAuth 凭据,自动处理过期与刷新条件,保证连续可用性。
  • 故障转移策略
    • 错误分类与降级策略(如速率限制、计费错误、上下文溢出、超时等),结合备用凭据与备用模型实现自动切换。
flowchart TD A["输入认证档案"] --> B["归一化提供方ID"] B --> C{"类型判断(API Key/Token/OAuth)"} C --> |API Key| D["直接映射"] C --> |Token| E["检查过期/转换为API Key"] C --> |OAuth| F["提取访问/刷新/过期时间"] D --> G["凭据映射完成"] E --> G F --> G G --> H["错误分类与降级策略"] H --> I["故障转移/重试/备用凭据"]

代理沙箱机制、安全隔离与权限控制

  • 沙箱模式
    • 非主会话(群组/频道)默认启用容器化沙箱,限制工具集与文件系统访问,仅允许必要工具(如会话列表/历史/发送等)。
  • 权限控制
    • macOS 节点通过网关协议暴露能力与权限映射,本地动作需遵循 TCC 状态;可按会话启用/禁用"提升权限"模式并持久化。
  • 安全建议
    • 默认仅主会话拥有主机执行权限;群组/频道会话置于沙箱内运行,避免越权操作。

代理生命周期管理、状态持久化与性能优化

  • 生命周期
    • 运行器提供运行状态查询、队列注入、中止与结束等待,便于长任务与并发场景的精细化控制。
  • 状态持久化
    • macOS 场景下,会话的思考级别、详细程度、模型、发送策略与群组激活等可通过会话补丁持久化。
  • 性能优化
    • 历史回合裁剪、上下文紧凑化、Turn 序列校验与图像/转录内容清洗,降低计算与存储压力。
    • 思维层级降级与工具拆分提升跨模型兼容性与稳定性。

多代理路由、会话隔离与资源管理

  • 多代理路由
    • 支持按发送者、工作区与代理维度进行会话隔离与路由,实现多代理协作与资源隔离。
  • 会话隔离
    • 不同会话拥有独立上下文与工具执行边界,避免相互干扰。
  • 资源管理
    • 通过会话车道、历史限制与沙箱策略,平衡并发度与资源占用。

依赖关系分析

  • 运行时 I/O
    • 运行时封装了日志输出与进程退出,支持测试环境下的非退出模式,便于单元测试与集成测试。
  • 代理运行器
    • 导出运行控制、历史限制、车道解析、沙箱信息、系统提示覆盖、工具拆分与类型定义,形成代理执行的统一入口。
  • 消息与工具
    • 消息工具识别与发送判定依赖渠道插件的动作提取能力,形成"核心工具 + 插件动作"的扩展模型。
  • 辅助与错误分类
    • 错误分类与降级策略贯穿代理执行链路,配合凭据映射与 Turn 校验,提升鲁棒性。
graph LR RT["runtime.ts"] --> ER["pi-embedded-runner.ts"] ER --> EM["pi-embedded-messaging.ts"] ER --> EP["pi-embedded-payloads.ts"] ER --> EH["pi-embedded-helpers.ts"] EH --> AC["pi-auth-credentials.ts"]

性能考量

  • 上下文规模控制
    • 使用历史回合裁剪与上下文紧凑化,避免超限导致的失败与延迟。
  • 流式输出
    • 工具流式与块流式输出缩短首包延迟,改善用户体验。
  • Turn 校验与内容清洗
    • 对 Turn 序列与图像/媒体内容进行清洗与降级,减少无效负载与错误重试。
  • 思维层级降级
    • 在高负载或不稳定网络下自动降级思维层级,维持稳定响应。

Pi 嵌入式运行时

Pi 嵌入式运行时位于 src/agents 下,核心入口为 pi-embedded.ts,实际运行逻辑集中在 pi-embedded-runner 子目录;配套的订阅、工具、扩展、系统提示、历史限制、沙箱信息、会话缓存、压缩安全护栏与上下文修剪等模块共同构成完整的嵌入式运行时。

graph TB A["pi-embedded.ts
导出运行与状态查询接口"] --> B["pi-embedded-runner.ts
再导出运行器子模块"] B --> C["run.ts
runEmbeddedPiAgent 主入口"] C --> D["run/attempt.ts
单次尝试与会话初始化"] C --> E["subscribeEmbeddedPiSession
事件订阅与流式处理"] C --> F["compact.ts
手动/自动压缩"] C --> G["model.ts
模型解析与鉴权"] C --> H["system-prompt.ts
系统提示构建"] C --> I["tool-split.ts
工具拆分策略"] C --> J["history.ts
历史限制"] C --> K["google.ts
Google/Gemini 兼容处理"] C --> L["sandbox-info.ts
沙箱信息"] C --> M["session-manager-cache.ts
会话缓存"] C --> N["extensions.ts
扩展加载"] C --> O["compaction-safety-timeout.ts
压缩安全超时"] C --> P["payloads.ts
响应负载构建"] C --> Q["block-chunker.ts
块级流式分块"] C --> R["messaging.ts
消息发送追踪"] C --> S["helpers.ts
错误分类与校验"]

核心组件

  • 运行器入口与状态查询
    • 导出 runEmbeddedPiAgent、queueEmbeddedPiMessage、waitForEmbeddedPiRunEnd、isEmbeddedPiRunActive、isEmbeddedPiRunStreaming、abortEmbeddedPiRun、compactEmbeddedPiSession、resolveEmbeddedSessionLane 等接口,统一对外暴露嵌入式运行时能力。
  • 运行时类型与元数据
    • EmbeddedPiRunMeta/EmbeddedPiRunResult/EmbeddedPiCompactResult 等类型定义运行元信息、运行结果与压缩结果。
  • 会话与订阅
    • subscribeEmbeddedPiSession 订阅 AgentSession 事件,驱动流式文本、思考、工具执行、回合与自动压缩等事件的回调处理。
  • 工具与系统提示
    • createOpenClawCodingTools 构建工具集;splitSdkTools 将工具全部归入 customTools;system-prompt 构建动态系统提示。
  • 历史与上下文
    • history 限制 DM 与群组历史;context-engine 类型定义上下文组装与压缩结果;session-manager-cache 缓存会话以提升性能。
  • 扩展与兼容
    • extensions 加载压缩安全护栏与上下文修剪扩展;google 处理 Gemini 转写顺序与工具 schema;compaction-safety-timeout 保护压缩过程。
  • 消息与块级流式
    • block-chunker 将流式文本切分为块;payloads 负责从运行结果构建响应负载;messaging 追踪消息发送目标与媒体。

架构总览

Pi 嵌入式运行时采用"直接 SDK 引入 + 事件驱动"的架构:通过 createAgentSession 创建会话,随后订阅 AgentSession 事件,结合系统提示、工具链、历史限制与扩展,完成一次完整的嵌入式运行周期。运行器还提供队列消息、等待运行结束、主动中断、会话压缩等运行期能力。

sequenceDiagram participant Caller as "调用方" participant Runner as "运行器
runEmbeddedPiAgent" participant Session as "AgentSession" participant Sub as "订阅器
subscribeEmbeddedPiSession" participant Tools as "工具集" participant Ext as "扩展" participant Store as "会话存储" Caller->>Runner : "传入参数与回调" Runner->>Session : "创建会话(createAgentSession)" Runner->>Sub : "订阅事件(流式文本/思考/工具/回合/压缩)" Runner->>Session : "prompt(有效提示)" Session-->>Sub : "事件(message/tool/turn/compaction)" Sub-->>Caller : "onBlockReply/onPartialReply/..." Runner->>Tools : "执行工具调用" Tools-->>Session : "返回工具结果" Runner->>Ext : "应用扩展(压缩/修剪)" Runner->>Store : "持久化会话(缓存/修复)" Runner-->>Caller : "返回运行结果与元数据"

详细组件分析

运行器初始化与会话生命周期

  • 初始化阶段
    • 解析模型与鉴权、准备沙箱上下文、构建系统提示、加载扩展、预热会话缓存、修复会话文件、应用转录策略与工具允许列表。
  • 会话创建
    • 使用 DefaultResourceLoader 注册扩展工厂并 reload;通过 createAgentSession 创建会话,应用系统提示覆盖。
  • 生命周期事件
    • 订阅 message/tool/turn/agent/compaction 等事件,驱动流式输出与工具执行。
flowchart TD Start(["开始"]) --> ResolveModel["解析模型与鉴权"] ResolveModel --> Sandbox["解析沙箱上下文"] Sandbox --> SysPrompt["构建系统提示"] SysPrompt --> Ext["加载扩展工厂并reload"] Ext --> Session["创建AgentSession"] Session --> ApplyPrompt["应用系统提示覆盖"] ApplyPrompt --> WarmCache["预热会话缓存/修复会话"] WarmCache --> Ready(["就绪"]) Ready --> Prompt["prompt(有效提示)"] Prompt --> Events["事件驱动(流式/工具/回合/压缩)"] Events --> End(["结束/返回结果"])

会话订阅与消息处理

  • 订阅器职责
    • 接收 AgentSession 事件,将流式文本与思考内容按块分发给 onBlockReply/onPartialReply;处理工具执行、回合与自动压缩事件。
  • 块级流式分块
    • EmbeddedBlockChunker 将连续流式片段聚合成块,剥离思考标签,提取最终内容与回复指令(媒体、语音、回复ID)。
  • 消息发送追踪
    • pi-embedded-messaging 记录通过消息工具发送成功的文本、媒体与目标,用于抑制确认文本与统计。
sequenceDiagram participant Sub as "订阅器" participant Chunk as "块分块器" participant Handler as "回调(onBlockReply/onPartialReply)" participant Msg as "消息追踪" Sub->>Chunk : "接收流式文本" Chunk-->>Handler : "块级文本/媒体/指令" Handler-->>Msg : "记录发送成功项" Handler-->>Sub : "触发回调"

历史记录管理与上下文保持

  • 历史限制
    • 根据会话键与配置决定 DM 与群组的历史轮次限制,减少上下文开销。
  • 历史清洗与配对修复
    • 在截断后重新修复 tool_use 与 tool_result 的配对关系,保证上下文一致性。
  • 上下文引擎
    • context-engine/types 定义上下文组装、压缩与引导结果的数据结构,支撑运行期上下文度量与报告。
flowchart TD Load["读取会话消息"] --> Sanitize["历史清洗(Gemini/Anthropic校验)"] Sanitize --> Truncate["按渠道类型截断历史轮次"] Truncate --> Repair["修复tool_use/tool_result配对"] Repair --> Apply["应用到会话消息"] Apply --> Report["生成上下文度量与报告"]

嵌入式工具定义与消息提供者策略

  • 工具拆分策略
    • splitSdkTools 将所有工具放入 customTools,确保 OpenClaw 的策略过滤、沙箱集成与扩展工具集一致。
  • 工具定义适配
    • 将 AgentTool 的 execute 签名适配为 ToolDefinition,保证与 pi-coding-agent 的调用约定一致。
  • 消息提供者策略
    • 根据通道能力与配置,注入 inlineButtons、反应指导、消息动作提示等,影响系统提示与行为。
classDiagram class ToolSplit { +splitSdkTools(options) : {builtInTools, customTools} } class Adapter { +toToolDefinitions(tools) : ToolDefinition[] } class ProviderPolicy { +channelCapabilities +inlineButtons +reactionGuidance +messageToolHints } ToolSplit --> Adapter : "转换为ToolDefinition" ProviderPolicy --> ToolSplit : "影响工具允许列表"

模型兼容性与提供商特定处理

  • 模型解析与鉴权
    • resolveModel 通过 ModelRegistry 与 AuthStorage 获取模型与密钥;针对 GitHub Copilot 等特殊场景进行令牌转换。
  • 提供商特定处理
    • Google/Gemini:turn ordering 修复、工具 schema 清理、历史清洗;Anthropic:拒绝文本清理、回合校验;OpenAI:apply_patch 工具与思考级别降级。
  • 流式参数与 Ollama
    • extra-params 提供提供商特定流式参数;Ollama 通过自定义流函数注册,确保本地模型兼容。
flowchart TD Resolve["resolveModel"] --> Auth["鉴权存储(setRuntimeApiKey)"] Auth --> Provider["提供商特定处理"] Provider --> Google["Google/Gemini: turn/ordering/schema"] Provider --> Anthropic["Anthropic: 拒绝/回合校验"] Provider --> OpenAI["OpenAI: apply_patch/降级"] Provider --> Ollama["Ollama: 自定义流函数注册"]

嵌入式运行时配置与运行期能力

  • 运行期状态查询
    • isEmbeddedPiRunActive/isEmbeddedPiRunStreaming 查询运行状态;queueEmbeddedPiMessage 向正在流式的运行追加消息;waitForEmbeddedPiRunEnd 等待运行结束。
  • 会话与命令通道
    • resolveEmbeddedSessionLane/全局 lanes 控制并发与优先级,避免死锁。
  • 压缩与安全护栏
    • compactEmbeddedPiSessionDirect 执行手动/自动压缩;compaction-safety-timeout 保护压缩过程;compaction-safeguard 与 context-pruning 扩展提供额外保障。
sequenceDiagram participant API as "外部API" participant Runs as "运行状态管理" participant Lane as "命令通道" participant Comp as "压缩" API->>Runs : "queueEmbeddedPiMessage" Runs-->>API : "是否入队成功" API->>Lane : "resolveEmbeddedSessionLane" Lane-->>API : "分配会话/全局通道" API->>Comp : "compactEmbeddedPiSession" Comp-->>API : "压缩结果与原因"

助手身份、历史与上下文保持

  • 助手身份
    • UI 层提供默认名称与头像,normalizeAssistantIdentity 统一输入,确保跨渠道一致性。
  • 历史与上下文
    • 通过历史限制、转录策略与上下文引擎,维持合理的上下文窗口与历史长度,避免溢出。

节点订阅与网关集成

  • 节点订阅管理
    • server-node-subscriptions 提供节点到会话的订阅映射,支持向指定会话广播事件;gateway-misc.test 展示事件路由与取消订阅行为。
  • 会话事件分发
    • 通过 sendToSession/sendToAllSubscribed 将运行期事件推送到已订阅节点,便于网关侧统一消费。
sequenceDiagram participant Manager as "节点订阅管理器" participant NodeA as "节点A" participant NodeB as "节点B" Manager->>NodeA : "订阅会话(main)" Manager->>NodeB : "订阅会话(main)" Manager->>Manager : "sendToSession('main', 'chat', payload)" Manager-->>NodeA : "事件(chat)" Manager-->>NodeB : "事件(chat)" Manager->>NodeA : "unsubscribeAll(nodeA)" Manager->>Manager : "sendToSession('main','tick',...)" Manager-->>NodeB : "事件(tick)"

开发指南、自定义实现与调试技巧

  • 开发指南
    • 使用 runEmbeddedPiAgent 作为统一入口;通过 onBlockReply/onPartialReply 获取流式输出;必要时使用 queueEmbeddedPiMessage 追加用户消息。
  • 自定义实现
    • 工具:通过 createOpenClawCodingTools 注入自定义工具;使用 tool-split 与 policy 控制可用工具集合。
    • 提示:通过 system-prompt 构建动态系统提示,注入渠道能力、反应指导、消息动作提示与沙箱信息。
    • 扩展:通过 extensions 加载压缩安全护栏与上下文修剪扩展,增强稳定性与性能。
  • 调试技巧
    • 启用日志与诊断:logger 提供子系统日志;compaction-diag 输出压缩前后的消息统计与贡献者分析。
    • 错误分类:helpers 提供上下文溢出、压缩失败、鉴权失败、限流等错误分类,辅助快速定位问题。
    • 等待运行结束:waitForEmbeddedPiRunEnd 提供超时控制,避免阻塞。

依赖关系分析

Pi 嵌入式运行时依赖 pi-* 生态包(pi-agent-core、pi-ai、pi-coding-agent、pi-tui),并通过 OpenClaw 的工具、系统提示、历史限制、扩展与会话管理形成闭环。

graph TB OpenClaw["OpenClaw 运行时"] --> PiCore["@mariozechner/pi-agent-core"] OpenClaw --> PiAI["@mariozechner/pi-ai"] OpenClaw --> PiCoding["@mariozechner/pi-coding-agent"] OpenClaw --> PiTUI["@mariozechner/pi-tui"] OpenClaw --> Tools["OpenClaw 工具集"] OpenClaw --> Prompt["系统提示构建"] OpenClaw --> History["历史限制/清洗"] OpenClaw --> Ext["Pi 扩展(压缩/修剪)"] OpenClaw --> Session["会话缓存/修复"]

性能考量

  • 会话缓存与预热
    • session-manager-cache 预热会话文件,减少重复解析成本;session-manager-init 确保会话头存在。
  • 历史限制与上下文修剪
    • history 限制 DM 与群组历史轮次;context-pruning 基于缓存 TTL 实现上下文修剪,降低上下文窗口压力。
  • 压缩安全护栏
    • compaction-safety-timeout 限制压缩耗时;compaction-safeguard 与 context-pruning 扩展在压缩过程中提供额外保护。
  • 工具与沙箱
    • splitSdkTools 将工具全部进入 customTools,便于统一策略与沙箱控制,减少不必要的内置工具开销。
相关推荐
im_AMBER1 小时前
从0到1实现块级编辑器的文件导入
前端·架构
不可能的是1 小时前
彻底搞懂 Module Federation(中中):MF 模块加载(上)
前端·webpack
毛骗导演1 小时前
万字解析 OpenClaw 源码架构-工具与自动化
前端
毛骗导演1 小时前
万字解析 OpenClaw 源码架构-代理系统(一)
前端·架构
波哥学开发1 小时前
🎯 Canvas 箭头绘制算法(附完整源码)
前端·计算机图形学
拖拉斯旋风1 小时前
从零到一:用 Node.js + LangChain + Milvus 打造《天龙八部》专属 RAG 问答机器人
前端
不可能的是1 小时前
彻底搞懂 Module Federation(中下):MF 模块加载(下)
前端·webpack
独特的账号1 小时前
前端浏览器插件的开发一步搞定
前端·react.js
李剑一1 小时前
超实用!数字孪生 Cesium 园区 3D 模型加载,一次学会的保姆级教程
前端·vue.js·cesium