Skip to content

Commit 939d1d9

Browse files
committed
Add web search pause turn example
1 parent 04b468d commit 939d1d9

2 files changed

Lines changed: 83 additions & 0 deletions

File tree

examples/web_search_pause_turn.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from __future__ import annotations
2+
3+
from anthropic import Anthropic
4+
from anthropic.types import Message, MessageParam
5+
6+
client = Anthropic()
7+
8+
9+
def assistant_turn_from_message(message: Message) -> MessageParam:
10+
"""Preserve paused server-tool blocks exactly as the SDK returned them."""
11+
return {"role": "assistant", "content": message.content}
12+
13+
14+
messages: list[MessageParam] = [
15+
{"role": "user", "content": "Search for the latest Claude web search documentation."}
16+
]
17+
18+
while True:
19+
message = client.messages.create(
20+
model="claude-sonnet-4-5-20250929",
21+
max_tokens=1024,
22+
messages=messages,
23+
tools=[
24+
{
25+
"name": "web_search",
26+
"type": "web_search_20250305",
27+
}
28+
],
29+
)
30+
31+
if message.stop_reason != "pause_turn":
32+
break
33+
34+
# Keep the full assistant turn intact. Splitting, filtering, or rewriting
35+
# individual server_tool_use blocks can orphan tool state on the next request.
36+
messages.append(assistant_turn_from_message(message))
37+
38+
39+
print(message.model_dump_json(indent=2))

tests/test_transform.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import pytest
1010

11+
from anthropic.types import ServerToolUseBlock
1112
from anthropic._types import Base64FileInput, omit, not_given
1213
from anthropic._utils import (
1314
PropertyInfo,
@@ -17,6 +18,7 @@
1718
)
1819
from anthropic._compat import PYDANTIC_V1
1920
from anthropic._models import BaseModel
21+
from anthropic.types.message_create_params import MessageCreateParamsNonStreaming
2022

2123
_T = TypeVar("_T")
2224

@@ -104,6 +106,48 @@ async def test_union_of_typeddict(use_async: bool) -> None:
104106
}
105107

106108

109+
@parametrize
110+
@pytest.mark.asyncio
111+
async def test_message_params_preserve_server_tool_use_blocks(use_async: bool) -> None:
112+
server_tool_use = ServerToolUseBlock(
113+
id="srvtoolu_123",
114+
input={"query": "latest Claude docs"},
115+
name="web_search",
116+
type="server_tool_use",
117+
)
118+
119+
assert await transform(
120+
{
121+
"max_tokens": 1024,
122+
"model": "claude-sonnet-4-5-20250929",
123+
"messages": [
124+
{
125+
"role": "assistant",
126+
"content": [server_tool_use],
127+
}
128+
],
129+
},
130+
MessageCreateParamsNonStreaming,
131+
use_async,
132+
) == {
133+
"max_tokens": 1024,
134+
"model": "claude-sonnet-4-5-20250929",
135+
"messages": [
136+
{
137+
"role": "assistant",
138+
"content": [
139+
{
140+
"id": "srvtoolu_123",
141+
"input": {"query": "latest Claude docs"},
142+
"name": "web_search",
143+
"type": "server_tool_use",
144+
}
145+
],
146+
}
147+
],
148+
}
149+
150+
107151
class Foo5(TypedDict):
108152
foo: Annotated[Union[Bar4, List[Baz4]], PropertyInfo(alias="FOO")]
109153

0 commit comments

Comments
 (0)