跳转至

提供者钩子和目录

三个提供者层、完整的钩子顺序表、一个可运行的提供者示例、内置钩子形状,以及提供者目录如何合并。本文是插件架构内部机制指南的一部分。

提供者运行时钩子

提供者插件包含三个层:

  • 清单元数据,用于低成本的预运行时查找: setup.providers[].envVars、providerAuthAliases、providerAuthChoices 和 channelConfigs。
  • 配置时钩子:catalog 加上 applyConfigDefaults。
  • 运行时钩子:40 多个可选钩子,涵盖认证、模型解析、流包装、 思考层级、重放策略和用量端点。参见 钩子顺序与用法。

OpenClaw 仍然负责通用代理循环、故障转移、转录处理和工具策略。这些钩子是提供者特定行为的扩展面,无需一整套自定义推理传输。

钩子查找首先使用已准备的生成结果或匹配的已加载注册表。 若未命中,提供者/模型作用域的发现会复用加载器的注册表缓存; 显式的运行时发现失效会清除该查找结果,而不会让另一个提供者缓存保留旧钩子。 为尝试而准备的提供者句柄会保留其选中的插件,而每个钩子都会接收当前的调用上下文。

合成认证查找包含来自声明提供者或 CLI 后端拥有者的仅认证发现条目。静态模型目录行不会替换这些认证实现。如果拥有者未提供合成认证钩子,查找将返回无合成结果,且不会加载无关的发现条目。对于没有声明拥有者的别名,仍然提供轻量级条目回退。外部认证捕获在只读 worker 工作之前仍会准备全新的结果。

当提供者拥有基于环境变量的凭据,且通用认证/状态/模型选择器路径无需加载插件运行时即可看到这些凭据时,请使用清单中的 setup.providers[].envVars。当一个提供者 ID 应复用另一个提供者 ID 的环境变量、认证配置文件、配置支持的认证以及 API 密钥接入选择时,请使用清单中的 providerAuthAliases。当接入/认证选择 CLI 界面需要知道提供者的选择 ID、组标签和简单的单标志认证接线,而无需加载提供者运行时,请使用清单中的 providerAuthChoices。将提供者运行时 envVars 保留用于面向操作者的提示,例如接入标签或 OAuth client-id/client-secret 设置变量。

通过所属的 channelConfigs.<id>.schema 和设置描述符来描述由环境变量驱动的渠道设置与认证。

钩子顺序与用法

对于模型/提供者插件,OpenClaw 大致按以下顺序调用钩子。“何时使用”列是快速决策指南。OpenClaw 不再调用的仅用于兼容性的提供者字段(例如 ProviderPlugin.capabilities 和 suppressBuiltInModel)特意未在此列出。

钩子 作用 何时使用
catalog 在 models.json 生成期间将提供者配置发布到 models.providers 提供者拥有目录或 base URL 默认值
applyConfigDefaults 在配置物化期间应用提供者拥有的全局配置默认值 默认值取决于认证模式、环境或提供者模型族语义
(内置模型查找) OpenClaw 首先尝试常规注册表/目录路径 (非插件钩子)
normalizeModelId 在查找前规范化遗留的或预览版 model-id 别名 提供者在规范模型解析前负责别名清理
normalizeTransport 在通用模型组装前规范化提供者族的 api / baseUrl 提供者负责同一传输族中自定义提供者 ID 的传输清理
normalizeConfig 在运行时/提供者解析前规范化 models.providers.<id> 提供者需要应由所属插件承载的配置清理
applyNativeStreamingUsageCompat 对配置提供者应用原生流式用量兼容性重写 提供者需要端点驱动的原生流式用量元数据修复
resolveConfigApiKey 在运行时认证加载前为配置提供者解析环境变量标记认证 提供者暴露自己的环境变量标记 API 密钥解析钩子
resolveSyntheticAuth 在不持久化明文的情况下呈现本地/自托管或配置支持的认证 提供者可以使用合成/本地凭据标记运行
钩子 作用 使用时机
resolveExternalAuthProfiles 叠加由提供方拥有的外部认证配置文件;对于 CLI/应用拥有的凭据,默认 persistence 为 runtime-only 提供方复用外部认证凭据,而不持久化复制的刷新令牌;在清单中声明 contracts.externalAuthProviders
shouldDeferSyntheticProfileAuth 将已存储的合成配置文件占位符置于基于环境变量/配置的认证之后 提供方存储不应获得优先级的合成占位配置文件
resolveDynamicModel 为尚未存在于本地注册表中的提供方拥有的模型 ID 提供同步回退 提供方接受任意上游模型 ID
prepareDynamicModel 返回异步准备好的模型,或在重试 resolveDynamicModel 之前预热可复用元数据 提供方在解析未知 ID 前需要网络元数据
normalizeResolvedModel 在嵌入式运行器使用已解析模型之前的最终重写 提供方需要传输层重写,但仍使用核心传输层
normalizeToolSchemas 在嵌入式运行器看到工具架构之前对其进行规范化 提供方需要传输族架构清理
inspectToolSchemas 在规范化后显示提供方拥有的架构诊断信息 提供方希望获得关键字警告,而无需向核心教授提供方特定规则
resolveReasoningOutputMode 选择原生与带标记的推理输出契约 提供方需要带标记的推理/最终输出,而不是原生字段
prepareExtraParams 在通用流选项包装器之前对请求参数进行规范化 提供方需要默认请求参数或按提供方清理参数
createStreamFn 使用自定义传输层完全替换常规流路径 提供方需要自定义线路协议,而不仅仅是包装器
wrapStreamFn 在应用通用包装器之后的流包装器 提供方需要请求头/正文/模型兼容包装器,而不需要自定义传输层
reconcileLocalService 在本地服务健康检查之后、每次请求之前协调提供方拥有的状态 受管理的本地路由器必须重新加载持久提供方状态,而无需将提供方策略移入核心
resolveTransportTurnState 附加原生的每轮次请求头、元数据或 WebSocket 策略 提供方希望通用传输层发送提供方原生的轮次标识,或调整 WebSocket 请求头和回退冷却时间
resolveWebSocketSessionPolicy 用于 WebSocket 策略的已弃用兼容钩子 现有插件将 WebSocket 字段迁移到 resolveTransportTurnState
formatApiKey 认证配置文件格式化器:已存储的配置文件成为运行时 apiKey 字符串 提供方存储额外认证元数据,并需要自定义运行时令牌格式
refreshOAuth 用于自定义刷新端点或刷新失败策略的 OAuth 刷新覆盖 提供方不适合共享的 OpenClaw 刷新器
buildAuthDoctorHint 在 OAuth 刷新失败时附加的修复提示 提供方在刷新失败后需要提供方拥有的认证修复指导
matchesContextOverflowError 提供方拥有的上下文窗口溢出匹配器 提供方存在通用启发式方法会遗漏的原始溢出错误
classifyFailoverReason 提供方拥有的故障转移原因分类 提供方可以将原始 API/传输错误映射为速率限制/过载等
钩子 作用 使用时机
isCacheTtlEligible 代理/回传提供商的 Prompt 缓存策略 提供商需要代理特定的缓存 TTL 门控
buildMissingAuthMessage 通用缺失认证恢复消息的替代 提供商需要提供商特定的缺失认证恢复提示
augmentModelCatalog 发现后追加的合成/最终目录行(已弃用,见下文) 提供商需要在 models list 和选择器中提供合成前向兼容行
resolveThinkingProfile 模型特定的 /think 级别集、显示标签和默认值 提供商为所选模型暴露自定义思考阶梯或二元标签
isBinaryThinking 开/关推理切换兼容性钩子 提供商仅暴露二元思考开/关
supportsXHighThinking xhigh 推理支持兼容性钩子 提供商希望仅在部分模型上启用 xhigh
resolveDefaultThinkingLevel 默认 /think 级别兼容性钩子 提供商拥有某个模型族的默认 /think 策略
isModernModelRef 用于实时配置过滤和冒烟选择的现代模型匹配器 提供商拥有实时/冒烟首选模型匹配
prepareRuntimeAuth 在推理前将已配置的凭据交换为实际的运行时 Token/密钥 提供商需要 Token 交换或短期请求凭据
resolveUsageAuth 解析 /usage 及相关状态界面的用量/计费凭据 提供商需要自定义用量/配额 Token 解析或不同的用量凭据
fetchUsageSnapshot 在认证解析后获取并规范化提供商特定的用量/配额快照 提供商需要提供商特定的用量端点或负载解析器
createEmbeddingProvider 为记忆/搜索构建提供商拥有的嵌入适配器 记忆嵌入行为属于提供商插件
buildReplayPolicy 返回控制提供商转录处理的回放策略 提供商需要自定义转录策略(例如,剥离思考块)
sanitizeReplayHistory 在通用转录清理后重写回放历史 提供商需要超出共享压缩辅助的提供商特定回放重写
validateReplayTurns 嵌入式运行器之前的最终回放轮次验证或重塑 提供商传输需要在通用清理后进行更严格的轮次验证
onModelSelected 运行提供商拥有的选择后副作用 当模型变为活动时,提供商需要遥测或提供商拥有的状态

reconcileLocalService 仅针对已配置的本地服务运行,包括从当前 Gateway 进程外部复用的健康进程。保持其低成本、幂等且可感知中止。拒绝会阻止提供商请求并释放其租约,而不会将健康进程归类为启动失败。

规范化分发是钩子特定的:

  • 模型引用在 normalizeModelId 分发之前应用一次清单声明的模型 ID 规范化。匹配的提供商钩子可以细化该准备好的模型 ID;空结果会保持其不变。OpenClaw 不会尝试其他提供商的规范化钩子,也不会在之后重新应用清单规则。 引用解析读取所选运行时注册表,而不激活插件。可执行规范化需要一个准备好的运行时所有者;没有所有者的读取仅使用静态清单策略。 直接注册的提供商拥有其 ID;兼容别名仅在不存在字面提供商时匹配,从而保留仅别名路由和显式 API 所有者资格。
  • normalizeTransport 首先尝试匹配的提供商。只有当它未更改 api 或 baseUrl,并且提供商没有 models.providers.<id> 条目时,才会尝试其他传输钩子,并在第一次更改时停止。
  • normalizeConfig 首先使用拥有捆绑提供商的轻量级策略表面。如果该表面没有 normalizeConfig 钩子,OpenClaw 可以调用匹配的运行时所有者,前提是允许运行时加载,并且当提供配置时,该所有者具有显式插件激活。它从不扫描其他提供商的钩子,也不会在拥有钩子返回无更改后继续回退。 配置组装传递 allowRuntimePluginLoad: false,因此它在不加载提供商运行时的情况下使用捆绑策略。

Google 系列配置清理由 Google 插件自身的 normalizeConfig 钩子实现,并与它的轻量策略界面共享。它不是 独立的核心兼容性兜底。

如果提供商需要完全自定义的通信协议或自定义请求执行器, 那属于另一类扩展。这些钩子用于仍然运行在 OpenClaw 正常推理循环上的提供商行为。

resolveUsageAuth 决定 OpenClaw 应调用 fetchUsageSnapshot,还是 回退到用于用量/状态界面的通用凭据解析。当提供商 拥有用量凭据时返回 { token, accountId?, subscriptionType?, rateLimitTier? }(可选的计划元数据会流入 fetchUsageSnapshot);当由提供商拥有的用量鉴权已处理请求,并且 必须抑制通用 API 密钥/OAuth 回退时,返回 { handled: true };当提供商未处理用量鉴权时,返回 null 或 undefined。

在清单的 providerUsageAuthEnvVars 中声明组织或计费凭据。这可以让通用发现和密钥脱敏 界面识别它们,而不会将它们变成推理鉴权候选项。

提供商示例

example-proxy、exchangeToken 和 fetchExampleProxyUsage 是你自己的提供商 id 和供应商 API 调用的占位符, 而不是导出的 OpenClaw 辅助函数。

api.registerProvider({
  id: "example-proxy",
  label: "Example Proxy",
  auth: [],
  catalog: {
    order: "simple",
    run: async (ctx) => {
      const apiKey = ctx.resolveProviderApiKey("example-proxy").apiKey;
      if (!apiKey) {
        return null;
      }
      return {
        provider: {
          baseUrl: "https://proxy.example.com/v1",
          apiKey,
          api: "openai-completions",
          models: [{ id: "auto", name: "Auto" }],
        },
      };
    },
  },
  resolveDynamicModel: (ctx) => ({
    id: ctx.modelId,
    name: ctx.modelId,
    provider: "example-proxy",
    api: "openai-completions",
    baseUrl: "https://proxy.example.com/v1",
    reasoning: false,
    input: ["text"],
    cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
    contextWindow: 128000,
    maxTokens: 8192,
  }),
  prepareRuntimeAuth: async (ctx) => {
    const exchanged = await exchangeToken(ctx.apiKey);
    return {
      apiKey: exchanged.token,
      baseUrl: exchanged.baseUrl,
      expiresAt: exchanged.expiresAt,
    };
  },
  resolveUsageAuth: async (ctx) => {
    const auth = await ctx.resolveOAuthToken();
    return auth ? { token: auth.token } : null;
  },
  fetchUsageSnapshot: async (ctx) => {
    return await fetchExampleProxyUsage(ctx.token, ctx.timeoutMs, ctx.fetchFn);
  },
});

内置示例

内置提供商插件组合上述钩子,以适配各供应商的目录、 鉴权、思考、重放和用量需求。权威钩子集合位于每个插件的 extensions/ 下;本页说明其形态,而不是 照搬列表。

透传目录提供商

OpenRouter、Kilocode、Z.AI 和 xAI 注册 catalog 以及 resolveDynamicModel / prepareDynamicModel,以便在 OpenClaw 静态目录之前呈现上游 模型 id。

OAuth 和用量端点提供商

GitHub Copilot、Gemini CLI、ChatGPT Codex、MiniMax、Xiaomi 和 z.ai 将 prepareRuntimeAuth 或 formatApiKey 与 resolveUsageAuth + fetchUsageSnapshot 配对,以负责令牌交换和 /usage 集成。

重放和对话记录清理家族

共享命名家族(google-gemini、passthrough-gemini、 anthropic-by-model、hybrid-anthropic-openai)让提供商通过 buildReplayPolicy 选择加入 对话记录策略,而不是每个插件重新实现清理。

仅目录提供商

byteplus、cloudflare-ai-gateway、huggingface、kimi-coding、nvidia、 qianfan、synthetic、together、venice、vercel-ai-gateway 和 volcengine 仅注册 catalog,并运行在共享推理循环上。

Anthropic 专用流辅助函数

Beta 请求头、/fast / serviceTier 和 context1m 位于 Anthropic 插件公开的 api.ts / contract-api.ts 接缝 (wrapAnthropicProviderStream、resolveAnthropicBetas、 resolveAnthropicFastMode、resolveAnthropicServiceTier)中,而不是在 通用 SDK 中。

提供商目录

提供商插件可以使用 registerProvider({ catalog: { run(...) { ... } } }) 为推理定义模型目录。

catalog.run(...) 返回与 OpenClaw 写入 models.providers 的相同形状:

  • 一个提供商条目使用 { provider }
  • 多个提供商条目使用 { providers }

当插件拥有提供商特定的模型 id、基础 URL 默认值或受鉴权控制的模型元数据时,使用 catalog。

catalog.order 控制插件目录相对于 OpenClaw 内置隐式提供商的合并时机:

  • simple:普通 API 密钥或环境变量驱动的提供商
  • profile:当存在鉴权配置文件时出现的提供商
  • paired:合成多个相关提供商条目的提供商
  • late:最后处理,在其他隐式提供商之后

在键冲突时,较晚的提供商获胜,因此插件可以有意覆盖具有相同提供商 id 的内置提供商条目。

插件还可以通过 api.registerModelCatalogProvider({ provider, kinds, staticCatalog, liveCatalog }) 发布只读模型行。这是列表/帮助/选择器界面的前向路径,并支持 text、voice、image_generation、video_generation 和 music_generation 行。提供商插件仍负责实时端点调用、令牌交换和供应商响应映射;核心负责通用行形状、来源标签和媒体工具帮助格式化。媒体生成提供商注册会根据 defaultModel、models 和 capabilities 自动合成静态目录行。

兼容性:

  • discovery 曾是 catalog 的旧别名。OpenClaw 已在 2026.4.26 中移除该别名及其弃用警告
  • 将 discovery 重命名为 catalog。仍注册 discovery 的提供商插件不会发布任何目录行
  • augmentModelCatalog 已弃用;内置提供商应通过 registerModelCatalogProvider 发布补充行。其移除门槛为 2026-10-01

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw