Python から Claude API を叩いているなら、次に pip install -U を打った日が移行日になる。Anthropic の Python SDK が v1.0 になり、内部の HTTP 層が httpx から API 互換フォークの httpx2 へ移った。旧 Text Completions API と、Messages の temperature / top_p / top_k、tool runner の compaction_control は削除。動作要件も Python 3.10 以上に上がった。手元のどこが当たるかは上げる前に数えられる。ただし grep だけで数えると漏れる変更が2つある。
目次
多くのコードに当たる8点
リリースノートと移行ガイドの記述を、手元で何をやることになるかで並べ直すとこうなる。中央の列が公式の記述、右の列が自分のコードに対して起きる作業だ。これは全部ではない。移行ガイドの破壊的変更はもっと多く、残りは次の節にまとめてある。
| # | 変わったこと | 手元でやること |
|---|---|---|
| 1 | HTTP 層が httpx から API 互換フォークの httpx2 へ |
SDK に httpx 由来のオブジェクトを渡していなければ作業なし |
| 2 | カスタム http_client ・ Timeout ・ transport は httpx2 側から作る |
インポートを httpx2 に差し替える。旧 httpx.Client を渡すと生成時に TypeError |
| 3 | httpx にパッチを当てるトレース/モック系ライブラリを使う場合、httpx2.alias_httpx() を呼ぶ |
テストと計測まわりの依存を確認し、何より先に実行される場所へ1行置く |
| 4 | Python 3.10 以上が必須 |
実行環境の Python の版を確認する |
| 5 | 旧 Text Completions API、Messages の temperature / top_p / top_k、tool runner の compaction_control が削除 |
該当する呼び出しを grep して、残す・落とす・書き換えるを決める |
| 6 | .with_raw_response の戻り値クラスが変わり、async では await response.parse() が要る grep で拾いにくい |
.text と .content はメソッドになった。同期クライアントにも当たる |
| 7 | AnthropicBedrock がリージョン未設定で ValueError。us-east-1 への暗黙フォールバックが廃止 grep で拾いにくい |
aws_region= を渡すか AWS_REGION を設定する |
| 8 | Bedrock の未知のストリーミングイベントが読み飛ばされる | amazon-bedrock-invocationMetrics を拾っていたら作り直す |
5行目の「削除」は、読むときに一段の注意が要る。削除なら呼んだ瞬間に止まり、非推奨なら警告を出しながら動く。読者が取る行動が変わるので、同じ扱いにできない。移行ガイドは Removed: という見出しで並べ、削除された引数を渡すと TypeError になると書いている。本稿は削除として扱う。
残りの破壊的変更(当たる人は限られるが、当たると止まる)
移行ガイドの末尾に、変更前と対処を1行ずつ並べた早見表がある。上の8点に入れなかったものを、そこから写しておく。使っていなければ読み飛ばしてよい。使っている場合、最後の httpx_aiohttp を除いて上の grep には掛からない(これだけは rg -n "httpx" に当たる)。
| これまで書いていたもの | v1.0 での書き方 |
|---|---|
output_format={...}(スキーマ辞書を渡す形) |
output_config={"format": {...}}。ヘルパーの output_format=Model(クラスを渡す形)は残る |
messages.parse(stream=True) |
messages.stream(...) |
BetaBase64PDFBlockParam |
BetaRequestDocumentBlockParam |
client.post(..., body=b"...") |
content=b"..." |
メッセージのストリームに対する isinstance(x, Stream) |
isinstance(x, MessageStream) |
ヘッダ値に bytes を渡している |
.decode() して str にする |
同じヘッダ名を大小2種で default_headers と extra_headers に分けて渡している |
後のものが前を置き換える。両方要るなら自分で連結する |
agent_toolset.READ_MAX_BYTES |
DEFAULT_MAX_FILE_BYTES |
requirements の httpx_aiohttp |
落とす。anthropic[aiohttp] で足りる |
この表を作ってから、最初に書いた「grep が0本なら上げるだけ」という結論が成立しないことが分かった。数えられるのは検索語を思いついたものだけになる。
上げる前に、当たる行を数える
移行の作業量は、影響する行が何本あるかで決まる。0本なら上げてテストを回すだけで終わり、20本あるなら半日の作業になる。数えるのは先だ。
# 影響しそうな箇所を数える(ヒット数=直す行数ではない。次の節で絞る)
rg -n "httpx" --glob '!*.lock'
rg -n "http_client|transport=|Timeout\("
rg -n "temperature|top_p|top_k"
rg -n "compaction_control"
rg -n "completions"
# grep で漏れやすい2つ(表の6・7)
rg -n "with_raw_response"
rg -n "AnthropicBedrock|AsyncAnthropicBedrock"
# 依存の宣言側も見る(バージョン指定を固定しているか)
rg -n "anthropic" requirements*.txt pyproject.toml
Windows でそのまま走らせるなら PowerShell の Select-String でも同じことができる。件数だけ先に見て、0 かどうかを判定する。
# 件数だけ先に見る
Get-ChildItem -Recurse -Filter *.py |
Select-String -Pattern 'httpx|http_client|compaction_control|with_raw_response|AnthropicBedrock' |
Measure-Object | Select-Object -ExpandProperty Count
ここで出る数字を「直す行数」と読むと外れる。temperature は他社の SDK にもローカル推論の呼び出しにも出てくる語で、Claude API と無関係なヒットが混ざる。completions も同じで、OpenAI 互換の呼び出しを持っているリポジトリでは大量に当たる。数えた後に、その行がどのクライアントに対する呼び出しかを目で見る工程が要る。
grep が0本でも安心できない2つ
ここが本稿を書き直した理由になる。最初に書いた原稿では、リリースノートの目立つ6点だけを並べて「grep のヒットが0本なら上げてテストを1回で終わり」と結んでいた。同じリリースノートの同じ段落に、grep の網に掛かりにくい破壊的変更が2件入っている。
1つ目は .with_raw_response だ。非同期クライアントで生のレスポンスを受け取っている場合、parse() がコルーチンになった。
# Before
response = await client.messages.with_raw_response.create(...)
message = response.parse()
# After
response = await client.messages.with_raw_response.create(...)
message = await response.parse()
.text と .content も属性からメソッドへ変わっていて、こちらは同期クライアントにも当たる。非同期側では text() ・ read() ・ json() も parse() と同じくコルーチンなので、await を付けないとレスポンスではなくコルーチンオブジェクトが返る。
| これまで | 同期クライアント | 非同期クライアント |
|---|---|---|
response.parse() |
response.parse() |
await response.parse() |
response.text |
response.text() |
await response.text() |
response.content |
response.read() |
await response.read() |
response.http_response.json() |
response.json() |
await response.json() |
.headers / .status_code / .request_id など |
変更なし | 変更なし(属性のまま) |
with_raw_response という語で1回 grep すれば見つかるが、「HTTP 層の入れ替え」を追っている頭では検索語に思い浮かばない。
2つ目は Bedrock 経由の場合になる。リージョンが解決できないとき、これまでは警告を出して us-east-1 に落ちていた。v1.0 は生成時に ValueError を投げる。
# Before — 何も設定していなければ暗黙で us-east-1
client = AnthropicBedrock()
# After
client = AnthropicBedrock(aws_region="us-east-1") # または AWS_REGION を設定
リージョンの解決順は aws_region= 引数、AWS_REGION / AWS_DEFAULT_REGION 環境変数、aws_profile に対応する boto3 セッションの設定。3番目は以前は無視されていたので、プロファイルに書いてあるから大丈夫という読みは v1.0 で初めて正しくなる。
この2件は、動かしている環境でだけ火が出る。Bedrock を使っていないなら7行目は当たらないし、生のレスポンスを触っていないなら6行目は当たらない。当たるかどうかを判定するには、リリースノートの箇条書きを最後まで読むしかない。
数え漏れを潰すなら、型チェッカを1回通す
移行ガイドは、grep より漏れの少ない手を1つ書いている。
A type checker (pyright / mypy) will flag almost everything below as an error after upgrading,
which makes it a good checklist even if you don't normally run one.
削除された引数を渡している行も、メソッドになった属性を属性のまま読んでいる行も、型チェッカなら検索語を思いつく必要がない。普段 pyright を回していないリポジトリでも、移行のときだけ1回通す価値がある。当サイトのリポジトリは pyright を入れてあるので、この手を先に使う。
Claude Code を使っているなら、移行ガイドは /claude-api upgrade python をプロジェクトで走らせて差分をレビューする形を案内している。差分を読む工程は残るので、影響範囲を先に数えておく意味は変わらない。
この形の棚卸しは8月に並んだ5つの廃止期限を grep 2本で監査した回と同じやり方になる。あのときは「期限までに直す対象を数える」目的だったが、今回は「上げてよいかを判定する」目的で使う。
httpx を掴んでいる箇所は4つに分かれる
grep でヒットした行は、次のどれかに落ちる。上から順に、作業が軽い側になっている。
| 型 | コードの見た目 | 必要な作業 |
|---|---|---|
| (a) 何も渡していない | クライアントの生成に API キーしか渡していない | なし。SDK が内部で用意する |
(b) http_client を渡している |
自分で作ったクライアントオブジェクトを引数で渡している | インポートを httpx2 に差し替える |
(c) Timeout を組み立てている |
接続・読み取りのタイムアウトを個別指定している | 同上 |
(d) transport を差し替えている |
リトライ・プロキシ・記録用のトランスポートを挟んでいる | 同上。挟んでいる目的ごと見直す価値がある |
(a) に全部落ちるなら、この節の作業は発生しない。SDK が内部で何を使うかは SDK 側の都合で、呼ぶ側のコードには出てこない。
(b) から (d) の書き換えは、移行ガイドが最小の編集として示しているのがインポートの別名づけだ。
# Before
import httpx
from anthropic import Anthropic, DefaultHttpxClient
client = Anthropic(
timeout=httpx.Timeout(60.0, connect=5.0),
http_client=DefaultHttpxClient(
proxy="http://my.proxy.example",
transport=httpx.HTTPTransport(local_address="0.0.0.0"),
),
)
# After
import httpx2 as httpx
from anthropic import Anthropic, DefaultHttpxClient
client = Anthropic(
timeout=httpx.Timeout(60.0, connect=5.0),
http_client=DefaultHttpxClient(
proxy="http://my.proxy.example",
transport=httpx.HTTPTransport(local_address="0.0.0.0"),
),
)
SDK 側の再エクスポート(anthropic.Timeout / anthropic.DefaultHttpxClient など)は既に httpx2 を指しているので、そのまま動く。旧 httpx.Client を http_client= に渡した場合は生成時に TypeError になるので、黙って壊れる形にはならない。anthropic.Transport と anthropic.ProxiesTypes は消えたので、httpx2.BaseTransport と httpx2.Proxy を直接使う。
(d) だけは、置き換えのついでに考え直す余地がある。トランスポートを差し替えている理由がリトライなら、SDK 側の再試行設定で足りるかもしれない。記録が目的なら、HTTP 層ではなく呼び出し側でログを取る形に移せる場合がある。型を組み直す手を動かす前に、その層を自分で持つ必要があるかを一度見る。
テスト側が httpx にパッチを当てているとき
実装コードに httpx が1行も出てこなくても、テストが掴んでいることがある。HTTP のやりとりを差し替えるモック系のライブラリと、外向きの通信を記録するトレース系のライブラリは、どちらも httpx の内部にパッチを当てて仕事をする。移行ガイドは respx ・ pytest-httpx ・ vcrpy ・ OpenTelemetry ・ Sentry を名前で挙げていて、これらは黙って失敗すると書いている。パッチを当てた先と実際に通信する側がずれるからだ。
解決は httpx2.alias_httpx() を1回呼ぶこと。置き場所には条件がある。httpx を誰かがインポートするより前に走らないと RuntimeError になる。
ここは筆者が最初に書いた原稿で外した箇所なので、そのまま書いておく。conftest.py の先頭に置く形を書いていた。移行ガイドが pytest 向けに示しているのは早期プラグインで、conftest.py より前に respx やテストモジュールが読み込まれる可能性を潰す形になっている。
# tests/_alias_httpx.py
import httpx2
httpx2.alias_httpx() # import httpx / httpcore を httpx2 / httpcore2 に解決させる
# pyproject.toml
[tool.pytest.ini_options]
addopts = "-p tests._alias_httpx"
pythonpath = ["."]
アプリケーション側ではエントリポイントの先頭に置く。ライブラリが利用者に代わって呼ぶことは、移行ガイドが明確に否定している。プロセス全体の import httpx の意味を変えてしまう呼び出しなので、決めるのはアプリケーションの側になる。
自分のテストが当てはまるかどうかは、依存を1回並べれば分かる。
# テストと計測の依存を並べて、httpx を前提にしているものを探す
pip list --format=freeze
rg -n "httpx" requirements-dev.txt pyproject.toml
削除された3つを探す
削除の対象は、旧 Text Completions API、Messages の temperature / top_p / top_k、tool runner の compaction_control の3系統だ。
Text Completions は client.completions.create()(/v1/complete)と、その型、HUMAN_PROMPT / AI_PROMPT の定数がまとめて消えた。Messages へ移していれば当たらない。移していないコードが残っているとしたら、初期に書いて動いたまま触っていないスクリプトの中になる。
temperature / top_p / top_k は、移行ガイドの案内が「消せ」になっている。現行モデルはこのサンプリング引数を使わないためで、引数がメソッドの署名から消えただけで API 側が受け付けなくなったわけではない。古いモデルに固定していて設定が要る場合は extra_body に入れて渡す。
# 古いモデルに固定していて、どうしても渡したいとき
client.messages.create(..., extra_body={"temperature": 0.2})
要約の再現性を上げるために 0 に近い値を入れていたなら、消した瞬間に出力の性質が変わる。当サイトの記事生成まわりでこの引数を使っていないかは、上の grep で数える対象に入れてある。
compaction_control は tool runner の引数で、当たる読者は限られる。ツールを繰り返し呼ぶ長い会話を SDK 側の runner に任せている場合だけ関係する。移行先はサーバー側の context_management による圧縮になる。自分で会話履歴を組み立てているなら、この行は関係ない。会話の途中に方針を差し込む書き方は会話途中の system メッセージに対応した回で扱っていて、そちらは runner を経由しない側の話になる。
Python 3.10 という新しい下限
要件が Python 3.10 以上に上がっている。3.9 以前で動いている環境では、SDK だけを上げることができない。
python -V
# 仮想環境ごとに違う場合があるので、実際に動かしている環境で見る
当サイトの週次収集ジョブは Python 3.12 系で回しているので、この行では止まらない見込みでいる。見込みと書いたのは、実際に v1.0 を入れて確かめていないからだ。
3.10 に届かない環境を持っているなら、選べる道は2つある。Python を上げるか、SDK のバージョンを固定して据え置くか。固定は期限つきの判断になる。削除された API を使い続けられるのは固定している間だけで、いずれ上げる日は来る。据え置きを選ぶなら、依存の宣言に上限を書いて、意図しない自動更新で上がらないようにしておく。
# requirements.txt に上限を書いておく例(据え置きを選んだ場合)
anthropic<1.0
移行を実際に走らせる計画(未実測)
本稿の時点で、v1.0 を手元に入れていない。書けるのはここまでで、以下は走らせる手順と、結果をどう判定するかの条件になる。
| 確かめること | 手順 | 判定 | 状態 |
|---|---|---|---|
| 現行の SDK 版 | pip show anthropic |
Version が v1.0 未満か | 未実測 |
| 影響行の本数 | 上の grep 7本 | ヒット数。0本でも「安全」の判定には使わない | 未実測 |
| 型チェッカの指摘 | v1.0 環境で pyright を1回 |
エラー件数と、その内訳 | 未実測 |
| インストールの可否 | 新規の仮想環境に v1.0 を入れる | Python の版で弾かれるか、依存の解決が通るか | 未実測 |
| 既存テストの結果 | v1.0 環境で pytest を1回 |
失敗の件数と、その内訳(HTTP 層由来/削除された引数由来) | 未実測 |
alias_httpx() の要否 |
早期プラグインを入れる前と後で pytest |
失敗件数が変わるか。変わらないなら当該ライブラリは無関係 | 未実測 |
| 実呼び出し | 検証環境から1リクエストだけ送る | 応答が返るか。返らない場合のエラー本文 | 未実測 |
試行回数は各1回とし、失敗した項目だけ3回まで繰り返して再現性を見る。1回で通ったものを3回引き直しても情報が増えないからだ。記録するのはエラーメッセージの原文と、失敗した行の位置。移行ガイドの記述と一致しなかった箇所だけを記事に書く。
測る前に、書かないことも決めておく。所要時間・書き換えた行数・失敗件数は、測ってから書く。見込みで数字を置くと、後で直すときにどれが実測だったのか分からなくなる。破壊的変更を本番へ通す前の段取りは自作 MCP サーバを新仕様へ移した回で一度組んでいるので、順番はそちらを流用する。
httpx2 のライセンスは BSD-3-Clause
当サイトはライブラリ本体を配布しない。httpx2 は SDK の依存として入る形になるので、読者は公式の配布元から各自取得することになる。
ライセンスは配布元の LICENSE.md の条文を読んで確認した。BSD-3-Clause。著作権表示は Pydantic Services Inc. と、フォーク元 HTTPX の Encode OSS Ltd. の2つが併記されている。条項は、ソース再配布時の著作権表示の保持、バイナリ再配布時の表示の再現、そして著作権者と貢献者の名前を推奨や宣伝に使わないことの3つ。PyPI の分類子も OSI Approved :: BSD License になっている。
3条目があるので、この記事は「Pydantic が当サイトの使い方を推奨している」とは書かない。同梱して配る場合は、1条目と2条目の著作権表示の同梱義務が発生する。SDK の依存として入るだけなら、読者側で追加の作業は起きない。
移行手順を教える記事で、依存するライブラリの条項を確認せずに出す形は取らない。要約や「フォークだから元と同じはず」という推測ではなく、条文を読んで判断している。
一次ソース
- Claude API リリースノート(公式) — 2026年8月20日の項
- Migrating to v1(anthropic-sdk-python・公式) — 変更ごとの before / after
- httpx2 LICENSE.md — BSD-3-Clause の条文
関連記事
- 8月に並んだ5つの廃止期限を grep 2本で監査した回
- 自作 MCP サーバを 2026-07-28 仕様へ移す棚卸しと検証手順
- Claude API が会話途中の system メッセージに対応した回
- Claude Code 2.1.233 で Todo ツールが既定オフになった回
まとめ
今日やる価値があるのは、grep を7本走らせてヒット数を見るところまでだ。with_raw_response と AnthropicBedrock の2本を落とさないこと。目立つ6点だけを追うと、この2つが検索語に上がってこない。ヒットが0本でも「当たらなかった」の意味にはならない。早見表の9項目のうち8項目は grep の網の外にある。
ヒットが0本でも、上げた後に pyright か mypy を1回通す。移行ガイド自身が「型チェッカがほぼ全部をエラーとして出すので、普段回していなくてもチェックリストとして使える」と書いている。検索語を思いつけるかどうかに依存しない手が1つあるなら、そちらを主にする。
数字が出たなら、(a) から (d) の分類に落として作業量を見積もってから日を決める。上げる日を先に決めて当日に初めて影響範囲を調べる形は取らない。HTTP 層の入れ替えと引数の削除が同じリリースに入っているので、失敗したときに原因が2系統から来る。先に数えておけば、テストが赤くなったときにどちらの系統かをすぐ絞れる。
未検証のまま残したこと。v1.0 は手元に入れていないので、インストールの可否・型チェッカの指摘件数・テストの失敗件数・実呼び出しの結果はいずれも未実測になる。本稿のコード例は移行ガイドに載っている before / after をそのまま引いたもので、手元で走らせて確かめてはいない。extra_body でサンプリング引数を渡す形が、どのモデルまで有効かも確かめていない。