Tech BlogAWSツール & 技術ブログ

Opus 5 は 4.8 と同額のドロップイン——ただし thinking が既定オンになった話と、自分の設定を棚卸しした記録

Claude Opus 5 が出ました。まず結論から書くと、Opus 4.8 からの移行はモデルIDの差し替えでほぼ済みます。料金は入力 $5 / 出力 $25 per MTok で 4.8 と同額、コンテキストウィンドウは 1M(既定かつ最大)、最大出力 128K、プロンプトキャッシュもバッチも Files API もそのまま使えます。上位ティアの Fable 5 が $10 / $50 なので、価格帯としてはその半分です。

つまり「乗り換えるとコストが上がる」という心配がない代わりに、判断軸が別のところに移ります。既定値が2つ変わっていて、そのどちらもエラーを出さずに挙動が変わるという点です。特に厄介なのは、片方が「HTTP 200 で正常終了したのに、やってほしかった処理が実行されていない」という形で出ることです。

この記事では、移行前に潰しておくべき落とし穴を、実際に自分の Claude Code 環境を Opus 5 目線で棚卸ししてみた結果と合わせてまとめます。過去のモデル世代交代についてはSonnet 5 と Opus 4.8 の使い分けOpus 4.8 リリース時の所感にも書いていますが、今回は「体感がどう変わったか」よりも「設定とコードのどこが黙って壊れるか」に寄せた内容です。

落とし穴1: thinking が既定オンになった。max_tokens は思考と応答の合計上限

Opus 4.8 と 4.7 では、リクエストに thinking を書かなければ思考なしで動いていました。Opus 5 はこれが逆で、thinking を省略すると adaptive thinking が有効になりますthinking: {"type": "adaptive"} を明示したのと同じ扱いです。パラメータの書き方自体はClaude Code と API のチートシートにも載せていますが、今回変わったのは書き方ではなく省略時の既定値の方です。

省略時の挙動はモデルごとにバラバラなので、表にしておきます。

モデル thinking 省略時 thinking: disabled
Opus 5 adaptive で思考する effort が high 以下なら可
Opus 4.8 / 4.7 思考しない
Sonnet 5 adaptive で思考する
Fable 5 常に思考する 400 エラー

「思考が有効になるだけなら品質が上がって嬉しいのでは」と思うところですが、ここに max_tokens が絡みます。max_tokens は思考トークンと応答テキストの合計に効く上限です。4.8 の時代に「応答は だいたい 2,000 トークンで収まるから max_tokens は 3,000 で十分」と詰めていた経路は、Opus 5 では思考が上限を食った分だけ応答が短くなり、最悪は文章の途中で切れます。

同じ max_tokens・同じリクエストでの内訳 Opus 4.8 省略=思考なし 応答テキスト(上限まで使える) Opus 5 省略=思考オン 思考トークン 応答テキスト 切れる max_tokens 上限 ※ 思考と応答は同じ上限を分け合う。エラーではなく stop_reason: max_tokens で返る

対処は単純で、thinking を一度も設定していない経路すべてで max_tokens を見直すか、思考を明示的に切ることです。ただし「切る」側には次の制約があります。

落とし穴2: thinking を切れるのは effort が high 以下。しかも検証はリクエスト単位

Opus 5 で thinking: {"type": "disabled"} が受け付けられるのは、effort が high 以下のときだけです。xhighmax と組み合わせると 400 が返ります。Opus 4.8 はこの組み合わせを受け付けていたので、4.8 で「レイテンシ優先だから思考オフ、でも賢さは欲しいから effort は最大」という設定にしていた経路は、モデルIDを変えた瞬間に落ちます。

さらに嫌なのが、この検証がリクエスト単位で走ることです。effort と thinking は毎回独立に検証されるので、会話の途中で effort を上げた後続リクエストだけが 400 になります。同じ会話の最初の数リクエストは通っているので、「さっきまで動いていたのに」という切り分けの難しい壊れ方になります。移行時はすべての呼び出し箇所を見る必要があり、最初の1箇所だけ確認して安心してはいけない類の変更です。

逃げ道は2つあります。effort を high 以下に下げるか、思考を戻すか。ここで効いてくるのが、Opus 5 は lowmedium がかなり強いという性質です。公式の推奨も「コーディングやエージェント用途は xhigh から始めて、そこから下げる方向に試す」という書き方になっています。レイテンシを優先したい経路なら、「xhigh +思考オフ」を維持するより「medium +思考オン」の方が筋がよく、コストも下がります。

落とし穴3: 思考を明示的に切ったときだけ起きる、2つのサイレント失敗

ここが今回いちばん気をつけるべき部分だと思っています。thinking: {"type": "disabled"} を明示した場合に限り、Opus 5 には2種類の静かな失敗があります。既定では思考がオンなので、素のリクエストでは踏みません。踏むのは「4.8 では省略が思考オフだったから、同じ挙動を保つために disabled を書き足した」コードです。

1つめ: ツール呼び出しが可視テキストとして出力され、実行されない。 構造化された tool_use ブロックではなく、ユーザー向けのテキストの中にツール呼び出しが書かれることがあります。ターンは正常に完了し、エラーも出ず、tool_use ブロックが存在しないので拾うフックもありません。ハーネス側からは「成功したターンで何も実行されなかった」ように見えます。エージェントループだとさらに悪く、その偽のテキストが会話履歴に残って後続のターンを汚染します。検索のようなツール多用のワークロードで出やすいとされています。

2つめ: <thinking> タグが応答に混入する。 内部的な XML タグがユーザー向け出力に漏れてきます。

どちらも「思考をオンに戻して effort を下げる」のが正攻法で、それが可能ならこの節は読まなくていい話です。それでも思考オフを維持しないといけない場合、対処が反直感的で面白いところがあります。

  • 「考えるな」「推論するな」系の指示は削除する。タグ混入を抑えるどころか悪化させます。抑制しようとして書いた指示が原因になっている、という逆転です。
  • タグ名を挙げずに一般形で書く。<thinking> タグを出さないで」より「内部的・システム的な XML タグを応答に含めないで」の方が効きます。名指しは測定上むしろ効果が薄いとされています。
  • ツールを使う前に一言喋る許可を与える。 ツール呼び出しがテキストに漏れる現象は、モデルが書きたがっている前置きを抑制したことに起因しているようで、「ツールを使う前に短く一文述べてよい」と伝えると収まります。

落とし穴4: プロンプトキャッシュの最小トークン数は世代間で単調じゃない

Opus 5 でプロンプトキャッシュの最小プレフィックスが 1024 トークンから 512 トークンに下がりました。これ自体は嬉しい変更で、「短すぎてキャッシュできない」と諦めていたプロンプトがコード変更なしでキャッシュ対象になります。

ただ、この値を世代順に並べると単調じゃないので注意が必要です。

モデル キャッシュ最小トークン
Opus 5 / Fable 5 512
Opus 4.8 / Sonnet 5 / Sonnet 4.6 1024
Opus 4.7 2048
Opus 4.6 / Opus 4.5 / Haiku 4.5 4096

「新しいほど小さい」ではありません。3,000 トークンのプロンプトは Opus 5 と 4.8 ではキャッシュされ、Opus 4.6 や Haiku 4.5 では黙ってキャッシュされません。しかもエラーは出ず、cache_creation_input_tokens が 0 になるだけです。用途に応じてモデルを行き来させる運用(重い処理は Opus、軽い処理は Haiku など)をしていると、片方だけキャッシュが効かず「同じ実装のはずなのにコストが合わない」という形で刺さります。キャッシュヒットの確認は usage.cache_read_input_tokens を見るのが確実です。

落とし穴5: Priority Tier 対象外、レート制限は別枠、fast mode は Claude API のみ

API を直接叩いている場合の運用面で、3つ引っかかりました。

Priority Tier は Opus 5 と Sonnet 5 が対象外です。 Opus 4.8 や Fable 5 は対象なので、Priority Tier 前提で組んだ本番経路のモデル名を Opus 5 に差し替えると、バリデーションで落ちます。「新しいモデルだから当然サポートされているはず」と思い込みやすいところです。

レート制限は Opus 4.x 共通枠とは別バケットです。 Opus 4.8 / 4.7 / 4.6 / 4.5 は共通の枠を分け合っていますが、Opus 5 はそこから引きません。つまりトラフィックを移しても旧枠は空かず、旧枠で確保していた上限を引き継ぐわけでもありません。移行前に Opus 5 側の枠を確認しないと、切り替えた瞬間に 429 が増えます。

fast mode は Opus 5 でも使えますが、$10 / $50 の別料金で、Claude API 限定です。 Bedrock や Google Cloud、Microsoft Foundry の経路では使えないので、マルチプラットフォーム構成なら分岐が必要になります。

もう1つ、API 経路で見落としやすい点として、Opus 5 はセーフティ分類器がリクエストを拒否することがあり、その場合 HTTP 200 で stop_reason: "refusal" が返ります。エラーではないので、response.content[0] を無条件に読むコードは例外で落ちます。stop_reason を先に見る作りにしておくのが必須です。サイバーセキュリティ系のカテゴリで拒否された場合は Opus 4.8 が推奨フォールバック先になっているので、フォールバックを入れておけば実際に処理が救われます。

プロンプトは「足す」より「消す」方向で直す

移行時のプロンプト調整で、方向が今までと逆になっているものが2つあります。

検証を促す指示は削除する。 Opus 5 は言われなくても自分の作業を検証します。そこに「最後に検証ステップを入れろ」「サブエージェントで検証させろ」といった指示が残っていると過剰検証になり、削除しても能力面の劣化は起きないとされています。書き換えではなく削除です。ハーネス側に持っている独立した検証ステップも冗長になっている可能性があります。面白いのは、「self-check させる」は一般的には有効なプロンプト手法で、このモデルではそれが裏目に出るという点です。プロンプトのテンプレート集を一律運用していると、ここだけ例外扱いが必要になります。

委譲を促す指示も削除する。 Opus 4.8 はサブエージェントを呼ぶのに消極的で「もっと委譲せよ」と書き足す必要がありましたが、Opus 5 は自分から呼びに行きます。呼べば呼ぶほどコンテキストの再構築とレポートの読み直しでコストと時間が増えるので、4.8 向けに足した委譲促進の文言は外して、逆に上限を設ける側に回るのが正解です。1世代でここまで方向が反転するのは珍しいと思います。

もう1つ、出力が長くなる傾向は effort を下げても縮まりません。ここは簡潔さの指示で対応する領域で、実際に短い簡潔化指示を入れると応答長が2割ほど減るとされています。effort をコスト調整のつまみとして使うのは正しいですが、冗長さのつまみとして使うのは間違い、という整理です。

自分の Claude Code 環境を Opus 5 目線で棚卸しした

ここまでは移行時に読むべき変更点の整理ですが、自分の環境が実際にどうなっているかは別問題なので、手元の設定を一通り見てみました。結果、思っていたより腐っていました。

~/.claude/settings.json のモデル指定が、黙って効かなくなっていた。 トップレベルに "model": "fable" と書いてありました。Fable 5 の期間限定復活のときに設定したものです。気になったのは、実際に動いているセッションが Opus 5 だったことです。

最初は「指定したモデルが使えなくなって残骸になったのだろう」と考えたのですが、調べたら違いました。他スコープの設定ファイル、つまりプロジェクト側・settings.local.json・managed settings のどれにもモデル指定はなく、環境変数も設定していません。fable は CLI が公式に認めているエイリアスで、claude --help にも「最新モデルのエイリアス、たとえば fable, opus, sonnet」と明記されています。無効な値ではありません。Fable 自体も到達可能なままです。

決定的だったのはセッション記録でした。Claude Code は ~/.claude/projects/ 配下にセッションログを残していて、リクエストごとに実際に使われたモデルIDが入っています。掘ってみると、7月15日までのセッションはすべて claude-fable-5 で動いていて、ピン留めはきちんと効いていました。そして Opus 5 が出たあとの今日のセッションは claude-opus-5 で始まっています。自分で切り替えてはいません。

つまりこれは「使えなくなったモデルの残骸」ではなく、書いた時点では効いていたピン留めが、モデル世代が変わったタイミングで黙って効かなくなったという話でした。エラーも警告も出ず、設定ファイルの文字列だけがそのまま残ります。設定ファイルを見ているだけでは絶対に気づけない類の腐り方です。CLAUDE.md にモデル指定を残すリスクはFable 5 を初めて使ったときの記事でも書きましたが、settings.json 側にはこの「静かに効かなくなる」パターンがあります。

effortLevel がグローバルに xhigh で入っていた。 これ自体は間違いではなく、コーディング用途の推奨に沿っています。ただ今回調べた内容と突き合わせると2つ言えます。1つは、自分の設定には thinking を無効化している箇所がなかったので、落とし穴2の「xhigh +思考オフで 400」は踏んでいないということ。逆に言えばあの 400 は API を直接叩くコード側の問題で、Claude Code の設定を見ていても発見できません。もう1つは、Opus 5 は lowmedium が強いので、xhigh を貼ったままにせず下げ方向に試す価値があるということです。ここは実際に下げて体感を比べるのが次のタスクになりました。

サブエージェント定義は alias 指定だったので無事だった。 ~/.claude/agents/ 配下の定義には model: opusmodel: sonnet と書いてあり、バージョン番号を含む固定IDではありませんでした。alias は世代交代に自動追従するので、Opus 5 が出た時点で勝手に追いついています。腐っていたのは fable というハード指定だけでした。alias で書いた箇所は生き残り、特定モデルを名指しした箇所だけが腐る——これが今回の棚卸しでいちばんはっきりした学びです。

thinking や effort をリクエスト単位で設定しているコードは1つもなかった。 当然ではありますが、この事実が判断を単純にしてくれました。Claude Code から使っているだけなら、「thinking が既定オンになった」は自分の設定を変える話ではありません。効いてくるのは API を直接叩いている経路だけです。逆に、自分でスクリプトから Claude API を呼んでいる人はそこを最優先で見るべき、という切り分けができます。

設定ファイルより先にドキュメントが腐っていた。 自分用のルールファイル(Markdown)に、旧世代のモデル名を直接書き込んだ記述が残っていました。設定ファイルは動作に影響するのでいずれ気づく可能性がありますが、ドキュメントに書いたモデル名は誰にも検証されないまま古くなります。CLAUDE.md のメンテナンスでも書いたとおり、この種のファイルは書いた時点で正しくても、放置すると古い前提を将来の自分に読ませることになります。

同じ棚卸しをするなら、このあたりを見れば足ります。

# 設定ファイルのモデル指定(ユーザースコープとプロジェクトスコープ)
grep -n '"model"\|effortLevel\|advisorModel' ~/.claude/settings.json .claude/settings.json 2>/dev/null

# バージョン番号を含むモデルIDのハード指定を全部洗い出す
grep -rniE 'claude-(opus|sonnet|haiku|fable)-[0-9]' ~/.claude/ .claude/ \
  --include='*.md' --include='*.json' 2>/dev/null

# サブエージェント定義のモデル指定(alias なら追従、固定IDなら要更新)
grep -rn '^model:' ~/.claude/agents/ 2>/dev/null

# 設定が実際に効いているかの実測。直近セッションで使われたモデルを数える
# (ディレクトリ名は作業パスを - でつないだもの。ls ~/.claude/projects/ で探す)
for f in $(ls -t ~/.claude/projects/<プロジェクト>/*.jsonl | head -5); do
  echo "--- $(basename "$f") ---"
  grep -o '"model":"[^"]*"' "$f" | sort | uniq -c
done

最後のコマンドが今回いちばん役に立ちました。設定に何と書いてあるかではなく、実際にどのモデルが動いたかを出せるので、ピン留めが効いているかどうかを事実で確認できます。世代交代の直後はこれを一度回しておくといいと思います。

まとめ: 400 になるものと、静かに変わるもの

移行時のチェック項目を、壊れ方で2つに分けて整理します。前者は放置すればエラーで気づけますが、後者は気づけません。

エラーで落ちる(対応は必須)

  • thinking: disabled と effort xhigh / max の組み合わせ → 400。effort を下げるか思考を戻す。呼び出し箇所すべてを確認する
  • Priority Tier 前提の経路に Opus 5 を指定 → バリデーションエラー
  • fast mode を Bedrock 等の経路で使用 → 非対応
  • (4.7 以前から来る場合)budget_tokenstemperature / top_p / top_k・末尾 assistant のプレフィル → いずれも 400

静かに挙動が変わる(自分で確認するしかない)

  • thinking を設定していない経路 → 思考が有効化され、max_tokens を思考と共有する。応答が途中で切れないか確認する
  • レート制限が別バケット → 旧枠の上限は引き継がない。切り替え前に確認する
  • キャッシュ最小が 512 に低下 → 短いプロンプトが新たに対象になる。逆に古い世代へ戻す経路は 4096 の壁がある
  • 設定ファイルのモデルのピン留め → 世代交代のタイミングで黙って効かなくなることがある。セッションログで実際に動いたモデルを実測する
  • 拒否応答が HTTP 200 で返る → stop_reason を先に見る作りにする
  • 「検証しろ」「委譲せよ」系の指示 → 過剰動作の原因になるので削除する
  • 出力の冗長さ → effort では縮まらないので簡潔さの指示で対応する

自分の環境については、「モデル名を名指しした箇所だけが腐る」という一点に集約できました。ハード指定を alias に寄せておけば、次の世代交代でこの棚卸しをもう一度やる必要はなくなります。

そしてもう1つ、今回いちばん効いた学びを付け足すなら、設定ファイルを読んで確認した気になってはいけないということです。書いてある内容と実際に動いているものが一致している保証はなく、しかも一致しなくなったときに誰も教えてくれません。Opus 5 は 4.8 と同額のドロップインなので、移行そのものは軽い作業です。重かったのは、過去の自分が書き残した固定値を見つけ出し、それがまだ効いているのかを実測する作業の方でした。