模型集成与选择
简介
本文聚焦于"模型集成与选择"的完整实现,覆盖以下关键主题:
- 模型目录管理:本地与远程模型目录的加载、缓存与回退策略
- 能力检测与兼容性验证:基于目录条目的输入类型、推理能力与上下文窗口等属性进行校验
- 模型选择算法:别名解析、默认模型推断、允许列表与白名单控制
- 负载均衡与性能评估:通过基准脚本与使用聚合统计进行评估
- 配置合并与认证管理:提供者配置合并、密钥与基础 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(使用统计与可视化)
核心组件
- 模型选择与解析:负责模型引用字符串解析、别名索引、默认模型推断、允许列表与白名单控制、思考级别与推理默认值解析。
- 模型目录与发现:负责从 PI SDK 加载模型目录、合并配置化模型、应用合成回退、支持图像/文档输入能力查询。
- 配置合并与计划:负责隐式与显式提供者配置合并、密钥与基础 URL 的保留策略、生成 models.json 写入计划。
- 列表与可用性:负责模型行构建、可用性判断(优先模型级,其次提供者级认证启发式)、过滤与展示。
- 会话与覆盖:负责会话级模型覆盖、允许模型解析、默认模型回退。
- 媒体理解:根据能力筛选媒体理解模型,支持共享与能力配置两种来源。
- 性能与监控:基准脚本用于评估延迟与用量,使用聚合与 UI 视图用于成本、吞吐、错误率与缓存命中率等指标。
架构总览
模型集成与选择的整体流程包括:配置加载与隐式/显式提供者合并、模型目录加载与可用性探测、模型选择与会话覆盖、能力筛选与兼容性验证、故障转移与降级、性能评估与监控。
详细组件分析
组件A:模型选择与解析(model-selection)
- 关键职责
- 解析模型引用字符串(provider/model 或别名),标准化提供者 ID 与模型 ID
- 构建别名索引,支持按别名解析
- 默认模型推断:优先代理覆盖,其次配置默认,最后回退到硬编码默认
- 允许列表与白名单:允许任意或受控集合,合成未在目录中的条目
- 思考级别与推理默认值:基于模型目录与配置综合判定
- 数据结构与复杂度
- 别名索引:Map 查询 O(1),构建 O(N)
- 允许集合:Set 查询 O(1),构建 O(M)
- 依赖关系
- 依赖模型目录条目以判定允许性与合成条目
- 依赖代理作用域与默认配置
- 错误处理
- 对空引用、无效引用返回错误;对不可解析引用给出警告并回退
组件B:模型目录与发现(model-catalog + pi-model-discovery)
- 关键职责
- 通过 PI SDK 动态导入模型注册表,加载模型目录
- 合并配置化提供者模型(非 PI 原生提供者)
- 应用合成回退:当目录缺失时,基于模板 ID 推导
- 提供能力查询:图像/文档输入、推理能力、上下文窗口
- 缓存与容错
- 目录加载结果缓存,失败不污染缓存,避免安装过程临时失败导致的持续失败
- 依赖关系
- 依赖认证存储与模型注册表类
- 依赖配置以决定是否合并配置化模型
组件C:配置合并与计划(models-config.merge + models-config.plan)
- 关键职责
- 合并隐式与显式提供者配置,优先显式,保留隐式模型字段(如上下文窗口、推理标记)
- 保留现有密钥与基础 URL,避免覆盖由 secret-ref 管理的凭据
- 生成 models.json 写入计划(跳过/无操作/写入)
- 复杂度
- 合并提供者:O(P)(P 为提供者数量)
- 保留策略:O(P)(逐提供者检查)
组件D:列表与可用性(list.rows + list.registry)
- 关键职责
- 加载模型注册表与可用模型集合
- 构建模型行:标签、别名、可用性、本地标识
- 可用性优先使用模型级 getAvailable(),否则回退到提供者级认证启发式
- 过滤与排序
- 支持按提供者与本地过滤,按提供者与 ID 排序
组件E:会话与覆盖(sessions-patch)
- 关键职责
- 会话 patch 中的 model 字段支持 null(重置为默认)、未提供(保持不变)、字符串(解析为允许模型)
- 解析允许模型引用,若目录不可用则返回 UNAVAILABLE 错误
- 将解析结果应用到会话条目,并标记是否为默认模型
组件F:媒体理解模型筛选(media-understanding/resolve)
- 关键职责
- 合并能力配置与共享模型配置
- 若共享模型未声明能力,则尝试从提供者注册表解析能力
- 仅保留具备指定能力的模型条目
组件G:故障转移与错误恢复(failover-error)
- 关键职责
- 将通用错误归类为故障转移原因(超时、配额、鉴权、格式、模型不存在等)
- 提供错误描述与状态码映射
- 将错误转换为 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 与认证存储文件
性能考量
- 目录加载缓存:避免重复动态导入与文件系统访问
- 合并策略:优先显式配置,减少回退路径
- 可用性探测:优先模型级可用性,必要时回退至认证启发式
- 基准测试:多轮运行取中位数,降低异常波动影响
- 监控指标:吞吐、错误率、缓存命中率、平均时延,辅助定位瓶颈
认证与权限管理
认证与权限管理相关代码主要分布在以下模块:
- 认证档案与存储: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
类型定义"] 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)、构建配置变更计划、生成严格用户提供的凭证矩阵,确保只纳入不可运行时生成或轮换的凭证。
架构总览
认证系统围绕"认证档案存储"和"凭证解析/刷新"两条主线展开,并通过"健康检查"和"配置计划"实现可观测性与可维护性。
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),避免明文泄露。
- 文件锁保护:所有写操作使用文件锁,重试策略避免并发冲突。
组件B:OAuth 解析、刷新与故障转移
- 模式兼容:允许 token 与 oauth 在某些场景互换(Bearer 场景)。
- 解析流程:先检查本地有效期,未过期直接返回;过期则加锁刷新。
- 提供商专用刷新:针对 chutes、qwen-portal 等提供专用刷新逻辑;通用提供商通过统一接口刷新。
- 故障转移:
- 若刷新失败且存在较新的主代理凭证,则采用主代理凭证;
- 尝试备用档案(基于默认档案修复建议);
- 若仍失败,尝试从主代理复制新鲜凭证到当前代理;
- 特定提供商(如 openai-codex)在特定错误条件下使用缓存的 access token 作为回退;
- 最终抛出带诊断提示的错误信息。
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 字段有效性与是否过期。
并检查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 小时),并提供短格式剩余时间展示。
组件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 解析与凭证矩阵,确保变更可控与可审计。
性能考量
- 文件锁与重试:写操作采用指数回退与最大超时,降低并发写入冲突概率。
- 运行时快照:支持多代理运行时快照合并,减少重复 IO。
- 健康检查:按提供商聚合状态,避免对每个档案单独检查带来的开销。
- 轮换策略:仅在速率限制错误时切换密钥,避免不必要的网络往返。
沙箱与安全机制
围绕"沙箱与安全"的关键模块分布于 agents/sandbox 及其子模块,配合配置校验、路径与媒体处理、工具策略与文件系统策略等模块协同工作,形成从配置到运行时的完整安全闭环。
安全校验与拒绝列表"] 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:// 处理、临时媒体目录白名单。
- 工具策略与文件系统策略:允许/拒绝工具集合的合并与生效;工具仅限工作区访问的策略解析。
架构总览
下图展示沙箱创建与安全校验在运行时的关键交互流程。
详细组件分析
安全校验与拒绝列表
- 目标:阻止危险的 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:阻断禁用配置。
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 规范化。
- 解析:通过现有祖先解析,即使最终叶子不存在也能正确识别真实父链,防止符号链接逃逸。
常量与默认值
- 默认镜像、容器前缀、工作目录、空闲/最大存活时间。
- 默认工具允许/拒绝清单(如 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。
- 注册表更新与热容器窗口提示。
沙箱路径管理
- 输入路径解析:支持
、/ 前缀展开、相对路径转绝对、Unicode 空格规范化。 - 边界检查:assertSandboxPath 确保相对路径不逃逸沙箱根,使用路径别名守卫避免符号/硬链接逃逸。
- 媒体路径处理:
- 不支持 data: URL;file:// URL 与 http:// URL 分别处理。
- 将容器内 /workspace 映射回宿主机工作区或临时媒体目录(受控白名单)。
- 临时媒体目录必须位于 OpenClaw 临时目录内且不逃逸。
工具策略与文件系统策略
- 工具策略:
- 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:临时目录解析
性能考量
- 路径解析与边界检查为纯字符串与少量文件系统 I/O,开销较低。
- 安全校验在创建前集中执行,避免运行期反复校验。
- 通过只读根文件系统、tmpfs、ulimit、CPU/内存限制降低容器资源占用风险。
- 热容器窗口(最近使用)提示减少频繁重建带来的开销。
AI 代理系统
OpenClaw 采用"网关控制平面 + 多通道接入 + 代理运行时"的分层架构:
- 网关(Gateway)作为统一控制平面,承载会话、路由、事件与工具调用编排;
- 代理运行时以 Pi 代理为核心,支持嵌入式运行、工具流式与块流式输出;
- 通过插件化渠道适配器连接 WhatsApp、Telegram、Discord、iMessage 等消息平台;
- 提供 CLI、Web 控制台与移动端节点,形成完整的本地优先、自托管智能体生态。
核心组件
- 代理运行时与生命周期
- 嵌入式 Pi 代理运行器负责执行推理、工具调度、流式输出与运行状态管理。
- 关键导出包括运行控制(启动/队列/中止/等待结束)、历史限制与会话车道解析、沙箱信息构建、系统提示覆盖与工具拆分等。
- 消息与工具
- 统一的消息工具识别与发送判定逻辑,支持核心消息工具与各渠道插件的动作提取。
- 块级回复载荷结构用于组织文本、媒体、语音与回执标记。
- 认证与凭据
- 将认证档案转换为 Pi 代理可用的 API Key 或 OAuth 凭据映射,并进行相等性比较。
- 辅助与错误分类
- 错误分类与降级策略、图像与转录内容清洗、Turn 序列校验、思维层级降级等。
- 运行时环境
- 标准 I/O 输出与退出行为封装,便于测试与非退出模式使用。
架构总览
下图展示从消息入口到代理执行、工具调用与响应返回的端到端流程,强调会话与上下文在代理运行时中的作用。
详细组件分析
代理运行时与生命周期
- 运行器职责
- 启动/排队/中止/等待嵌入式 Pi 代理运行,维护运行元数据与结果。
- 历史回合限制与会话车道解析,确保上下文规模可控与并发会话隔离。
- 沙箱信息构建与系统提示覆盖,满足不同场景下的安全与提示一致性。
- 工具拆分与额外参数应用,提升跨模型兼容性与运行稳定性。
- 生命周期管理
- 通过运行状态查询与等待结束,实现对长尾任务的可观测与可中断。
- 结合会话修剪与紧凑化策略,降低上下文开销并维持长期对话质量。
解析历史限制/车道"] Load --> Plan["生成工具调用计划"] Plan --> Stream{"是否需要流式输出?"} Stream --> |是| Chunk["块流式/工具流式输出"] Stream --> |否| Final["生成最终回复"] Chunk --> Monitor["监控运行状态/队列"] Final --> Monitor Monitor --> Done(["结束/等待下一轮"])
会话管理与上下文保持
- 会话键与历史限制
- 支持基于会话键的历史回合裁剪,兼顾 DM 与群组场景的差异化上限。
- 上下文紧凑化
- 提供紧凑化能力以减少上下文长度,缓解超限风险并保持语义连贯。
- 会话车道
- 会话车道解析用于区分不同运行路径或优先级,保障资源分配与隔离。
工具流式传输与块流式处理
- 工具与消息工具识别
- 统一识别核心消息工具与各渠道插件的动作,确保发送类工具被正确提取与执行。
- 块级回复载荷
- 文本、媒体 URL、音频转语音、推理标记、回执标识与回复目标等字段构成块级输出的基础结构。
- 流式输出
- 在工具执行与模型生成过程中,按块推送中间结果,提升交互体验与可观测性。
代理配置、模型选择与认证轮换
- 模型选择
- 通过标准化的提供方 ID 归一化与凭据映射,支持多提供商与多模型的灵活切换。
- 认证轮换
- 将认证档案转换为 API Key 或 OAuth 凭据,自动处理过期与刷新条件,保证连续可用性。
- 故障转移策略
- 错误分类与降级策略(如速率限制、计费错误、上下文溢出、超时等),结合备用凭据与备用模型实现自动切换。
代理沙箱机制、安全隔离与权限控制
- 沙箱模式
- 非主会话(群组/频道)默认启用容器化沙箱,限制工具集与文件系统访问,仅允许必要工具(如会话列表/历史/发送等)。
- 权限控制
- macOS 节点通过网关协议暴露能力与权限映射,本地动作需遵循 TCC 状态;可按会话启用/禁用"提升权限"模式并持久化。
- 安全建议
- 默认仅主会话拥有主机执行权限;群组/频道会话置于沙箱内运行,避免越权操作。
代理生命周期管理、状态持久化与性能优化
- 生命周期
- 运行器提供运行状态查询、队列注入、中止与结束等待,便于长任务与并发场景的精细化控制。
- 状态持久化
- macOS 场景下,会话的思考级别、详细程度、模型、发送策略与群组激活等可通过会话补丁持久化。
- 性能优化
- 历史回合裁剪、上下文紧凑化、Turn 序列校验与图像/转录内容清洗,降低计算与存储压力。
- 思维层级降级与工具拆分提升跨模型兼容性与稳定性。
多代理路由、会话隔离与资源管理
- 多代理路由
- 支持按发送者、工作区与代理维度进行会话隔离与路由,实现多代理协作与资源隔离。
- 会话隔离
- 不同会话拥有独立上下文与工具执行边界,避免相互干扰。
- 资源管理
- 通过会话车道、历史限制与沙箱策略,平衡并发度与资源占用。
依赖关系分析
- 运行时 I/O
- 运行时封装了日志输出与进程退出,支持测试环境下的非退出模式,便于单元测试与集成测试。
- 代理运行器
- 导出运行控制、历史限制、车道解析、沙箱信息、系统提示覆盖、工具拆分与类型定义,形成代理执行的统一入口。
- 消息与工具
- 消息工具识别与发送判定依赖渠道插件的动作提取能力,形成"核心工具 + 插件动作"的扩展模型。
- 辅助与错误分类
- 错误分类与降级策略贯穿代理执行链路,配合凭据映射与 Turn 校验,提升鲁棒性。
性能考量
- 上下文规模控制
- 使用历史回合裁剪与上下文紧凑化,避免超限导致的失败与延迟。
- 流式输出
- 工具流式与块流式输出缩短首包延迟,改善用户体验。
- Turn 校验与内容清洗
- 对 Turn 序列与图像/媒体内容进行清洗与降级,减少无效负载与错误重试。
- 思维层级降级
- 在高负载或不稳定网络下自动降级思维层级,维持稳定响应。
Pi 嵌入式运行时
Pi 嵌入式运行时位于 src/agents 下,核心入口为 pi-embedded.ts,实际运行逻辑集中在 pi-embedded-runner 子目录;配套的订阅、工具、扩展、系统提示、历史限制、沙箱信息、会话缓存、压缩安全护栏与上下文修剪等模块共同构成完整的嵌入式运行时。
导出运行与状态查询接口"] --> 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 事件,结合系统提示、工具链、历史限制与扩展,完成一次完整的嵌入式运行周期。运行器还提供队列消息、等待运行结束、主动中断、会话压缩等运行期能力。
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 等事件,驱动流式输出与工具执行。
会话订阅与消息处理
- 订阅器职责
- 接收 AgentSession 事件,将流式文本与思考内容按块分发给 onBlockReply/onPartialReply;处理工具执行、回合与自动压缩事件。
- 块级流式分块
- EmbeddedBlockChunker 将连续流式片段聚合成块,剥离思考标签,提取最终内容与回复指令(媒体、语音、回复ID)。
- 消息发送追踪
- pi-embedded-messaging 记录通过消息工具发送成功的文本、媒体与目标,用于抑制确认文本与统计。
历史记录管理与上下文保持
- 历史限制
- 根据会话键与配置决定 DM 与群组的历史轮次限制,减少上下文开销。
- 历史清洗与配对修复
- 在截断后重新修复 tool_use 与 tool_result 的配对关系,保证上下文一致性。
- 上下文引擎
- context-engine/types 定义上下文组装、压缩与引导结果的数据结构,支撑运行期上下文度量与报告。
嵌入式工具定义与消息提供者策略
- 工具拆分策略
- splitSdkTools 将所有工具放入 customTools,确保 OpenClaw 的策略过滤、沙箱集成与扩展工具集一致。
- 工具定义适配
- 将 AgentTool 的 execute 签名适配为 ToolDefinition,保证与 pi-coding-agent 的调用约定一致。
- 消息提供者策略
- 根据通道能力与配置,注入 inlineButtons、反应指导、消息动作提示等,影响系统提示与行为。
模型兼容性与提供商特定处理
- 模型解析与鉴权
- resolveModel 通过 ModelRegistry 与 AuthStorage 获取模型与密钥;针对 GitHub Copilot 等特殊场景进行令牌转换。
- 提供商特定处理
- Google/Gemini:turn ordering 修复、工具 schema 清理、历史清洗;Anthropic:拒绝文本清理、回合校验;OpenAI:apply_patch 工具与思考级别降级。
- 流式参数与 Ollama
- extra-params 提供提供商特定流式参数;Ollama 通过自定义流函数注册,确保本地模型兼容。
嵌入式运行时配置与运行期能力
- 运行期状态查询
- isEmbeddedPiRunActive/isEmbeddedPiRunStreaming 查询运行状态;queueEmbeddedPiMessage 向正在流式的运行追加消息;waitForEmbeddedPiRunEnd 等待运行结束。
- 会话与命令通道
- resolveEmbeddedSessionLane/全局 lanes 控制并发与优先级,避免死锁。
- 压缩与安全护栏
- compactEmbeddedPiSessionDirect 执行手动/自动压缩;compaction-safety-timeout 保护压缩过程;compaction-safeguard 与 context-pruning 扩展提供额外保障。
助手身份、历史与上下文保持
- 助手身份
- UI 层提供默认名称与头像,normalizeAssistantIdentity 统一输入,确保跨渠道一致性。
- 历史与上下文
- 通过历史限制、转录策略与上下文引擎,维持合理的上下文窗口与历史长度,避免溢出。
节点订阅与网关集成
- 节点订阅管理
- server-node-subscriptions 提供节点到会话的订阅映射,支持向指定会话广播事件;gateway-misc.test 展示事件路由与取消订阅行为。
- 会话事件分发
- 通过 sendToSession/sendToAllSubscribed 将运行期事件推送到已订阅节点,便于网关侧统一消费。
开发指南、自定义实现与调试技巧
- 开发指南
- 使用 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 的工具、系统提示、历史限制、扩展与会话管理形成闭环。
性能考量
- 会话缓存与预热
- session-manager-cache 预热会话文件,减少重复解析成本;session-manager-init 确保会话头存在。
- 历史限制与上下文修剪
- history 限制 DM 与群组历史轮次;context-pruning 基于缓存 TTL 实现上下文修剪,降低上下文窗口压力。
- 压缩安全护栏
- compaction-safety-timeout 限制压缩耗时;compaction-safeguard 与 context-pruning 扩展在压缩过程中提供额外保护。
- 工具与沙箱
- splitSdkTools 将工具全部进入 customTools,便于统一策略与沙箱控制,减少不必要的内置工具开销。