ワークフロー&基本ツール · daymade/claude-code-skills

openclaw-model-switch

OpenClaw インスタンスのモデル設定の切り替えや修復を行います(例:Kimi k2p6 → k3)。デフォルトモデルの変更、モデル定義の追加、およびモデル設定エラー(401 "Invalid token"、「No available channel / model not found」、思考レベル拒否「Thinking level X is not supported」、設定変更が反映されない問題など)を解決します。ユーザーが OpenClaw モデルの切り替え・アップグレード・ロールバック(切换模型/换模型/ 升级模型)を希望する場合や、OpenClaw/龙虾ボットのモデル設定ミス(模型配的错了)を指摘した場合、またはボットがフォールバックしたり LLM 呼び出しでエラーを返したりした場合に使用します。

L4 高権限 · 段階的認可と監査V1 コミット固定コマンド実行ネットワーク通信ファイル書き込みDual-pass Audit
Author daymadeGitHub daymade/claude-code-skills ↗Stars 1392License MIT(仓库根 LICENSE 文件;GitHub API spdx MIT;Copyright (c) 2025 daymade)Commit d5c4678cb5
管理レベルは Skill の能力と推奨統制措置を示すものであり、品質や安全性の認証、利用可否の判定ではありません。使用の可否はユーザーおよび管理者が決定します。Agent 環境によって制約が異なるため、自動保護を仮定しないでください。第三者製 Skill の著作権は原著作者に帰属し、利用リスクは利用者が負います。

1仕組みと動作原理

わずか 240 行の単一スクリプトで構成され、その動作は「openclaw.json の読み込み → JSON の変更 → 元ファイルへの上書き」に徹しており、デーモンや API ラッパーは存在しません。

openclaw-model-switch/scripts/switch-model.py
def save_config(path: Path, config: dict): with open(path, "w", encoding="utf-8") as f: json.dump(config, f, indent=2, ensure_ascii=False) f.write("\n")
ここでの処理内容: このアーキテクチャにおいてモデルの切り替えは、バックアップを伴うテキストレベルの JSON 書き換えと同等です。OpenClaw ゲートウェイの起動時に読み込まれるのがまさにこのファイルであり、スクリプトは IPC/RPC を行わないため、「変更後の再起動は必須」というハードな制約が存在します(スクリプトの末尾にこのプロンプトが出力されます)。

設定検出は「明示的な --config によるショートカット、それ以外の場合は 3 つの候補のうち存在するものをすべて編集対象としてリストアップ」し、同時に変更すべきミラーとして扱います。

openclaw-model-switch/scripts/switch-model.py
CONFIG_CANDIDATES = [ Path.home() / ".openclaw" / "openclaw.json", Path.home() / ".kimi" / "kimi-claw" / "openclaw.json", Path.home() / ".kimi_openclaw" / "openclaw.json", ]
ここでの処理内容: 「変更したのに反映されない」最大の根本原因を解決します。マシン上に openclaw.json が複数存在し(デスクトップ版、ゲートウェイ、Kimi Claw ミラー各 1 つ)、1 つだけ変更しても次回同期時に上書きされてしまいます。なお、デフォルトの探索順序は同リポジトリ内の openclaw スキル(~/workspace/.force/openclaw を優先)とは異なります。

「ミラーの同期」の実装は、プライマリ設定を他のファイルへコピーするのではなく、各設定ファイルに対して個別に同じ変更ロジックを実行する方式をとっています。

openclaw-model-switch/scripts/switch-model.py
print(f"Found {len(configs)} config files; will edit and sync all:")
ここでの処理内容: 各ファイルが個別に読み込み → バックアップ → provider/デフォルトモデル変更 → 保存を行います。各ファイル固有の内容が消去されないメリットがある一方、元々 2 つのファイル間に差異があった場合は変更後も差異が残るという副作用があります(verification.second_pass の discrepancy の項を参照)。

変更対象のファイルは書き込み前に必ず <設定ディレクトリ>/config-backups/openclaw-<ローカルタイムスタンプ>.json へバックアップされ、保持上限やプルーニングのロジックはありません。

openclaw-model-switch/scripts/switch-model.py
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") backup_path = backup_dir / f"openclaw-{timestamp}.json" shutil.copy2(path, backup_path)
ここでの処理内容: バックアップは「ワンクリックロールバック」の前提条件であり、SKILL.md の安全ルールの第 1 条でもあります。同リポジトリ内の openclaw スキルの backup_config と比較すると、UTC タイムスタンプ(本スクリプトではローカル時間の datetime.now())と 20 世代の保持上限の 2 点が欠けており、使用に伴いディレクトリは肥大化し続けます。

モデル定義が存在しない場合は組み込み定義を自動補完します。KNOWN_MODELS に k3 / k2p6 / kimi-k2.7-code の id、contextWindow、maxTokens、input モダリティがハードコードされており、provider レベルの headers を継承させます。

openclaw-model-switch/scripts/switch-model.py
"k3": { "id": "k3", "name": "k3", "reasoning": True, "input": ["text", "image"], "contextWindow": 1048576, "maxTokens": 32768, },
ここでの処理内容: モデルブロックを手動記述することなく、model id を入力するだけで「新モデルへの切り替え」ができるよう敷居を下げています。headers の継承(provider.get("headers"))は、Kimi 公式エンドポイント向けの X-Kimi-Claw-ID / User-Agent ヘッダーを追加モデルでも引き続き機能させるための措置です。

デフォルトモデルの参照を agents.defaults.model.primary に書き込み(形式判定は行わず添字で直接代入)、同時に agents.defaults.models のエイリアスマッピングを書き換えます。

openclaw-model-switch/scripts/switch-model.py
config["agents"]["defaults"]["model"]["primary"] = f"{provider_name}/{model_id}"
ここでの処理内容: OpenClaw ではデフォルトモデルを文字列または {primary: ...} オブジェクトとして記述できますが、本スクリプトはオブジェクト形式のみをサポートしています。ユーザー設定が文字列の場合は TypeError が発生し、agents.defaults ブロック全体が欠落している場合は KeyError が発生します(openclaw の set_default_model は形式に自動適応するのと対照的です)。

デフォルトモデル変更時、エイリアスマッピング内の「現在の provider/」で始まるすべてのキーを削除した上で、新モデル用の空オブジェクトのみを書き戻します。

openclaw-model-switch/scripts/switch-model.py
stale_keys = [k for k in models_map if k.startswith(f"{provider_name}/")] for k in stale_keys: del models_map[k] models_map[f"{provider_name}/{model_id}"] = {}
ここでの処理内容: 古いモデルのエイリアス残骸による混乱を防ぐ意図ですが、実際には同一 provider 配下の他モデルのエイリアス("DeepSeek V4 Pro" のようなユーザー定義の表示名エイリアスを含む)もまとめて消去されてしまうため、実質的な破壊的副作用となります(verdict.risks を参照)。

書き換え後はメタデータのタイムスタンプを保守します。meta.lastTouchedAt に UTC ISO 時間を書き込み、meta.lastTouchedVersion が存在すれば維持、存在しなければ "unknown" を設定します。

openclaw-model-switch/scripts/switch-model.py
config.setdefault("meta", {})["lastTouchedAt"] = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
ここでの処理内容: OpenClaw に対し「この設定が最後にいつ変更されたか」の記録を残し、「いつ変更されたのか、自分が変更したのか」の調査を容易にします。また、本スクリプトがユーザー設定に新しいフィールドを挿入する唯一の箇所でもあります(既存の meta の内容は削除しません)。

再起動パスは `openclaw gateway restart` の 1 系統のみであり、失敗時は警告を出力してユーザーに手動再起動を促すだけで、systemd へのフォールバックはありません。

openclaw-model-switch/scripts/switch-model.py
["openclaw", "gateway", "restart"],
ここでの処理内容: subprocess.run に argv リストを渡す(shell=True を使わない)ためコマンドインジェクションの脆弱性はありません。ただし、openclaw が PATH に通っていない場合は手動再起動しか選択肢がなく、SKILL.md の kimi-models.md でも「openclaw gateway restart requires CLI to be in PATH」が既知の制限事項として挙げられています。

スクリプトの枠を超えた本当の「スキルの深さ」はドキュメント層の診断プロトコルにあります。まず curl を使って <baseUrl>/v1/messages に対し実際の補完プローブを実行し、設定変更後に openclaw agent で検証を実行します。

openclaw-model-switch/SKILL.md
curl -sS -o /tmp/probe.json -w "HTTP %{http_code}\n" \ -X POST "<baseUrl>/v1/messages" \ -H "Authorization: Bearer <apiKey>" \ -H "Content-Type: application/json" \ -H "anthropic-version: 2023-06-01" \
ここでの処理内容: 「一覧(listing)は信用できない、実際のリクエストのみが確証となる」という規律を確立します。該当モデルでエンドポイントが 200+content を返すことを証明してから設定を変更します。このステップはドキュメントに従ってエージェントが実行するものであり、スクリプト自体はネットワークリクエストを一切行いません。

2コア機能

01ワンコマンドでのデフォルトモデル切り替え: python3 scripts/switch-model.py <model-id> [--provider NAME] [--config PATH] [--restart]
02複数の openclaw.json の自動検出と一括編集(次回同期による上書きを防ぐためミラーも同時に変更)
03未知のモデルに対する組み込み定義の自動補完(k3: 1,048,576 コンテキスト / k2p6: 201,072 / kimi-k2.7-code: 262,144、いずれも 32,768 出力上限)
04書き込み前の自動バックアップ: 変更対象の各設定と同じディレクトリの config-backups/ 配下にタイムスタンプ付きコピーを作成
05provider の自動推測(デフォルトでは kimi-coding を優先、それ以外は設定内の先頭の provider を採用)、--provider による明示指定も可能
06エンドポイント/モデルの真偽プローブプロトコル: POST <baseUrl>/v1/messages が 200 を返し body に content 配列を含むことを確認(401 はキーのハイジャック、503 はリレーグループの利用不可を特定)
07エンドツーエンド検証プロトコル: openclaw agent --local --json を実行し、result=success かつ fallbackUsed=false であることを検証(フォールバックで失敗を隠蔽している場合は成功とみなさない)
085 種類の現場障害のトラップカタログ(環境変数キーのハイジャック / プラグインによる思考レベルのハードコード / リレー 503 グループ / 非権威な一覧表示 / 編集対象ファイルの誤り)+ ローカル echo サーバーによるパケットキャプチャ手順

3外部依存関係

KindDependency / Endpoint
cliopenclaw CLI(gateway restart;脚本实际调用)
cliopenclaw gateway status(读 Config (service) 判断网关真正读哪份配置)
cliopenclaw agent --local --json(Step 4 端到端验证,看 result/fallbackUsed)
clicurl(Step 2 端点探针;由 agent 按文档执行,非脚本调用)
clipython3 -m json.tool(手工编辑后的 JSON 校验建议)
apiAnthropic Messages 兼容接口(探针目标:POST <baseUrl>/v1/messages,Bearer + anthropic-version 头)
networkKimi 官方端点(references 里给出的 provider baseUrl 示例)
network本地 echo 抓包服务器(trap 目录附录的 wire-capture 配方,读真实 x-api-key)
packagePython 3 标准库 only(json/os/shutil/subprocess/argparse/pathlib/datetime;无第三方依赖)

4推奨統制措置と判定根拠

安全運用のための推奨統制措置
Agent 向け
段階的・都度認可、サンドボックス推奨
管理者向け
承認フロー、ロールバック可能、全履歴監査
判定根拠(ファイルパスと抜粋)
  • scripts/: ローカルスクリプトまたはコマンドの実行: python3 scripts/switch-model.py <model-id> [--provider NAME] [--config PATH
  • 网络端点: 外部ネットワークアクセスの宣言: スクリプト自体: ネットワーク呼び出しゼロ(urllib/requests/socket/httpx なし、URL 定数なし)
  • 本地工作目录: ファイル読み書きとアーティファクト出力: <検出された各 openclaw.json>(インプレース上書き、indent=2 + ensure_ascii=False + 末尾改行)
監査ノート: リスク警告: 黄色。ローカル設定の書き換え+ドキュメント駆動の外部プローブに分類されます。理由: ①付属スクリプトは子プロセスを実行し、dry-run や構造バリデーションなしに openclaw.json をインプレースで直接上書きするため(同リポジトリの openclaw が持つ --dry-run や自動 audit と比較して)、誤った設定も即座に反映されてしまいます。②スクリプトには、同一 provider プレフィックスの agents.defaults.models 配下の全キーを削除し、他モデルのエイリアスまで巻き添えで消去するという実際の破壊的副作用があります。③ドキュメントに従って実行する場合、provider の apiKey を用いて <baseUrl>/v1/messages に対する curl プローブが実行され(ユーザー自身が設定したエンドポイントへの送信であり、想定内の業務通信で外部流出ではありません)、パケットキャプチャ手順では実際の x-api-key が /tmp/captured.txt に書き出されます。④スクリプト自体はネットワーク呼び出しを行わず、環境変数の認証情報も読み取らず、サードパーティ依存関係も持ちません。したがって、人間の監視下での変更が必要ですが、オレンジ(第三者への認証情報送信や情報流出コードパスが存在する状態)には当たらないため「黄色」と判定します。

5二重目の独立検証

  • [discrepancy] 文档称脚本 'syncs mirror files'(SKILL.md Step 3)是否等于内容同步 — 代码只对每个发现的文件各自施加同一处修改(循环里 load→backup→改 provider/默认模型→save),从不把主配置内容复制到其它文件;因此若两份 openclaw.json 原本就有差异,改完仍然有差异,只是「默认模型」这一处一致了。SKILL.md 的 'syncs mirror files' 与脚本实际的 'edit all of them identically' 不是一回事,属措辞夸大(脚本自己的打印也是 'will edit and sync all')。
  • [discrepancy] README 声称 openclaw-model-switch 有 'Model validation against provider's model list' — 脚本里没有校验门禁:模型不在 provider 的 models 里时只做 model_exists → 若内置 KNOWN_MODELS 也没有该 id,仅打印 Warning('Model X is not defined in config and not in built-in known models.')然后照常写入并返回 0。SKILL.md 自身并未这样宣称(它靠 Step 2 探针 + Step 4 验证兜底),所以是 README 层面的描述与代码能力不符。
  • [ok] 「Step 2 端点探针 / Step 4 端到端验证」是否由 skill 代码实现 — 复核确认这不是代码能力而是文档纪律:grep 全脚本无任何 HTTP 客户端与 curl 调用,Step 2/Step 4 都是给 agent 的操作指令(curl 与 openclaw agent 两条命令)。本报告已在 how_it_works 末条、capabilities 与 external_deps 中统一标注为「文档指示、非脚本执行」,避免把文档承诺记成代码能力。
  • [ok] 脚本是否发网络请求 / 读 env 里的 API key(用户指定的两个重点) — 反向扫描 scripts/ 零命中:无 urllib/requests/socket/httpx/curl/wget;无 os.environ/getenv/apiKey 读取。附带发现 import os 在该文件中完全未被使用(无 os.* 调用),说明连标准库层面的环境访问都没接上——凭证交接 100% 发生在文档层(curl 头)而非代码层。
  • [ok] 备份是否真的先于写入、且每份被改文件都有备份 — 循环体内顺序为 load_config → 解析 provider → backup_config(打印 '[path] backed up to: …')→ add_model_definition → update_default_model → 写 meta → save_config,备份严格前置于任何 save_config;显式 --config 时不走 discover_configs 的多文件分支,只备份那一个文件,与文档一致。
  • [ok] 别名清理的破坏范围(第一遍记录「删除 stale keys」,第二遍量化影响) — 确认删除条件是 k.startswith(f"{provider_name}/"),粒度是整个 provider 前缀而非「旧模型」——同一 provider 下所有其它模型的别名映射条目都会被 del,随后只补回新模型的一条空对象(models_map[f"{provider_name}/{model_id}"] = {});若属性顺序上是先删后写,用户其它模型的显示名别名确实会永久丢失(备份可回滚)。已升级为 verdict.risks 首位。
  • [ok] 多文件模式下的失败原子性 — provider 缺失时在循环体内直接 sys.exit(1),若第一个候选文件已成功写入而第二个文件里没有该 provider,进程会在中途退出:出现「有的文件改了、有的没改」的半改状态,且没有回滚逻辑(文档也未提示需人工核对全部镜像)。
  • [ok] SKILL.md 的故障知识是否能在 references 里落地(声明 vs 资产) — SKILL.md 表格里的 5 类症状与 references/troubleshooting-model-config.md 的 5 条 trap 一一对应(含 env KIMI_API_KEY 劫持、插件 binary thinking、canonicalModelId 解等级、relay 分组 503、改错文件),kimi-models.md 也确实给出 k3/k2p6/kimi-k2.7-code 的规格与配置片段;文档承诺的知识资产存在且自洽,无空头引用。

6結論

  • 実際の運用トラブルを再現可能な診断プロトコルへ昇華: プローブでエンドポイント/モデルの有効性を証明してから設定を変更し、最終的に実際の agent による検証を必須とする(fallbackUsed は false 必須)という「証明優先」の規律が、純粋な設定ツールとの最大の違い
  • 「変更が反映されない」真の根本原因であるマシン上の複数 openclaw.json を直撃: 単一のハードコードされたパスに固執せず、デフォルトで 3 つの候補のうち存在するファイルをすべて変更
  • モデル切り替えの運用コストが極めて低い: 内蔵の KNOWN_MODELS により、設定内にモデル定義がない場合でもワンタッチで補完し、provider の headers も自動継承
  • 希少な現場トラブル対応アセット: 環境変数によるワイヤキーのハイジャック、プラグインによる思考レベルの固定化、リレーのグループ別 503 といった「ドキュメントに載っていない」落とし穴を、症状 → 真因 → 証明方法 → 修正手順としてまとめ、実行可能な echo サーバーのパケットキャプチャ手順まで付属
  • スクリプト実装がクリーン: 純粋な標準ライブラリのみ、ネットワークアクセスなし、固定 argv による非シェル子プロセス実行。モデル切り替えという要求以外の余計な処理を行わない(meta タイムスタンプのみ追加書き込み)
  • 最適な用途: 「OpenClaw マシンが手元にあり、特定ボットのモデルを切り替えまたは修復したい」という運用シーンに最適です。特に新しくリリースされた Kimi モデルへの移行(k2p6 → k3)、401 Invalid token / Thinking level not supported / 503 No available channel でスタックしている場合、または設定変更が反映されないケースに適しています(SKILL.md の Step 1〜4 はまさにこのトラブルシューティング手順に沿っており、トラップカタログから直接真因と証明手段を特定可能)。また、事前にプローブによる証明を求め、変更後はエンドツーエンド検証を必須とするため、「成功と報告されたが実際にはフォールバックで動いていた」という見せかけの成功を防ぐことができ、エージェント向けの「運用マニュアル」としても最適です。
    不向きな用途: 複数ボットの横断的な比較や一括メンテナンスが必要なシナリオには不向きです(それは openclaw スキルの audit/diff/copy/list サブコマンドの守備範囲であり、本スキルは「現在のマシン上のいくつかのミラー」のみを対象とします)。設定のインプレース書き換えを許容できず、事前にプレビューを行って判断したい慎重な運用には不向きです(--dry-run 非搭載)。デフォルトモデルが文字列形式で記述されている設定や、agents.defaults の構造が不完全な設定には不向きです(ディスク書き込み前に KeyError でクラッシュし、複数ファイル処理時には手前のファイルのみ変更されるリスクがあります)。また、カスタム deepseek provider の作成が禁止されていたりモデル ID に [1m] を含めることが禁じられている DeepSeek ゲートウェイ provider 向けのパッチ作業にも不向きです(そちらは openclaw + deepseek_patch_sop.md の担当です)。
    Install Agent-Ready
    ① Verified Mirror 2026-09-15
    Option A · Direct DownloadDownload openclaw-model-switch.tar.gz
    sha256: c53908d204b24a25…
    Option B · Copy Guide for Agent
    install.json
    Agent はこの JSON ガイドから自動的にダウンロードして検証します。
    ② Upstream GitHub
    GitHub Repo ↗
    Pinned to commit d5c4678cb5.