OpenClaw 源码解析(十四):Provider 系统与模型能力接入机制
1. 本期目标
上一期我们分析了 OpenClaw 的 Plugins 插件系统。Plugin 解决的是“如何把外部能力接入 OpenClaw”的问题,其中一个非常重要的能力就是Model Provider。
这一期继续分析 OpenClaw 的 Provider 系统。
简单来说:
Tool 决定 Agent 能调用什么动作; Skill 决定 Agent 如何组织动作; Plugin 决定 OpenClaw 如何扩展能力; Provider 决定 OpenClaw 使用哪个模型、如何认证、如何请求、如何处理模型差异。OpenClaw 支持多个 LLM Provider,配置模型时使用provider/model形式,例如anthropic/claude-opus-4-6、google/gemini-3-flash-preview、lmstudio/my-local-model等。官方文档也明确说明,OpenClaw 可以使用多个 LLM providers,通常先完成 provider 认证,然后把默认模型设置为provider/model。(OpenClaw)
本期重点分析:
1. Provider、Model、Runtime、Plugin 的区别 2. provider/model 模型引用格式 3. 模型选择与默认模型配置 4. models.providers 如何注册自定义模型服务 5. Provider Plugin 如何接管 provider-specific logic 6. OpenAI-compatible、本地模型、CLI runtime 的区别 7. Tool calling 与 Provider 兼容性处理 8. 多模态能力、上下文窗口、token 限制如何描述 9. Model fallback 与 auth profile rotation 10. 一次 Agent 推理请求的完整 Provider 链路2. Provider 是什么?
可以先给一个直观定义:
Provider 是模型能力的供应方。它可以是:
OpenAI; Anthropic; Google Gemini; OpenRouter; Moonshot; DeepSeek; Qwen; Groq; Mistral; Ollama; LM Studio; vLLM; SGLang; LiteLLM; 某个 OpenAI-compatible 私有代理; 某个本地模型服务。Provider 的任务不是“生成 prompt”,而是解决模型调用相关的问题:
这个模型在哪里? 怎么认证? 请求发到哪个 baseUrl? 使用什么 API 协议? 模型支持文本还是图片? 上下文窗口多大? 最大输出多少 token? 是否支持 reasoning? 是否支持 tool calling? 失败后能不能 fallback?所以 Provider 可以理解为:
OpenClaw 与具体模型后端之间的适配层。3. Provider、Model、Runtime、Plugin 的区别
这几个概念很容易混淆。
Provider: 模型服务提供方,例如 anthropic、google、openai、lmstudio。 Model: Provider 下的具体模型,例如 claude-opus-4-6、gemini-3-flash-preview、my-local-model。 Runtime: 执行 Agent 推理循环的运行时,例如 OpenClaw 自己的 runtime、Codex harness、Claude CLI、Gemini CLI。 Plugin: 把 Provider、Runtime、Tool、Skill 等能力注册进 OpenClaw 的扩展机制。举个例子:
anthropic/claude-opus-4-6 anthropic 是 Provider; claude-opus-4-6 是 Model; 这个模型可以通过 OpenClaw runtime 调用,也可以在某些配置下通过 claude-cli runtime 调用; Anthropic provider 相关逻辑可以由 provider plugin 注册。再看一个 OpenAI 例子:
openai/gpt-5.5OpenClaw 文档中特别区分了 OpenAI provider 与 runtime:openai/<model>默认可以走 native Codex app-server harness;如果通过 provider/model runtime policy 显式选择agentRuntime.id: "openclaw",则使用 OpenClaw 内置 runtime 的 API-key 或兼容路由。(OpenClaw)
所以要记住:
Provider 解决“模型从哪里来”; Model 解决“具体用哪个模型”; Runtime 解决“用哪套推理执行链路”; Plugin 解决“这些能力如何接入 OpenClaw”。4. 为什么需要 Provider 系统?
如果 OpenClaw 只支持一个模型接口,那么 Agent 推理链路会很简单:
构造 messages ↓ 发送给固定 API ↓ 读取输出但现实中,不同模型服务差异很大:
认证方式不同; 请求协议不同; tool calling schema 支持不同; reasoning 字段不同; 图片输入格式不同; 流式输出格式不同; 错误码和限流信息不同; 上下文窗口不同; OAuth 和 API key 管理不同; 本地模型和云端模型延迟不同。Provider 系统的价值就是把这些差异收敛到统一入口:
OpenClaw core 保持通用推理循环; Provider plugin 处理具体模型服务差异。官方文档也说明,大多数 provider-specific logic 会放在 provider plugins 中,例如 onboarding、model catalog、auth env-var mapping、transport/config normalization、tool-schema cleanup、failover classification、OAuth refresh、usage reporting、thinking/reasoning profiles 等;OpenClaw core 保留 generic inference loop。(OpenClaw)
这说明 OpenClaw 的设计思路是:
不要把所有 Provider 特殊逻辑堆进 core; 而是让 Provider Plugin 接管这些差异。5.provider/model:模型引用格式
OpenClaw 使用统一的模型引用格式:
provider/model例如:
anthropic/claude-opus-4-6 google/gemini-3-flash-preview openai/gpt-5.5 openrouter/deepseek/deepseek-chat lmstudio/my-local-model local/my-local-model官方文档把这作为 Quick rules 的第一条:model refs 使用provider/model;同时agents.defaults.models在设置后会作为 allowlist,CLI 可通过openclaw onboard、openclaw models list、openclaw models set <provider/model>管理模型。(OpenClaw)
这套格式的好处是:
第一,模型引用不会和其他 Provider 的同名模型冲突。 第二,配置、切换、fallback、allowlist 都可以用统一字符串表达。 第三,Provider 逻辑可以根据 provider 前缀路由。例如:
qwen-max这个名字单独出现时不够明确,因为它可能来自 Qwen 官方、OpenRouter、LiteLLM 代理或私有兼容接口。
而:
qwen/qwen-max openrouter/qwen/qwen-max local/qwen-max就能明确说明请求应该走哪个 Provider。
6. 默认模型配置
OpenClaw 的默认模型通常配置在:
agents.defaults.model.primary例如:
{ "agents": { "defaults": { "model": { "primary": "anthropic/claude-opus-4-6" } } } }如果希望提供 fallback,可以写成:
{ "agents": { "defaults": { "model": { "primary": "anthropic/claude-opus-4-6", "fallbacks": [ "google/gemini-3-flash-preview", "openai/gpt-5.5" ] } } } }官方 Models CLI 文档列出的相关配置键包括agents.defaults.model.primary、agents.defaults.model.fallbacks、agents.defaults.imageModel.primary、agents.defaults.pdfModel.primary、agents.defaults.imageGenerationModel.primary、agents.defaults.videoGenerationModel.primary、agents.defaults.models和models.providers。(OpenClaw)
可以理解为:
primary: 默认首选模型。 fallbacks: 主模型失败后可尝试的备用模型。 imageModel / pdfModel: 图片理解、PDF 理解等专用模型。 imageGenerationModel / videoGenerationModel: 媒体生成任务使用的模型。 agents.defaults.models: 模型可见性、别名和 allowlist。 models.providers: 自定义 provider 和模型目录。7.agents.defaults.models:模型 allowlist 与 alias
agents.defaults.models很容易被误解。
它不是“注册 Provider”的地方,而是更偏向:
允许哪些模型出现; 给模型设置 alias; 给 provider/model 设置额外元数据; 限制用户在 /model 中能选什么。官方文档说明,如果设置了agents.defaults.models,它会成为/model和 session overrides 的 allowlist;当用户选择不在 allowlist 中的模型时,OpenClaw 会提示 model is not allowed,并要求加入 allowlist、清除 allowlist 或从/model list选择。(OpenClaw)
示例:
{ "agents": { "defaults": { "model": { "primary": "anthropic/claude-opus-4-6" }, "models": { "anthropic/claude-opus-4-6": { "alias": "Opus" }, "google/gemini-3-flash-preview": { "alias": "Gemini Flash" } } } } }如果想允许某个 Provider 下的全部模型,可以使用:
{ "agents": { "defaults": { "models": { "openai/*": {}, "vllm/*": {} } } } }官方文档也说明,可以添加provider/*entries,让/model、/models和 model pickers 只展示这些 Provider 的发现模型;这适合希望限制 Provider 但不想手动列出所有模型的场景。(OpenClaw)
8.models.providers:注册自定义 Provider
如果要接入自定义模型服务,就要看:
models.providers它用于添加:
OpenAI-compatible proxy; Anthropic-compatible proxy; Google-compatible endpoint; 本地 LM Studio; vLLM; SGLang; LiteLLM; 企业内部模型网关; 自己写的模型代理服务。官方文档说明,可以通过models.providers或models.json添加自定义 Provider 或 OpenAI/Anthropic-compatible proxies;如果 bundled provider plugin 已经发布默认 catalog,只有在需要覆盖 base URL、headers 或 model list 时才需要显式写models.providers.<id>。(OpenClaw)
一个典型配置如下:
{ "models": { "mode": "merge", "providers": { "custom-proxy": { "baseUrl": "http://localhost:4000/v1", "apiKey": "LITELLM_KEY", "api": "openai-completions", "models": [ { "id": "llama-3.1-8b", "name": "Llama 3.1 8B", "reasoning": false, "input": ["text"], "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }, "contextWindow": 128000, "contextTokens": 96000, "maxTokens": 32000 } ] } } } }这里要注意:
models.providers.<id>.models[].id 是 Provider 内部模型 ID; 真正引用时才写 provider/model。例如:
models.providers.local.models[].id = "my-local-model" agents.defaults.model.primary = "local/my-local-model"本地模型文档也强调,models.providers.<id>.models[].id是 provider-local 值,不要在这里包含 provider 前缀。(OpenClaw)
9. Provider 配置字段
一个 Provider 配置通常包含这些字段:
baseUrl: 模型服务地址。 apiKey: 认证凭据。 api: 请求协议适配器。 models: 该 Provider 下的模型目录。 headers: 额外请求头。 auth: 认证策略。 contextWindow: 默认上下文窗口。 contextTokens: 运行时有效上下文上限。 maxTokens: 最大输出 token。 timeoutSeconds: 模型请求超时时间。OpenClaw 的配置文档列出了这些字段:models.providers.*.api可选openai-completions、openai-responses、anthropic-messages、google-generative-ai等;apiKey是 Provider credential;baseUrl是 upstream API base URL;headers可用于 proxy 或 tenant routing;timeoutSeconds用于控制模型 HTTP 请求超时。(OpenClaw)
其中最重要的是:
api: 决定如何构造请求和解析响应。 baseUrl: 决定请求发往哪里。 models: 决定该 Provider 具体有哪些模型。比如一个本地 vLLM 服务通常使用:
{ "api": "openai-completions", "baseUrl": "http://127.0.0.1:8000/v1" }如果后端明确支持 Responses API,则可以使用:
{ "api": "openai-responses" }本地模型文档也说明,MLX、vLLM、SGLang、LiteLLM、OAI-proxy 或自定义网关,只要暴露 OpenAI-style/v1/chat/completionsendpoint,就可以使用 Chat Completions adapter;只有后端明确支持/v1/responses时才使用 Responses API。(OpenClaw)
10.models.mode: merge 与 replace
models.mode决定 OpenClaw 如何处理配置中的 Provider catalog。
merge: 默认模式,把配置里的 Provider 与内置 catalog 合并。 replace: 替换模式,只使用显式配置的 Provider / Model。官方文档说明,自定义 providers 会写入 agent 目录下的models.json,默认以 merge 模式合并,除非设置models.mode为replace。(OpenClaw)
一般建议:
日常使用: 用 merge。 企业内网严格控制模型来源: 可以考虑 replace。 本地模型加云端 fallback: 用 merge。 完全离线环境: 可以用 replace。例如,本地优先但保留云端 fallback:
{ "agents": { "defaults": { "model": { "primary": "lmstudio/my-local-model", "fallbacks": ["anthropic/claude-opus-4-6"] } } }, "models": { "mode": "merge", "providers": { "lmstudio": { "baseUrl": "http://127.0.0.1:1234/v1", "apiKey": "lmstudio", "api": "openai-responses", "models": [ { "id": "my-local-model", "name": "Local Model", "reasoning": false, "input": ["text"], "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }, "contextWindow": 196608, "maxTokens": 8192 } ] } } } }官方本地模型文档也建议,即使运行本地模型,也保留 hosted models 配置并使用models.mode: "merge",这样 fallback 仍然可用。(OpenClaw)
11. 本地模型 Provider
OpenClaw 对本地模型的支持可以分成几类:
LM Studio; Ollama; vLLM; SGLang; MLX; LiteLLM; 自定义 OpenAI-compatible server。以 LM Studio 为例,官方文档推荐启动本地 server,默认地址通常是:
http://127.0.0.1:1234/v1然后在models.providers中配置lmstudioProvider。文档也给出建议:加载较大的本地模型、启动本地 server、确认/v1/models能列出模型、把实际 model ID 写入配置,并保持模型已加载以减少冷启动延迟。(OpenClaw)
本地模型的优势是:
数据不离开本机; 推理成本可控; 适合隐私敏感场景; 适合离线或内网环境; 可以和云端模型做 fallback。但本地模型也有局限:
硬件要求高; 推理速度不稳定; tool calling 能力取决于模型和服务实现; 上下文窗口和多模态能力需要手动配置; 本地服务挂掉时需要 fallback 或显式报错。所以本地 Provider 更适合作为:
隐私优先场景的 primary; 低成本任务的 primary; 云端不可用时的 fallback; 开发调试环境。12. Provider Plugin 与registerProvider
上一期讲 Plugin 时,我们提到插件可以注册很多能力,其中就包括 Provider。
Provider Plugin 的核心是:
registerProvider(...)官方文档明确说明,Provider-specific logic 大多由 provider plugins 处理,OpenClaw 保留 generic inference loop。(OpenClaw)
源码类型中也可以看到 Provider 相关 hooks 非常多,例如 dynamic model resolution、transport normalization、runtime auth、usage snapshot、tool schema normalization、reasoning output mode、stream wrapper 等。这说明 Provider Plugin 不只是“声明一个 baseUrl”,而是可以参与请求前后的多个关键环节。(GitHub)
可以把 Provider Plugin 能力理解为:
模型目录: 告诉 OpenClaw Provider 下有哪些模型。 认证: 告诉 OpenClaw 使用哪些 env var、OAuth token、API key。 请求适配: 告诉 OpenClaw 如何构造请求。 响应适配: 告诉 OpenClaw 如何解析流式输出、usage、reasoning。 工具兼容: 告诉 OpenClaw 如何清理或改写 tool schema。 错误分类: 告诉 OpenClaw 哪些错误可以 fallback,哪些应该直接失败。 用量统计: 告诉 OpenClaw 如何查询 Provider usage 或 quota。13. Generic inference loop 与 Provider-specific logic
OpenClaw 的设计可以抽象成两层:
OpenClaw core: 负责通用 Agent 推理循环。 Provider plugin: 负责具体 Provider 差异。通用推理循环包括:
读取 session; 构造 messages; 注入 system prompt; 构造 tools; 调用模型; 处理 streaming; 处理 tool call; 写入 session state; 发送回复。Provider-specific logic 包括:
这个 Provider 怎么认证; 这个模型 ID 需不需要别名归一化; 这个请求要用 Chat Completions 还是 Responses; 这个模型是否支持 developer role; 这个 Provider 的 tool schema 哪些字段不兼容; 这个 Provider 的 rate limit 文本如何识别; 这个 Provider 的 reasoning 字段如何处理。可以画成:
Agent run ↓ OpenClaw core 构造通用请求上下文 ↓ Provider registry 解析 provider/model ↓ Provider plugin 处理认证、模型元数据、transport 兼容 ↓ Shared model runtime 发起请求 ↓ Provider plugin 处理流式输出、错误分类、usage ↓ OpenClaw core 继续工具调用或回复投递一句话概括:
OpenClaw core 管流程,Provider plugin 管差异。14. Tool calling 与 Provider 兼容
Tool calling 是 Provider 系统中非常关键的部分。
因为不同 Provider 对 function calling / tool calling 的支持并不完全一致:
有的支持 JSON Schema 的全部字段; 有的只支持简化 schema; 有的要求 tool call id 格式严格; 有的对 developer role 支持不好; 有的要求 messages.content 是字符串; 有的无法处理复杂嵌套参数; 有的 streaming tool call 格式与 OpenAI 不一致。OpenClaw 的 Provider 类型中有 provider-owned tool-schema normalization 相关上下文,注释说明它运行在 replay、compaction、inference 的工具注册前,允许 Provider 改写其 transport family 不支持的 schema keywords。(GitHub)
这说明:
Tool schema 不是原样发给所有模型; Provider 可以在请求前做兼容性清理。例如:
删除某些 Provider 不支持的 JSON Schema 关键字; 把复杂 schema 改写成更简单的形式; 对 tool call replay 做 provider-specific sanitation; 处理 reasoning model 对 tool call 的特殊要求。所以 Tool 系统和 Provider 系统是互相耦合的:
Tool 定义动作; Provider 决定这个动作 schema 如何传给模型; Model 决定能不能稳定地产生 tool call; Runtime 决定如何执行和回放 tool call。15. 多模态能力:input 字段
模型是否支持图片输入,不应该靠名字猜,而应该在 catalog metadata 中描述。
OpenClaw 配置文档说明,models.providers.*.models.*.input用于描述模型输入模态:文本模型使用["text"],原生图像/视觉模型使用["text", "image"];只有当选中的模型标记为 image-capable 时,图片附件才会注入到 agent turns 中。(OpenClaw)
例如:
{ "id": "vision-model", "name": "Vision Model", "input": ["text", "image"], "reasoning": false, "contextWindow": 128000, "maxTokens": 8192 }如果本地模型实际支持图片,但配置写成:
"input": ["text"]那么图片可能不会以原生视觉输入方式进入模型。
反过来,如果模型不支持图片却配置成:
"input": ["text", "image"]就可能导致请求失败。
所以多模态能力要靠 catalog metadata 显式表达。
16. 上下文窗口与运行时 token cap
Provider 配置中常见两个容易混淆的字段:
contextWindow contextTokens可以这样理解:
contextWindow: 模型原生支持的最大上下文窗口。 contextTokens: OpenClaw 运行时实际使用的上下文上限。官方配置文档说明,contextWindow是模型原生上下文窗口元数据,contextTokens是可选的运行时上下文 cap;当你希望有效上下文预算小于模型原生窗口时,可以设置contextTokens。(OpenClaw)
例如:
{ "id": "big-context-model", "contextWindow": 200000, "contextTokens": 80000, "maxTokens": 8192 }含义是:
模型理论上支持 200k 上下文; 但 OpenClaw 运行时只使用 80k; 最多输出 8192 tokens。这样做的原因可能是:
降低成本; 减少延迟; 避免超长上下文导致模型质量下降; 给工具输出和系统提示词保留余量; 兼容某些代理服务的实际限制。17. Auth:API Key、OAuth 与 Auth Profile
Provider 认证通常有几类:
API key; OAuth; 本地 CLI 登录状态; AWS SDK; 自定义 header; 代理服务 token。OpenClaw 的 model failover 文档说明,它使用 auth profiles 存储 API keys 和 OAuth tokens;secrets 位于 agent 目录下的auth-profiles.json,runtime auth-routing state 位于auth-state.json,而 config 中的auth.profiles/auth.order只是 metadata 和 routing,不保存 secret。(OpenClaw)
这说明 OpenClaw 把认证拆成两层:
配置层: 描述有哪些 profile、优先顺序是什么。 秘密层: 保存真实 API key 或 OAuth token。 运行状态层: 记录 cooldown、disabled、lastUsed 等状态。这对多账号、多 key 轮换很重要。
例如同一个 Provider 可以有多个 profile:
anthropic:default anthropic:backup-key google:user@gmail.com openai-codex:user@example.comOpenClaw 可以在限流或失败时尝试其他 profile。
18. Auth profile rotation
当一个 Provider 有多个 auth profile 时,OpenClaw 不一定每次都用同一个 key。
官方 failover 文档说明,Provider 有多个 profile 时,OpenClaw 会根据显式配置、配置 profiles、已存储 profiles 等来源确定顺序;如果没有显式 order,会使用一种 round-robin 排序,并考虑 OAuth/API key 类型、lastUsed、cooldown/disabled 等因素。(OpenClaw)
可以理解为:
优先使用配置指定的 profile; 没有配置时使用可用 profiles; 限流或失败的 profile 会进入 cooldown; disabled 的 profile 会被跳过; session 可能固定某个 profile 以保持缓存友好。这解决了一个实际问题:
同一个 Provider 下可能有多个账号或 key; 某个 key 触发限流时,不应该立刻让整个 Agent 失败; 可以先尝试其他 profile,再考虑模型 fallback。19. Model fallback
Provider 失败后,不一定马上失败给用户。
OpenClaw 的 fallback 分两层:
第一层:当前 Provider 内部的 auth profile rotation。 第二层:切换到 agents.defaults.model.fallbacks 中的下一个模型。官方文档明确说明,OpenClaw 处理失败分两阶段:先在当前 Provider 内做 auth profile rotation;如果当前 Provider 因 failover-worthy error 被耗尽,再移动到agents.defaults.model.fallbacks中的下一个模型。(OpenClaw)
可以画成:
primary model 请求失败 ↓ 判断错误类型 ↓ 如果是 rate limit / auth / timeout 等可 fallback 错误 ↓ 尝试同 Provider 的其他 auth profile ↓ 当前 Provider 耗尽 ↓ 尝试 fallbacks 中的下一个 provider/model ↓ 成功则继续回复 ↓ 失败则继续 fallback 或报错这里要注意:
不是所有错误都应该 fallback。比如:
上下文过长; 请求格式明显错误; 用户手动指定的 strict model 不可用; 工具 schema 永久不兼容。这些情况可能更适合直接暴露错误,而不是悄悄换模型。
20. Session model switching:/model
用户也可以在会话中切换模型。
常见命令:
/model /model list /model 3 /model openai/gpt-5.5 /model status官方文档说明,/model可以在当前 session 中切换模型;如果 Agent 空闲,下一次 run 会立刻使用新模型;如果 run 已经激活,OpenClaw 会把 live switch 标记为 pending,并在干净的 retry point 切换。文档还强调,用户通过/model选择的模型对当前 session 是 strict 的,如果不可达,会显式失败,而不是静默使用默认 fallback。(OpenClaw)
这点很关键:
配置里的 primary 可以 fallback; 用户手动指定的 session model 更偏严格选择。原因也很合理:
用户主动说“我要用这个模型”; 系统不应该悄悄换成另一个模型还假装成功。21. 一次模型调用的完整链路
我们把 Provider 系统放进 Agent run 里看,一次完整链路大致是:
用户消息进入 Channel ↓ Session 创建或恢复 ↓ 确定当前 Agent ↓ 读取 session model override ↓ 如果没有 override,读取 agents.defaults.model.primary ↓ 构造 fallback candidate chain ↓ 解析 provider/model ↓ 从 model registry 找 Provider 和 model metadata ↓ 加载 Provider config 和 auth profile ↓ 构造 system prompt、messages、tools ↓ Provider plugin 处理 tool schema / transport / auth / reasoning 兼容 ↓ 调用 shared model runtime 或 provider-specific runtime ↓ 接收 streaming 输出 ↓ 如果模型产生 tool call,进入 Tool pipeline ↓ 如果模型产生 final response,进入回复投递 ↓ 如果失败,进入 auth rotation 或 model fallback ↓ 写入 session state 和日志这条链路说明:
Provider 系统不是单独存在的; 它贯穿模型选择、认证、工具调用、失败恢复和输出生成全过程。22. 自定义 Provider 配置示例
假设我们有一个本地 OpenAI-compatible 服务:
http://127.0.0.1:8000/v1模型 ID 是:
qwen3-30b可以配置:
{ "agents": { "defaults": { "model": { "primary": "local/qwen3-30b" }, "models": { "local/*": {} } } }, "models": { "mode": "merge", "providers": { "local": { "baseUrl": "http://127.0.0.1:8000/v1", "apiKey": "sk-local", "api": "openai-completions", "timeoutSeconds": 300, "models": [ { "id": "qwen3-30b", "name": "Qwen3 30B Local", "reasoning": false, "input": ["text"], "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }, "contextWindow": 120000, "contextTokens": 80000, "maxTokens": 8192 } ] } } } }这里的重点是:
Provider ID 是 local; 模型本地 ID 是 qwen3-30b; 完整模型引用是 local/qwen3-30b; api 使用 openai-completions; baseUrl 指向本地服务; agents.defaults.models 用 local/* 允许该 Provider 下的模型。23. 常见问题一:为什么模型不出现在/model list?
可能原因有:
Provider 没有配置成功; models.providers 没有写入; models.mode 使用 replace 导致内置 catalog 被覆盖; agents.defaults.models allowlist 限制了可见模型; 插件未启用; Gateway 没有重启; 模型 ID 写错; Provider auth 不可用; session 仍然 pinned 到旧模型。排查思路:
openclaw models list openclaw models status openclaw config get models.providers openclaw config get agents.defaults.models openclaw gateway status --deep --require-rpc openclaw gateway restart如果当前 session 仍然使用旧模型,可以用:
/model status /model provider/model /reset官方文档也提醒,修改agents.defaults.model.primary不会重写已有 session selection;如果 status 显示当前 session pinned 到某模型,需要用/model Y切换当前 session,或者通过/reset清理旧 session 状态。(OpenClaw)
24. 常见问题二:为什么图片没有进入模型?
可能原因:
当前模型 input 只写了 ["text"]; 所选 Provider 不支持原生图片输入; 模型实际支持图片,但 catalog metadata 没写; WebChat 或 node-origin attachment path 发现模型不是 image-capable; 使用了错误的模型 ref; 图片理解模型和聊天模型配置混淆。解决方向:
{ "id": "my-vision-model", "input": ["text", "image"] }官方配置说明中也明确提到,如果 custom 或 proxy model 接收图片,需要在该模型上设置input: ["text", "image"],这样 WebChat 和 node-origin attachment paths 才会把图片作为原生模型输入传递,而不是文本媒体引用。(OpenClaw)
25. 常见问题三:为什么 fallback 没有发生?
可能原因:
用户用 /model 手动指定了 strict 模型; fallbacks 没有配置; 错误类型不属于 failover-worthy; 上下文过长这类错误应该走 compaction/retry,而不是 model fallback; 所有 fallback 都不在可用 Provider 中; auth profile 全部 disabled; fallback 模型也失败了。需要区分:
配置 primary 失败: 可以走 fallbacks。 用户手动 /model 选择失败: 更倾向直接报错。 rate limit / timeout / auth 失败: 更可能触发 fallback。 request too large / context overflow: 更可能触发压缩或报错。官方 failover 文档也说明,agent primaries 如果没有显式 fallbacks,以及显式用户选择、model picker、one-off CLI provider/model overrides 等场景通常是 strict;如果不可达或失败,会报告失败,而不是从无关 fallback 回答。(OpenClaw)
26. 常见问题四:models.providers和agents.defaults.models混淆
这是初学者最常见的问题。
models.providers: 注册 Provider 和模型目录。 agents.defaults.models: 控制模型可见性、别名、allowlist 和 metadata。错误写法:
{ "agents": { "defaults": { "models": { "local/qwen3-30b": {} } } } }如果只这样写,但没有:
{ "models": { "providers": { "local": { "baseUrl": "...", "models": [ { "id": "qwen3-30b" } ] } } } }那么 OpenClaw 可能知道你“允许 local/qwen3-30b”,但并不知道localProvider 如何连接,也不知道qwen3-30b在哪里。
官方文档也明确提醒,agents.defaults.models["provider/model"]只控制模型可见性、aliases 和 per-model metadata,不会单独注册新的 runtime model;自定义 Provider 模型还需要添加models.providers.<provider>.models[],并且至少包含匹配的id。(OpenClaw)
27. Provider 相关源码阅读路线
这一期建议从这些方向读源码:
第一组:Provider Plugin 类型 src/plugins/types.ts ProviderPlugin registerProvider ProviderRuntimeModel ProviderRuntimeProviderConfig 第二组:模型目录与 registry src/agents/model-catalog.* src/model-catalog/* src/llm/model-registry.* 第三组:Provider 配置解析 src/config/* models.providers models.mode agents.defaults.models 第四组:模型选择与命令 src/auto-reply/commands /model /models openclaw models list openclaw models status 第五组:OpenAI / Anthropic / Google 等插件 extensions/openai/* extensions/anthropic/* extensions/google/* extensions/ollama/* extensions/lmstudio/* extensions/openrouter/* 第六组:本地模型支持 local models OpenAI-compatible adapters openai-completions openai-responses 第七组:fallback 和 auth model failover auth profiles auth-state.json auth-profiles.json cooldown disabledUntil 第八组:工具兼容 provider tool schema normalization reasoning output mode transport normalization stream wrapper阅读时可以带着这些问题:
1. provider/model 是在哪里解析成 provider 和 modelId 的? 2. model registry 如何合并内置 catalog、plugins 和 models.providers? 3. agents.defaults.models allowlist 在什么阶段生效? 4. Provider Plugin 的 registerProvider 注册了哪些 hooks? 5. Provider 如何声明支持的 models? 6. OpenAI-compatible provider 如何选择 openai-completions 或 openai-responses? 7. Provider 如何处理 tool schema 不兼容? 8. auth profile rotation 在失败后如何选择下一个 key? 9. fallback candidate chain 是如何构造的? 10. /model 切换如何影响当前 session?28. 我的理解
我认为 OpenClaw 的 Provider 系统最值得学习的地方,是它没有把“模型调用”简单写成一个 API 请求函数。
很多 Agent 项目最初会这样设计:
callLLM(messages, tools)但随着模型后端增加,这个函数会越来越复杂:
如果是 OpenAI,就这样; 如果是 Anthropic,就那样; 如果是 Gemini,要转换图片格式; 如果是 OpenRouter,要处理模型名前缀; 如果是本地模型,要调整 baseUrl; 如果是 CLI runtime,要走命令行; 如果是 OAuth,要刷新 token; 如果 rate limit,要换 key; 如果 tool schema 不兼容,要删字段; 如果 streaming 格式不同,要重新解析; ……OpenClaw 的做法是把这些差异拆出去:
OpenClaw core 只保留通用 Agent loop; Provider Plugin 负责每个模型服务的特殊规则; models.providers 负责自定义连接; agents.defaults.models 负责可见性和选择策略; fallback 系统负责失败恢复; auth profiles 负责多账号和多 key 轮换。这样 Provider 系统就不只是“模型列表”,而是一套完整的模型接入控制层。
29. 本期重点理解
这一期可以总结为五点:
第一,Provider 是模型服务供应方,Model 是 Provider 下的具体模型,Runtime 是执行 Agent 推理的后端链路,Plugin 是把这些能力接入 OpenClaw 的机制。 第二,OpenClaw 使用 provider/model 作为统一模型引用格式,例如 anthropic/claude-opus-4-6。 第三,models.providers 用来注册自定义 Provider 和模型目录,agents.defaults.models 用来控制模型可见性、alias 和 allowlist。 第四,Provider Plugin 通过 registerProvider 接管认证、模型目录、transport normalization、tool schema cleanup、错误分类、usage reporting、reasoning profile 等 provider-specific logic。 第五,模型失败时,OpenClaw 会先尝试当前 Provider 内部的 auth profile rotation,再根据 agents.defaults.model.fallbacks 尝试其他模型。一句话概括:
OpenClaw 的 Provider 系统,本质上是一个模型接入与模型治理层,它把不同模型服务的认证、目录、协议、能力、错误和 fallback 策略统一纳入 Agent 执行链路。30. 本期小结
本期主要分析了 OpenClaw 的 Provider 系统。Provider 决定模型从哪里来、如何认证、使用什么协议、支持哪些输入模态、上下文窗口多大、是否支持工具调用,以及失败后如何切换。OpenClaw 使用provider/model作为统一模型引用格式,通过agents.defaults.model.primary和fallbacks设置默认模型与备用模型,通过agents.defaults.models管理模型 allowlist 和 alias,通过models.providers接入自定义或本地模型服务。Provider-specific logic 主要由 Provider Plugin 负责,包括 model catalog、auth env mapping、transport normalization、tool schema cleanup、failover classification、OAuth refresh 和 usage reporting 等。这样 OpenClaw core 可以保持通用推理循环,而不同 Provider 的差异由插件隔离处理。
这一期可以用一句话总结:
Provider 让 OpenClaw 能把不同云端模型、本地模型、CLI 后端和代理服务统一纳入同一套 Agent 推理、工具调用和失败恢复机制中。