On August 20, 2026, the anthropic package on PyPI went from 0.x to 1.0.0. The release notes said one thing: upgraded to httpx2, breaking changes, see MIGRATION.md. Within hours, teams running pydantic-ai on top of it started seeing runtime failures that had nothing to do with their own code — every pydantic-ai release up to that day declared compatibility with anthropic>=0.7,<2.0 and let the new major version install without actually supporting it. The fix, pydantic-ai v2.33.0, shipped the same day. For anyone whose lockfile updated between those two releases, the gap was a few hours; for anyone on a loose version range who happened to rebuild an image or run a fresh pip install in that window, it was a broken deploy with no code change to point to.
This is the exact failure mode a coding agent can’t see coming on its own. Claude Code has no way to know that anthropic==1.0.0 shipped that week, that it swapped HTTP libraries, or that a downstream package it’s never heard of had a same-day compatibility gap — unless the project’s CLAUDE.md says so. Browse more real-world CLAUDE.md and AGENTS.md examples in our gallery.
What Actually Broke, in Order
The timeline matters because it’s shorter than most teams’ release cadence:
- August 20, 2026, morning — Anthropic ships
anthropicv1.0.0. The headline change is a rebuild of the SDK’s HTTP transport onhttpx2, a Pydantic-maintained fork of the no-longer-actively-maintainedhttpx. The release also removes a list of parameters and types that had been deprecated for months. - Same day — every published
pydantic-aiversion’s dependency spec (anthropic>=0.7,<2.0) is technically satisfied by 1.0.0, sopip installanduv synchappily resolve to it. Nothing in the metadata says the two are actually incompatible. - Same day, hours later —
pydantic-aiv2.33.0 ships with the fix and a tightened constraint. Anyone who resolves dependencies after this point gets a working combination without knowing anything happened.
Nobody involved shipped bad code. The anthropic SDK did what a major version bump is supposed to do — signal a breaking change and document it. pydantic-ai’s version range was reasonable when it was written and wrong for exactly one day. The failure was purely a timing gap in an ecosystem where three independent teams (Anthropic, Pydantic, and whoever’s CI ran pip install in that window) all had to line up, and didn’t.
The httpx → httpx2 Change Isn’t a Rename
The part of the migration most likely to actually break code isn’t a config tweak — it’s that httpx2 is a separate package, and existing httpx objects don’t get automatically converted:
# Before (anthropic 0.x)
import httpx
from anthropic import Anthropic
client = Anthropic(
timeout=httpx.Timeout(60.0, connect=5.0),
http_client=httpx.Client(proxy="http://my.proxy.example"),
)
# After (anthropic 1.0+)
import httpx2 as httpx
from anthropic import Anthropic
client = Anthropic(
timeout=httpx.Timeout(60.0, connect=5.0),
http_client=httpx.Client(proxy="http://my.proxy.example"),
)
If a project only ever passes plain values (timeout=30.0, max_retries=3, and so on), there’s genuinely nothing to change — the SDK handles the transport internally. The break only shows up for code that constructs its own httpx.Client, passes a custom transport, or inspects response objects the SDK hands back (error handlers that read err.response, for instance, now get an httpx2.Response, not an httpx.Response, and isinstance checks against the old type silently stop matching). Tracing and mocking libraries — OpenTelemetry instrumentation, respx, pytest-httpx, vcrpy — are in the same boat if they patch httpx directly rather than going through the SDK’s public surface. Anthropic’s own workaround for that case is a module-level alias that has to run before any other import:
# At the very top of the entry point, before anything else imports httpx
import httpx2
httpx2.alias_httpx() # makes `import httpx` resolve to httpx2
This is the kind of line that’s easy to add once someone hits the failure and impossible for an agent to think to add before that, because nothing about a normal AnthropicProvider setup hints that the transport library changed underneath it.
Everything Else v1.0 Removed
The httpx2 migration is the headline, but it’s not the only breaking change in the release, and several of the others are exactly the kind of thing training data still confidently suggests:
| Removed in v1.0 | What used to work | Replacement |
|---|---|---|
client.completions.create() | The legacy /v1/complete text-completion endpoint | client.messages.create() |
anthropic.HUMAN_PROMPT / anthropic.AI_PROMPT | String constants for manually formatting completion prompts | Not needed with the Messages API |
temperature, top_p, top_k as direct kwargs on messages.create/stream/parse | Passing sampling params straight into the call | extra_body={"temperature": 0.2}, or omit |
output_format (dict form) on beta.messages.create() | Raw dict for structured output config | output_config={"format": {...}} |
anthropic.Transport, anthropic.ProxiesTypes | Type aliases re-exported from httpx | httpx2.BaseTransport, httpx2.Proxy |
isinstance(obj, anthropic.Stream) matching message streams | A working type check for stream objects | isinstance(obj, anthropic.lib.streaming.MessageStream) |
Implicit us-east-1 fallback in AnthropicBedrock() | Working code with no region specified | Explicit aws_region= or AWS_REGION env var (now raises ValueError if missing) |
| Python 3.9 support | Installing on 3.9 | Python 3.10+ required |
The HUMAN_PROMPT/AI_PROMPT removal is worth calling out specifically: those constants show up in years of blog posts, Stack Overflow answers, and tutorials predating the Messages API, which means they’re still in a lot of training data as “how you call Claude.” A coding agent asked to “add a Claude API call” with no other context has a real chance of reaching for a pattern that hasn’t worked since the Completions API was deprecated, let alone since it was deleted outright in this release. The Bedrock region change is its own trap in the opposite direction — code that worked fine for years by omitting the region now throws at construction time, which reads like a bug in the calling code rather than a version bump, unless someone remembers this release happened.
Why AI Agent Projects Hit This Harder Than Most
Two things about how coding agents work with dependencies make this specific kind of break more likely, not less:
Agents default to permissive version ranges unless told not to. Asked to add a package, the reflex is anthropic>=0.34 or no upper bound at all — it’s the more “correct-looking” choice in isolation, and it’s exactly the shape that let pydantic-ai’s old constraint through unmodified. A human maintainer who remembers “we pinned this once for a reason” is a safeguard an agent doesn’t have unless it’s written down.
Agents suggest upgrades as routine maintenance. “Your dependencies are out of date, want me to bump them?” is a helpful, common suggestion — and for a project sitting on anthropic==0.9x with no context, bumping straight to 1.0 looks like a clean patch, not a major-version jump that also happens to change the HTTP transport underneath every request the app makes. Nothing about the version string signals “check MIGRATION.md first” unless CLAUDE.md says to check.
Neither behavior is wrong in general — permissive ranges and routine upgrades are normal, reasonable defaults. They’re just the wrong defaults for a package whose major version bumps have, twice now, come with an HTTP transport change (httpx itself was a breaking addition when the SDK first adopted it years ago) and no changelog line calling that out explicitly.
The CLAUDE.md Rules This Actually Needs
None of the above requires avoiding upgrades — it requires making the upgrade a decision instead of a default. A minimal block that covers the specific failure mode above:
## Anthropic Python SDK (`anthropic` package)
- Current pinned range: `anthropic>=1.0.0,<2.0.0` (upgraded from 0.x on [date]).
Do not widen this range without reading MIGRATION.md at
https://github.com/anthropics/anthropic-sdk-python/blob/main/MIGRATION.md first.
- This project is on the v1.x line: the HTTP transport is `httpx2`, not `httpx`.
Any code that constructs an `httpx.Client`, inspects `err.response`, or does
`isinstance(x, anthropic.Stream)` needs the v1.x equivalents
(`httpx2.Client`, `httpx2.Response`, `anthropic.lib.streaming.MessageStream`).
- Do not suggest `anthropic.HUMAN_PROMPT`, `anthropic.AI_PROMPT`, or
`client.completions.create()` — the legacy Completions API was removed in v1.0.
Use `client.messages.create()`.
- If `pydantic-ai` is a dependency, keep it pinned to `>=2.33.0` — earlier
releases do not correctly constrain against `anthropic` v1.x and will
install a broken combination.
- Minimum Python version for this dependency is 3.10 (raised from 3.9 in v1.0).
- Before bumping this package's major version, flag it as a decision for
the user, not a routine dependency update — check whether any breaking
change in the target version's MIGRATION.md affects code in this repo.
Pair that with a settings.json guard that keeps an agent from resolving its way around the intent of the pin:
{
"permissions": {
"deny": [
"Bash(pip install --upgrade anthropic*)",
"Bash(pip install -U anthropic*)"
]
}
}
That deny rule doesn’t block a deliberate, reviewed upgrade — it blocks the specific one-liner an agent reaches for when “update my dependencies” is interpreted literally, which is the exact path that turns a routine request into an unplanned major-version jump.
If the project uses Claude Agent SDK rather than calling the anthropic package directly, note that distinction in CLAUDE.md too — they’re separate PyPI packages with separate release cadences, and “the Anthropic SDK” is ambiguous enough that an agent (or a teammate) can update the wrong one while debugging the right problem. The gallery’s Claude Agent SDK Python rules are a good reference for how that project structures its own agent-facing conventions, separate from the raw API client covered here.
Common Mistakes
Treating the 1.0.0 version bump as “just a stability milestone.” GitHub’s own release notes for this version undersell it that way — no enumerated breaking-changes list, just a pointer to MIGRATION.md. Skipping that file because the release notes read as low-key is how the httpx2 transport change gets missed.
Pinning anthropic but not pydantic-ai (or vice versa) when both are dependencies. The incident this article is built around happened specifically because one package’s constraint didn’t account for the other’s release. Pinning only one side of an integration doesn’t close that gap — it just changes which side breaks first.
Assuming isinstance(x, anthropic.Stream) still detects message streams. It’s the kind of check that fails silently — no exception, just a branch that stops being taken — and shows up as “the app didn’t do the thing it used to do” rather than a clear error pointing at the SDK version.
Leaving AnthropicBedrock() with no explicit region because it worked before. The implicit us-east-1 fallback is gone; this now raises ValueError at client construction, which is easy to mistake for an unrelated config bug if nobody remembers this release changed it.
None of this is a reason to pin anthropic forever and never upgrade — the SDK is actively maintained, and staying several major versions behind creates its own problems. It’s a reason to make the upgrade decision explicit in CLAUDE.md rather than letting an agent (or a CI job, or a fresh pip install on a bad day) make it implicitly, because the one thing this incident demonstrates is that “the version range is satisfied” and “the combination actually works” can diverge for hours at a time, in an ecosystem an agent has no visibility into beyond what the project tells it.
Browse more real dependency-management, migration, and framework-specific CLAUDE.md/AGENTS.md examples in our gallery.
FAQ
What actually broke when anthropic hit v1.0.0?
The headline change was a rebuild of the SDK’s HTTP transport from httpx to httpx2, a Pydantic-maintained fork. The release also removed the legacy Completions API (client.completions.create(), HUMAN_PROMPT/AI_PROMPT), several deprecated parameters (temperature/top_p/top_k as direct kwargs), some type aliases, and raised the minimum Python version from 3.9 to 3.10.
What was the pydantic-ai incident, specifically?
Every pydantic-ai release up to August 20, 2026 declared a dependency constraint that allowed anthropic v1.0.0 to install, without actually supporting the new httpx2-based transport. Unpinned or freshly resolved installs during that window could fail at runtime against Anthropic models. pydantic-ai v2.33.0, released the same day, corrected the constraint.
Do I need to change my code for the httpx2 migration?
Only if it touches the transport layer directly — constructing your own httpx.Client/http_client, inspecting response objects from error handlers, or using isinstance checks against SDK-exported httpx types. Code that only passes plain values like timeout=30.0 or max_retries=3 needs no changes.
Is the legacy Completions API really gone?
Yes, as of v1.0.0. client.completions.create(), the Completion/CompletionCreateParams types, and the HUMAN_PROMPT/AI_PROMPT constants are all removed. Use client.messages.create() instead — this has been the recommended path for years, but the old API only stopped working at this release.
What’s the single most useful CLAUDE.md rule from this incident?
Pin the package to an explicit range tied to a known-good migration, note which major line the transport layer is on (httpx vs httpx2), and flag major-version bumps of this specific package as a decision requiring MIGRATION.md review rather than a routine update — because the failure mode here wasn’t bad code on either side, it was an agent (or a script) treating a major-version bump as routine.