Anthropic Python SDK 1.0 Migration: By Hand or Claude Code

Moving a Python project from anthropic 0.x to 1.0 takes one install command, pip install --upgrade "anthropic>=1,<2", then a pass through a fixed list of breaking changes: the HTTP layer now runs on httpx2, the async .with_raw_response readers became coroutines, Text Completions and the temperature/top_p/top_k parameters are gone, and AnthropicBedrock refuses to construct without a region. Walk that list by hand with the official migration guide, or let Claude Code make the edits with /claude-api upgrade python and review the diff. Claude Code’s release note names it /claude-api upgrade; the migration guide adds the python argument, which is the form to type. Both routes end in the same place – the page below covers each, current as of anthropic 1.0.0 (released on PyPI August 20, 2026; checked August 25).

TL;DR

  • Upgrade with pip install --upgrade "anthropic>=1,<2", then run pyright or mypy: the migration guide notes that a type checker flags almost every breaking change, which makes it a ready-made checklist.
  • Python 3.10 is the new floor. Nothing else about your environment changes; the SDK still supports Pydantic v1 and v2.
  • httpx became httpx2. Plain values like timeout=30.0 keep working; httpx objects you hand to the client must come from httpx2, and libraries that patch httpx go blind until you call httpx2.alias_httpx().
  • Removed: Text Completions, sampling parameters, and schema dicts in output_format. client.completions.create(), temperature, top_p, and top_k are gone; schema dicts move to output_config={"format": {...}}.
  • Claude Code v2.1.239 (August 21, 2026) added /claude-api upgrade to migrate Python projects from anthropic 0.x to 1.x. Treat its output like any automated migration: read the diff before you commit it.

What Breaks When I Upgrade to anthropic 1.0?

Six changes carry most of the weight; I condense the guide’s quick reference to these six, and the smaller removals follow. The biggest one has a plain reason: the SDK’s HTTP layer moved from httpx, which is no longer actively maintained, to httpx2, an API-compatible fork maintained by the Pydantic team, with the same classes, the same behavior, and security fixes included.

Change How it surfaces Fix
Python 3.9 dropped Unsupported below 3.10 Upgrade to Python 3.10 or later
httpx replaced by httpx2 TypeError at construction when you pass an old httpx.Client; instrumentation goes blind import httpx2 as httpx; call httpx2.alias_httpx() for tracing and mocks
.with_raw_response returns APIResponse Async parse() / text() / json() / read() need await; .text and .content became methods await response.parse() / await response.text() on async; response.text() / response.read() on sync
Text Completions removed client.completions.create(), HUMAN_PROMPT, AI_PROMPT no longer exist Move to client.messages.create()
Deprecated parameters removed temperature, top_p, top_k raise TypeError; schema dicts in output_format raise too Remove them (or extra_body for older models); output_config={"format": {...}}
Bedrock region required AnthropicBedrock() raises ValueError with no region Pass aws_region= or set AWS_REGION

Smaller removals and one behavior change ride along, each with a replacement:

Removed or changed Use instead
messages.parse(stream=True) (which never worked) messages.stream(..., output_format=Order), then stream.get_final_message().parsed_output
tool_runner(compaction_control=...) Server-side compaction: betas=["compact-2026-01-12"] plus a context_management dict
Raw bytes as body= on client.get/post/put/patch/delete content=b"...", and cast_to=httpx2.Response in the same call
isinstance(x, Stream) for message streams from anthropic.lib.streaming import MessageStream; isinstance(x, MessageStream)
bytes header values .decode() them; header values must be str
BetaBase64PDFBlockParam BetaRequestDocumentBlockParam
anthropic.Transport / ProxiesTypes httpx2.BaseTransport / httpx2.Proxy / httpx2.AsyncBaseTransport
agent_toolset.READ_MAX_BYTES DEFAULT_MAX_FILE_BYTES
Two casings of one header name sent as two headers The later entry replaces the earlier, including headers the SDK sets itself; join the values yourself if you need both

The last row bites quietly: default_headers={"USER-AGENT": "my-app/1.0"} now replaces the SDK’s own User-Agent instead of sending both.

How Do I Migrate by Hand?

Three steps, in order: upgrade, let the type checker find the breakage, then fix by category.

pip install --upgrade "anthropic>=1,<2"
pyright   # or mypy

Fix the httpx imports first, because they fail loudest. The SDK’s own re-exports (anthropic.Timeout, anthropic.DefaultHttpxClient, anthropic.DefaultAsyncHttpxClient, anthropic.DefaultAioHttpClient) already point at httpx2 and keep working; only objects you build from httpx directly need the alias.

# 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  # or `import httpx2` and rename the references
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"),
    ),
)

If other code in the application still imports httpx and shares clients or exception types with the SDK, or if you run OpenTelemetry’s HTTPXClientInstrumentor, Sentry’s httpx integration, respx, pytest-httpx, or vcrpy, call httpx2.alias_httpx() once at the top of your entry point. It must run before anything imports httpx (it raises RuntimeError otherwise), and the guide reserves it for applications: a library should never call it on behalf of its users. Under pytest, the guide’s least intrusive option is an early plugin, a tests/_alias_httpx.py module that calls httpx2.alias_httpx(), registered in pyproject.toml so it loads ahead of respx, pytest-httpx, and your test modules:

# tests/_alias_httpx.py
import httpx2

httpx2.alias_httpx()  # makes `import httpx` / `import httpcore` resolve to httpx2 / httpcore2
# pyproject.toml
[tool.pytest.ini_options]
addopts = "-p tests._alias_httpx"
pythonpath = ["."]

Response and error objects are httpx2 types now. The package change applies to what the SDK returns, not only what you pass in. APIStatusError.response, APIConnectionError.request, response.http_response / .headers / .url on raw responses, and the response= argument your custom http_client event hooks receive are all httpx2 objects. They carry exactly the same attributes as before, so only isinstance checks and type annotations that name httpx.Response / httpx.Request / httpx.Headers need to switch to httpx2. The isinstance case deserves a second look. The guide says only that such checks must switch; the reason they matter is that, unless httpx2.alias_httpx() has made httpx resolve to httpx2, a check like isinstance(err.response, httpx.Response) against the old package returns False without raising, and the handler skips its branch.

# Before
def log_failure(err: anthropic.APIStatusError) -> None:
    response: httpx.Response = err.response
    print(response.status_code, response.headers.get("request-id"))


# After
def log_failure(err: anthropic.APIStatusError) -> None:
    response: httpx2.Response = err.response
    print(response.status_code, response.headers.get("request-id"))

Then the raw-response readers. .with_raw_response used to return LegacyAPIResponse for both clients; it now returns the same APIResponse / AsyncAPIResponse classes that .with_streaming_response already used.

LegacyAPIResponse (before) APIResponse (sync, after) AsyncAPIResponse (async, after)
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, .url, .request_id unchanged unchanged

Then the removed parameters. Current models do not use temperature, top_p, or top_k, so the generated methods no longer accept them. A model that predates the change still honors them through extra_body, which the SDK merges into the request JSON as-is.

# Before
client.messages.create(..., model="claude-sonnet-4-6", temperature=0.2)

# After
client.messages.create(..., model="claude-sonnet-4-6", extra_body={"temperature": 0.2})

Schema dicts move the same way: output_format={"type": "json_schema", "schema": ...} on beta.messages.create() becomes output_config={"format": {"type": "json_schema", "schema": ...}}; the parse() / stream() / count_tokens() / tool_runner() helpers keep output_format=Order for a class, and a schema dict there now raises TypeError.

Finish with Bedrock. AnthropicBedrock and AsyncAnthropicBedrock used to log a warning and fall back to us-east-1; they now raise ValueError at construction. The region resolves from aws_region=, then AWS_REGION / AWS_DEFAULT_REGION, then the boto3 session for the given aws_profile. The SDK also now skips unknown Bedrock streaming events it used to yield; the only known case is amazon-bedrock-invocationMetrics.

How Do I Migrate with Claude Code?

The migration guide itself names the shortcut: run /claude-api upgrade python in your project and review the diff. Claude Code v2.1.239, released August 21, 2026, is where the command landed; the release note reads, in full, “Added /claude-api upgrade to migrate Python projects from anthropic 0.x to 1.x, and updated the skill’s Python reference for 1.x (timeouts use anthropic.Timeout, not httpx.Timeout)”.

That sentence is the whole verified surface: a /claude-api skill command that migrates a project’s 0.x usage to 1.x. I have found no further documentation of how it chooses its edits, so treat it as exactly that: an automated migration whose diff you review. Update to v2.1.239 or later (claude update, or the install and update reference), open a session in the project root, and run it:

/claude-api upgrade python

Then read the diff hunk by hunk, run the type checker, and run the test suite – the same review you would give a contributor’s migration PR. The type-checker step matters more than usual here, because almost every 1.0 break is a type error, and that check does not care who made the edits. The one detail the release note calls out, anthropic.Timeout rather than httpx.Timeout, matches the guide: that re-export already points at httpx2.

By hand /claude-api upgrade python
Requires Migration guide, pyright or mypy Claude Code v2.1.239 or later
Who makes the edits You Claude Code, in your working tree
Review step Type checker plus tests Diff review, then type checker plus tests
My recommendation Small surface, or heavy custom httpx wiring Many call sites with mechanical changes

New to Claude Code? The quickstart covers the first session, and the full guide covers bundled skills and slash commands.

FAQ

Does anthropic 1.0 still support Pydantic v1?

Yes. The SDK still supports Pydantic v1 and v2; the Python 3.10 minimum is the only environment change.

Why does my OpenTelemetry or respx setup stop seeing SDK requests after upgrading?

Those libraries patch httpx, which the SDK no longer uses. Call httpx2.alias_httpx() before anything imports httpx; import httpx then resolves to httpx2 for the whole process.

Can I still pass temperature to an older model?

Yes, through extra_body={"temperature": 0.2}, which the SDK merges into the request JSON. For messages.batches.create(), put the key straight into the request’s params dict.

What replaced client-side compaction in tool_runner?

Server-side compaction: pass betas=["compact-2026-01-12"] and context_management={"edits": [{"type": "compact_20260112", "trigger": {"type": "input_tokens", "value": 100_000}}]} to tool_runner(). In the guide’s example, that pair replaces compaction_control={"enabled": True, "context_token_threshold": 100_000}; the trigger threshold must be at least 50,000 tokens.

Do I need to drop httpx_aiohttp from requirements?

Yes. anthropic[aiohttp] and http_client=DefaultAioHttpClient() work as before, but the extra no longer installs httpx_aiohttp because it now ships inside the SDK.

Key Takeaways

For application developers: - Pin "anthropic>=1,<2", run the type checker, and fix by category, in this order: httpx imports, raw-response awaits, removed parameters, Bedrock region. - Put httpx2.alias_httpx() in the first lines of the entry point if anything else in the process shares httpx objects with the SDK or instruments httpx.

For library maintainers: - Never call httpx2.alias_httpx() inside a library; alias the import (import httpx2 as httpx) instead. - Drop anthropic.Transport / ProxiesTypes in favor of httpx2.BaseTransport / httpx2.Proxy.

For teams using Claude Code: - Update to v2.1.239 or later and run /claude-api upgrade python from the project root; review the diff, then run the type checker and tests before committing.

References

  1. Anthropic, “Migrating to v1”, anthropic-sdk-python MIGRATION.md: upgrade command, Python 3.10 floor, httpx2, .with_raw_response classes, removed APIs and parameters, Bedrock changes, and the /claude-api upgrade python pointer. Verified 2026-08-25.
  2. PyPI, anthropic: 1.0.0 released August 20, 2026; still the latest release as of 2026-08-25.
  3. Anthropic, Claude Code v2.1.239 release notes, August 21, 2026: “Added /claude-api upgrade to migrate Python projects from anthropic 0.x to 1.x, and updated the skill’s Python reference for 1.x (timeouts use anthropic.Timeout, not httpx.Timeout)”.
添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论