Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
version: '0.9.13'
version: '0.10.2'

- name: Install dependencies
run: uv sync --all-extras
Expand All @@ -46,7 +46,7 @@ jobs:
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
version: '0.9.13'
version: '0.10.2'

- name: Install dependencies
run: uv sync --all-extras
Expand All @@ -55,14 +55,18 @@ jobs:
run: uv build

- name: Get GitHub OIDC Token
if: github.repository == 'stainless-sdks/anthropic-python'
if: |-
github.repository == 'stainless-sdks/anthropic-python' &&
!startsWith(github.ref, 'refs/heads/stl/')
id: github-oidc
uses: actions/github-script@v8
with:
script: core.setOutput('github_token', await core.getIDToken());

- name: Upload tarball
if: github.repository == 'stainless-sdks/anthropic-python'
if: |-
github.repository == 'stainless-sdks/anthropic-python' &&
!startsWith(github.ref, 'refs/heads/stl/')
env:
URL: https://pkg.stainless.com/s
AUTH: ${{ steps.github-oidc.outputs.github_token }}
Expand All @@ -80,7 +84,7 @@ jobs:
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
version: '0.9.13'
version: '0.10.2'

- name: Bootstrap
run: ./scripts/bootstrap
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/detect-breaking-changes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
version: '0.9.13'
version: '0.10.2'
- name: Install dependencies
run: uv sync --all-extras
- name: Detect removed symbols
Expand Down
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.84.0"
".": "0.85.0"
}
6 changes: 3 additions & 3 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 34
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic%2Fanthropic-60fbf504538934c934f523d456bbf3cd99e7f1e2275041f74d5beb627bf38e19.yml
openapi_spec_hash: 58021ab18daccd5c45a930ffd7d6ab4d
config_hash: bf86c14604e5705bfb2f351adf702c02
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic%2Fanthropic-7fce94a3c9f72c1d81df2009682a3b554e4b641b32443fd7c1f09f566420f711.yml
openapi_spec_hash: ae7e30bb8d093b5546cdc2b180f7b8e0
config_hash: 32f037e4bc66dfaca12016b0e5110140
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
# Changelog

## 0.85.0 (2026-03-16)

Full Changelog: [v0.84.0...v0.85.0](https://github.com/anthropics/anthropic-sdk-python/compare/v0.84.0...v0.85.0)

### Features

* **api:** chore(config): clean up model enum list ([#31](https://github.com/anthropics/anthropic-sdk-python/issues/31)) ([cce1a5b](https://github.com/anthropics/anthropic-sdk-python/commit/cce1a5b9e6fce4f269cec42803f37ce5e2ac2f76))
* **api:** GA thinking-display-setting ([207340c](https://github.com/anthropics/anthropic-sdk-python/commit/207340cc621855928f53e8ddd58f216ac0d8150d))
* **tests:** update mock server ([7dc86a4](https://github.com/anthropics/anthropic-sdk-python/commit/7dc86a4ffc9e70533a58065496c78394c6a6e97a))


### Bug Fixes

* **client:** add missing 413 and 529 error handlers to async client ([#1554](https://github.com/anthropics/anthropic-sdk-python/issues/1554)) ([9c2986f](https://github.com/anthropics/anthropic-sdk-python/commit/9c2986fb9c046b4cffa1b03ca8762f9c9dea0bab))
* **tool runner:** propagate container_id for programmatic tool calling ([#1462](https://github.com/anthropics/anthropic-sdk-python/issues/1462)) ([3ae7ff6](https://github.com/anthropics/anthropic-sdk-python/commit/3ae7ff6ff7af8a881706ae8068b1040a23c96fbd))
* **tools:** use filtered messages list in async compaction ([#1124](https://github.com/anthropics/anthropic-sdk-python/issues/1124)) ([710d666](https://github.com/anthropics/anthropic-sdk-python/commit/710d666f80b7667e3551c1a68d7c0ffaad115de1))


### Chores

* **ci:** bump uv version ([09656ac](https://github.com/anthropics/anthropic-sdk-python/commit/09656acef77fa459d30d811bd51aa780a567182b))
* **internal:** codegen related update ([c9e9fc2](https://github.com/anthropics/anthropic-sdk-python/commit/c9e9fc240334fc466426646d7acd64904f881a80))
* **internal:** codegen related update ([77f77d1](https://github.com/anthropics/anthropic-sdk-python/commit/77f77d19b4657a7ad0d31de42504c25cf4ed76ef))
* **tests:** unskip tests that are now supported in steady ([827330b](https://github.com/anthropics/anthropic-sdk-python/commit/827330b527b4af299af084752a7317b0596956af))

## 0.84.0 (2026-02-25)

Full Changelog: [v0.83.0...v0.84.0](https://github.com/anthropics/anthropic-sdk-python/compare/v0.83.0...v0.84.0)
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ $ pip install ./path-to-wheel-file.whl

## Running tests

Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests.
Most tests require you to [set up a mock server](https://github.com/dgellow/steady) against the OpenAPI spec to run the tests.

```sh
$ ./scripts/mock
Expand Down
2 changes: 2 additions & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ from anthropic.types import (
WebFetchBlockParam,
WebFetchTool20250910,
WebFetchTool20260209,
WebFetchTool20260309,
WebFetchToolResultBlock,
WebFetchToolResultBlockParam,
WebFetchToolResultErrorBlock,
Expand Down Expand Up @@ -453,6 +454,7 @@ from anthropic.types.beta import (
BetaWebFetchBlockParam,
BetaWebFetchTool20250910,
BetaWebFetchTool20260209,
BetaWebFetchTool20260309,
BetaWebFetchToolResultBlock,
BetaWebFetchToolResultBlockParam,
BetaWebFetchToolResultErrorBlock,
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "anthropic"
version = "0.84.0"
version = "0.85.0"
description = "The official Python library for the anthropic API"
dynamic = ["readme"]
license = "MIT"
Expand Down
31 changes: 21 additions & 10 deletions scripts/mock
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,34 @@ fi

echo "==> Starting mock server with URL ${URL}"

# Run prism mock on the given spec
# Run steady mock on the given spec
if [ "$1" == "--daemon" ]; then
npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log &
# Pre-install the package so the download doesn't eat into the startup timeout
npm exec --package=@stdy/cli@0.19.3 -- steady --version

# Wait for server to come online
npm exec --package=@stdy/cli@0.19.3 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-query-object-format=brackets "$URL" &> .stdy.log &

# Wait for server to come online via health endpoint (max 30s)
echo -n "Waiting for server"
while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do
attempts=0
while ! curl --silent --fail "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1; do
if ! kill -0 $! 2>/dev/null; then
echo
cat .stdy.log
exit 1
fi
attempts=$((attempts + 1))
if [ "$attempts" -ge 300 ]; then
echo
echo "Timed out waiting for Steady server to start"
cat .stdy.log
exit 1
fi
echo -n "."
sleep 0.1
done

if grep -q "✖ fatal" ".prism.log"; then
cat .prism.log
exit 1
fi

echo
else
npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL"
npm exec --package=@stdy/cli@0.19.3 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-query-object-format=brackets "$URL"
fi
16 changes: 8 additions & 8 deletions scripts/test
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color

function prism_is_running() {
curl --silent "http://localhost:4010" >/dev/null 2>&1
function steady_is_running() {
curl --silent "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1
}

kill_server_on_port() {
Expand All @@ -25,7 +25,7 @@ function is_overriding_api_base_url() {
[ -n "$TEST_API_BASE_URL" ]
}

if ! is_overriding_api_base_url && ! prism_is_running ; then
if ! is_overriding_api_base_url && ! steady_is_running ; then
# When we exit this script, make sure to kill the background mock server process
trap 'kill_server_on_port 4010' EXIT

Expand All @@ -36,19 +36,19 @@ fi
if is_overriding_api_base_url ; then
echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}"
echo
elif ! prism_is_running ; then
echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server"
elif ! steady_is_running ; then
echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Steady server"
echo -e "running against your OpenAPI spec."
echo
echo -e "To run the server, pass in the path or url of your OpenAPI"
echo -e "spec to the prism command:"
echo -e "spec to the steady command:"
echo
echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}"
echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.3 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-query-object-format=brackets${NC}"
echo

exit 1
else
echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}"
echo -e "${GREEN}✔ Mock steady server is running with your OpenAPI spec${NC}"
echo
fi

Expand Down
6 changes: 6 additions & 0 deletions src/anthropic/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,12 +513,18 @@ def _make_status_error(
if response.status_code == 409:
return _exceptions.ConflictError(err_msg, response=response, body=body)

if response.status_code == 413:
return _exceptions.RequestTooLargeError(err_msg, response=response, body=body)

if response.status_code == 422:
return _exceptions.UnprocessableEntityError(err_msg, response=response, body=body)

if response.status_code == 429:
return _exceptions.RateLimitError(err_msg, response=response, body=body)

if response.status_code == 529:
return _exceptions.OverloadedError(err_msg, response=response, body=body)

if response.status_code >= 500:
return _exceptions.InternalServerError(err_msg, response=response, body=body)
return APIStatusError(err_msg, response=response, body=body)
Expand Down
2 changes: 1 addition & 1 deletion src/anthropic/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

__title__ = "anthropic"
__version__ = "0.84.0" # x-release-please-version
__version__ = "0.85.0" # x-release-please-version
11 changes: 7 additions & 4 deletions src/anthropic/lib/tools/_beta_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ class ToolError(Exception):

Example::

raise ToolError([
{"type": "text", "text": "Error details here"},
{"type": "image", "source": {"type": "base64", "data": "...", "media_type": "image/png"}},
])
raise ToolError(
[
{"type": "text", "text": "Error details here"},
{"type": "image", "source": {"type": "base64", "data": "...", "media_type": "image/png"}},
]
)
"""

content: BetaFunctionToolResultType
Expand All @@ -55,6 +57,7 @@ def __init__(self, content: BetaFunctionToolResultType) -> None:
super().__init__(message)
self.content = content


Function = Callable[..., BetaFunctionToolResultType]
FunctionT = TypeVar("FunctionT", bound=Function)

Expand Down
38 changes: 32 additions & 6 deletions src/anthropic/lib/tools/_beta_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ def append_messages(self, *messages: BetaMessageParam | ParsedBetaMessage[Respon
for message in messages
]
self._messages_modified = True
self.set_messages_params(lambda params: {**params, "messages": [*self._params["messages"], *message_params]})
self.set_messages_params(
lambda params: {**params, "messages": [*params["messages"], *message_params]}
)
self._cached_tool_call_response = None

def _should_stop(self) -> bool:
Expand Down Expand Up @@ -255,6 +257,11 @@ def __run__(self) -> Iterator[RunnerItemT]:
message = self._get_last_message()
assert message is not None

# Update container from response for programmatic tool calling support
last_assistant_message = self._get_last_assistant_message()
if last_assistant_message is not None and last_assistant_message.container is not None:
self._params["container"] = last_assistant_message.container.id

self._iteration_count += 1

# If the compaction was performed, skip tool call generation this iteration
Expand Down Expand Up @@ -356,12 +363,19 @@ def _get_last_message(self) -> ParsedBetaMessage[ResponseFormatT] | None:
return self._last_message()
return self._last_message

def _get_last_assistant_message_content(self) -> list[ParsedBetaContentBlock[ResponseFormatT]] | None:
def _get_last_assistant_message(self) -> ParsedBetaMessage[ResponseFormatT] | None:
last_message = self._get_last_message()
if last_message is None or last_message.role != "assistant" or not last_message.content:
return None

return last_message.content
return last_message

def _get_last_assistant_message_content(self) -> list[ParsedBetaContentBlock[ResponseFormatT]] | None:
last_assistant_message = self._get_last_assistant_message()
if last_assistant_message is None:
return None

return last_assistant_message.content


class BetaToolRunner(BaseSyncToolRunner[ParsedBetaMessage[ResponseFormatT], ResponseFormatT]):
Expand Down Expand Up @@ -469,7 +483,7 @@ async def _check_and_compact(self) -> bool:
messages.pop()

messages = [
*self._params["messages"],
*messages,
BetaMessageParam(
role="user",
content=self._compaction_control.get("summary_prompt", DEFAULT_SUMMARY_PROMPT),
Expand Down Expand Up @@ -515,6 +529,11 @@ async def __run__(self) -> AsyncIterator[RunnerItemT]:
message = await self._get_last_message()
assert message is not None

# Update container from response for programmatic tool calling support
last_assistant_message = await self._get_last_assistant_message()
if last_assistant_message is not None and last_assistant_message.container is not None:
self._params["container"] = last_assistant_message.container.id

self._iteration_count += 1

# If the compaction was performed, skip tool call generation this iteration
Expand Down Expand Up @@ -560,12 +579,19 @@ async def _get_last_message(self) -> ParsedBetaMessage[ResponseFormatT] | None:
return await self._last_message()
return self._last_message

async def _get_last_assistant_message_content(self) -> list[ParsedBetaContentBlock[ResponseFormatT]] | None:
async def _get_last_assistant_message(self) -> ParsedBetaMessage[ResponseFormatT] | None:
last_message = await self._get_last_message()
if last_message is None or last_message.role != "assistant" or not last_message.content:
return None

return last_message.content
return last_message

async def _get_last_assistant_message_content(self) -> list[ParsedBetaContentBlock[ResponseFormatT]] | None:
last_assistant_message = await self._get_last_assistant_message()
if last_assistant_message is None:
return None

return last_assistant_message.content

async def _generate_tool_call_response(self) -> BetaMessageParam | None:
content = await self._get_last_assistant_message_content()
Expand Down
1 change: 1 addition & 0 deletions src/anthropic/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
from .tool_search_tool_result_error import ToolSearchToolResultError as ToolSearchToolResultError
from .web_fetch_tool_20250910_param import WebFetchTool20250910Param as WebFetchTool20250910Param
from .web_fetch_tool_20260209_param import WebFetchTool20260209Param as WebFetchTool20260209Param
from .web_fetch_tool_20260309_param import WebFetchTool20260309Param as WebFetchTool20260309Param
from .web_search_result_block_param import WebSearchResultBlockParam as WebSearchResultBlockParam
from .thinking_config_adaptive_param import ThinkingConfigAdaptiveParam as ThinkingConfigAdaptiveParam
from .thinking_config_disabled_param import ThinkingConfigDisabledParam as ThinkingConfigDisabledParam
Expand Down
1 change: 1 addition & 0 deletions src/anthropic/types/beta/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
from .beta_tool_search_tool_result_error import BetaToolSearchToolResultError as BetaToolSearchToolResultError
from .beta_web_fetch_tool_20250910_param import BetaWebFetchTool20250910Param as BetaWebFetchTool20250910Param
from .beta_web_fetch_tool_20260209_param import BetaWebFetchTool20260209Param as BetaWebFetchTool20260209Param
from .beta_web_fetch_tool_20260309_param import BetaWebFetchTool20260309Param as BetaWebFetchTool20260309Param
from .beta_web_search_result_block_param import BetaWebSearchResultBlockParam as BetaWebSearchResultBlockParam
from .beta_compaction_content_block_delta import BetaCompactionContentBlockDelta as BetaCompactionContentBlockDelta
from .beta_thinking_config_adaptive_param import BetaThinkingConfigAdaptiveParam as BetaThinkingConfigAdaptiveParam
Expand Down
7 changes: 5 additions & 2 deletions src/anthropic/types/beta/beta_iterations_usage.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

from typing import List, Union
from typing_extensions import TypeAlias
from typing_extensions import Annotated, TypeAlias

from ..._utils import PropertyInfo
from .beta_message_iteration_usage import BetaMessageIterationUsage
from .beta_compaction_iteration_usage import BetaCompactionIterationUsage

__all__ = ["BetaIterationsUsage", "BetaIterationsUsageItem"]

BetaIterationsUsageItem: TypeAlias = Union[BetaMessageIterationUsage, BetaCompactionIterationUsage]
BetaIterationsUsageItem: TypeAlias = Annotated[
Union[BetaMessageIterationUsage, BetaCompactionIterationUsage], PropertyInfo(discriminator="type")
]

BetaIterationsUsage: TypeAlias = List[BetaIterationsUsageItem]
Loading
Loading