XT.PT The SDK → This story
Analysis The SDK

Anthropic's Python SDK v1.0 moves off httpx, and the reason is maintenance

A supply-chain event dressed as a version bump — plus the one-line call that stops your test mocks from silently missing every request.

Anthropic

The Anthropic Python SDK reached v1.0 on 2026-08-20, and the headline change is not an API feature. It is the HTTP client underneath. Per the platform release notes: "The SDK's HTTP layer moves from httpx to httpx2, a maintained, API-compatible fork".

For anyone who has ever pinned a transitive dependency to keep a build reproducible, that sentence is the interesting part of the release.

Why the fork exists

The SDK's own migration guide gives the reason without hedging: "The SDK's HTTP layer moved from httpx, which is no longer actively maintained, to httpx2".

httpx2's documentation says the same thing from the other side. It describes itself as "A next-generation HTTP client for Python" that "provides sync and async APIs, and support for both HTTP/1.1 and HTTP/2" — the httpx pitch, unchanged — and then explains the handover: "With HTTPX itself seeing limited activity recently, Pydantic is picking up stewardship under the HTTPX2 name so that users have a reliably maintained path forward."

So the shape of this is: a widely used async HTTP client goes quiet, Pydantic forks it under a new name and takes on maintenance, and one of the larger SDK vendors moves its wire layer onto the fork in a major version. That is a supply-chain event dressed as a version bump. httpx sits under a large amount of Python tooling; a vendor SDK moving off it is a signal about the upstream, and it is worth asking what else in your dependency tree is still on the original.

What breaks in your code

The move is API-compatible, but not name-compatible. If you construct any of the HTTP objects yourself, they now have to come from the new package:

# Before
import httpx
client = Anthropic(http_client=httpx.Client(proxy="http://127.0.0.1:8080"))

# After
import httpx2
client = Anthropic(http_client=httpx2.Client(proxy="http://127.0.0.1:8080"))

The release notes are specific about the scope: "build custom http_client, Timeout, and transport objects from httpx2 (the DefaultHttpxClient helpers are unchanged)". The helper names stayed, so code that only used DefaultHttpxClient is untouched.

The subtler trap is monkeypatching. Test suites and tracing libraries routinely patch httpx by module name — respx, VCR-style recorders, and most APM auto-instrumentation all work that way. Those patches now attach to a module the SDK no longer calls, which fails in the worst possible manner: the tests still pass, the traces are still emitted, and neither of them is watching the requests any more. The release notes provide the escape hatch: "call httpx2.alias_httpx() at startup if you rely on tracing or mocking libraries that patch httpx."

If you have request-level mocks in CI, that one line is the difference between a test suite that mocks the network and a test suite that quietly hits it.

Three removals with teeth

v1.0 also drops long-deprecated surface. The release notes list "the legacy Text Completions API, the temperature, top_p, and top_k parameters on Messages methods, and the tool runner's client-side compaction_control."

The Text Completions removal takes /v1/complete with it, along with the Completion and CompletionCreateParams types and the HUMAN_PROMPT and AI_PROMPT constants. Any code still assembling prompts by string concatenation around those constants stops compiling rather than stops working, which is the right failure.

The sampling-parameter removal is the one likely to bite hardest, because passing temperature=0 is muscle memory for anyone who wants deterministic-ish output. It is gone from the method signature, not deprecated in it. The migration guide's documented workaround is to route it through the passthrough for models that still accept it: extra_body={"temperature": 0.2}.

Note what that implies. The parameter is not being rejected by the API for every model — it is being removed from the typed surface of the SDK, which is a statement about what the current models are built to accept. Reaching for extra_body is the guide's own answer for "older models requiring these," and it is also a reasonable smoke alarm: if your call needs extra_body to keep working, you are calling a model generation the SDK has stopped shaping itself around.

The migration guide's own before-and-after example bundles the sampling removal with an unrelated rename, which is a good illustration of how much a major-version bump can move at once:

# Before
client.messages.create(..., temperature=0.2, output_format={"type": "json_schema"})

# After
client.messages.create(..., output_config={"format": {"type": "json_schema"}})

The third removal, compaction_control= on tool_runner(), points the same direction: client-side context compaction gives way to server-side context_management. Long-running agent loops that manage their own context trimming in the client have a migration to do, not just a rename.

The silent default that is now an error

The change most likely to surface in production is the smallest one. On Bedrock, per the release notes, "AnthropicBedrock now raises an error when no AWS region is configured instead of defaulting to us-east-1." The migration guide names the exception — ValueError — and the two ways to satisfy it: the aws_region= argument or the AWS_REGION environment variable.

This is a strictly better behavior and it will still cause an outage somewhere. Any deployment that has been quietly running in us-east-1 because nobody set the region — a container that lost its env file, a cron job that never inherited one, a laptop script promoted to a server — now fails at client construction instead of succeeding in a region the operator did not choose. That is the correct trade: a silent default that happens to be a data-residency decision is a bug, and turning it into a startup error is how you find out where you have one.

For anyone tracking residency for real, that default was worse than untidy. us-east-1 is a US region, and an implicit fallback into it is a compliance answer nobody wrote down.

Two more mechanical notes: v1.0 requires Python 3.10 or later, up from 3.9. And on the async client, raw responses now need awaiting — await response.parse(), await response.text(), and await response.read(), the last replacing .content.

Before you bump

The upgrade is cheap for straightforward call sites and non-trivial for anything that touches the transport. In rough order: check whether anything in your test or observability stack patches httpx by name and add alias_httpx() if so; grep for temperature, top_p, and top_k on Messages calls; grep for AnthropicBedrock without an explicit region; confirm your floor is Python 3.10; and audit async with_raw_response uses for the missing await.

Then do the wider check the release invites: httpx being "no longer actively maintained" is a fact about your whole dependency tree, not just about one SDK.

Primary sources: Claude Platform release notes, anthropic-sdk-python MIGRATION.md, HTTPX2 documentation, read 2026-08-25.

Corrections and source documents: contact the desk
Read next →
Read next
Pricing · 5 min

The price rise that won't happen, and the one already on the calendar

Provenance · 5 min

Claude's text watermark ships before the API that reads it