0
# Tool Decorators
1
2
Tool decorators provide the simplest way to convert Python functions into Claude-compatible tools. They automatically generate JSON schemas from type hints and docstrings, handle parameter validation, and create the necessary tool definitions.
3
4
## Capabilities
5
6
### Synchronous Tool Decorator
7
8
Creates a synchronous function tool with automatic schema inference from type hints and docstrings.
9
10
```python { .api }
11
def beta_tool(
12
func: Callable[..., str | Iterable[BetaContent]] | None = None,
13
*,
14
name: str | None = None,
15
description: str | None = None,
16
input_schema: dict | type[BaseModel] | None = None
17
) -> BetaFunctionTool | Callable[[Callable], BetaFunctionTool]:
18
"""
19
Decorator to create a function tool with automatic schema generation.
20
21
The decorator can be used in three ways:
22
1. Without parentheses: @beta_tool
23
2. With empty parentheses: @beta_tool()
24
3. With parameters: @beta_tool(name="custom_name", description="...")
25
26
Type hints and docstrings are automatically parsed to generate the tool schema.
27
Parameter descriptions are extracted from the docstring's Args section.
28
29
Args:
30
func: The function to convert into a tool (when used without parentheses)
31
name: Custom tool name (defaults to function.__name__)
32
description: Tool description (defaults to function docstring)
33
input_schema: Custom JSON schema or Pydantic model for parameters
34
(defaults to auto-generated from function signature)
35
36
Returns:
37
BetaFunctionTool instance or decorator function
38
39
Raises:
40
RuntimeError: If used with Pydantic v1 (requires Pydantic v2)
41
"""
42
```
43
44
#### Usage Examples
45
46
**Basic usage with automatic schema generation:**
47
48
```python
49
from anthropic import Anthropic, beta_tool
50
51
@beta_tool
52
def search_database(query: str, limit: int = 10) -> str:
53
"""Search the product database.
54
55
Args:
56
query: Search query string
57
limit: Maximum number of results to return
58
"""
59
# Your database search logic
60
return f"Found {limit} results for '{query}'"
61
62
# Use with Claude
63
client = Anthropic()
64
message = client.beta.messages.create(
65
model="claude-3-5-sonnet-20241022",
66
max_tokens=1024,
67
tools=[search_database.to_dict()],
68
messages=[{"role": "user", "content": "Find laptops under $1000"}]
69
)
70
```
71
72
**Custom tool name and description:**
73
74
```python
75
@beta_tool(
76
name="db_search",
77
description="Advanced database search with filtering and pagination"
78
)
79
def search_database(query: str, filters: dict = None) -> str:
80
"""Internal function that powers the search."""
81
# Implementation
82
return "Search results..."
83
```
84
85
**Custom schema with Pydantic model:**
86
87
```python
88
from pydantic import BaseModel, Field
89
90
class SearchParams(BaseModel):
91
query: str = Field(description="The search query")
92
category: str = Field(description="Product category to search within")
93
min_price: float = Field(default=0, description="Minimum price filter")
94
max_price: float = Field(default=float('inf'), description="Maximum price filter")
95
96
@beta_tool(input_schema=SearchParams)
97
def advanced_search(query: str, category: str, min_price: float = 0, max_price: float = float('inf')) -> str:
98
"""Search products with price filtering."""
99
return f"Searching {category} for '{query}' between ${min_price}-${max_price}"
100
```
101
102
**Complex return types with content blocks:**
103
104
```python
105
from anthropic.types.beta import BetaTextBlockParam
106
107
@beta_tool
108
def analyze_code(code: str, language: str) -> list[BetaTextBlockParam]:
109
"""Analyze code for potential issues.
110
111
Args:
112
code: The source code to analyze
113
language: Programming language (python, javascript, etc.)
114
"""
115
# Analysis logic
116
return [
117
{"type": "text", "text": "Analysis complete:"},
118
{"type": "text", "text": f"Found 3 issues in {language} code"},
119
]
120
```
121
122
**Error handling in tools:**
123
124
```python
125
@beta_tool
126
def divide_numbers(numerator: float, denominator: float) -> str:
127
"""Divide two numbers.
128
129
Args:
130
numerator: The number to divide
131
denominator: The number to divide by
132
"""
133
if denominator == 0:
134
# Return error message as string
135
return "Error: Cannot divide by zero"
136
137
result = numerator / denominator
138
return f"Result: {result}"
139
```
140
141
### Asynchronous Tool Decorator
142
143
Creates an asynchronous function tool with automatic schema inference, enabling tools that perform async operations like API calls or database queries.
144
145
```python { .api }
146
def beta_async_tool(
147
func: Callable[..., Coroutine[Any, Any, str | Iterable[BetaContent]]] | None = None,
148
*,
149
name: str | None = None,
150
description: str | None = None,
151
input_schema: dict | type[BaseModel] | None = None
152
) -> BetaAsyncFunctionTool | Callable[[Callable], BetaAsyncFunctionTool]:
153
"""
154
Decorator to create an async function tool with automatic schema generation.
155
156
Identical to beta_tool but for async functions. The decorated function must
157
be defined with `async def`.
158
159
Args:
160
func: The async function to convert into a tool
161
name: Custom tool name (defaults to function.__name__)
162
description: Tool description (defaults to function docstring)
163
input_schema: Custom JSON schema or Pydantic model for parameters
164
165
Returns:
166
BetaAsyncFunctionTool instance or decorator function
167
168
Raises:
169
RuntimeError: If used with Pydantic v1 (requires Pydantic v2)
170
"""
171
```
172
173
#### Usage Examples
174
175
**Basic async tool:**
176
177
```python
178
import asyncio
179
from anthropic import AsyncAnthropic, beta_async_tool
180
181
@beta_async_tool
182
async def fetch_weather(location: str) -> str:
183
"""Fetch current weather from API.
184
185
Args:
186
location: City name or coordinates
187
"""
188
# Simulate API call
189
await asyncio.sleep(0.1)
190
return f"Weather in {location}: Sunny, 72°F"
191
192
# Use with async client
193
client = AsyncAnthropic()
194
message = await client.beta.messages.create(
195
model="claude-3-5-sonnet-20241022",
196
max_tokens=1024,
197
tools=[fetch_weather.to_dict()],
198
messages=[{"role": "user", "content": "What's the weather in Tokyo?"}]
199
)
200
```
201
202
**Async tool with external API:**
203
204
```python
205
import httpx
206
207
@beta_async_tool
208
async def get_stock_price(symbol: str) -> str:
209
"""Get current stock price from financial API.
210
211
Args:
212
symbol: Stock ticker symbol (e.g., AAPL, GOOGL)
213
"""
214
async with httpx.AsyncClient() as client:
215
response = await client.get(f"https://api.example.com/stock/{symbol}")
216
data = response.json()
217
return f"{symbol}: ${data['price']}"
218
```
219
220
**Async tool with database query:**
221
222
```python
223
@beta_async_tool
224
async def query_user_data(user_id: int) -> str:
225
"""Retrieve user information from database.
226
227
Args:
228
user_id: Unique user identifier
229
"""
230
# Example using an async database library
231
async with database.connection() as conn:
232
user = await conn.fetch_one("SELECT * FROM users WHERE id = ?", user_id)
233
return f"User: {user['name']}, Email: {user['email']}"
234
```
235
236
**Mixing sync and async tools:**
237
238
```python
239
from anthropic import AsyncAnthropic, beta_tool, beta_async_tool
240
241
@beta_tool
242
def get_current_time() -> str:
243
"""Get the current time."""
244
from datetime import datetime
245
return datetime.now().isoformat()
246
247
@beta_async_tool
248
async def fetch_news(category: str = "technology") -> str:
249
"""Fetch latest news headlines.
250
251
Args:
252
category: News category (technology, business, sports, etc.)
253
"""
254
async with httpx.AsyncClient() as client:
255
response = await client.get(f"https://api.news.com/headlines?category={category}")
256
return response.text
257
258
# Use both tools together
259
client = AsyncAnthropic()
260
runner = client.beta.messages.tool_runner(
261
model="claude-3-5-sonnet-20241022",
262
max_tokens=1024,
263
tools=[get_current_time, fetch_news],
264
messages=[{"role": "user", "content": "What time is it and what's in the news?"}]
265
)
266
final_message = await runner.until_done()
267
```
268
269
## Types
270
271
### Tool Function Signatures
272
273
```python { .api }
274
# Synchronous tool function type
275
Function = Callable[..., str | Iterable[BetaContent]]
276
277
# Asynchronous tool function type
278
AsyncFunction = Callable[..., Coroutine[Any, Any, str | Iterable[BetaContent]]]
279
```
280
281
### Content Block Types
282
283
```python { .api }
284
from anthropic.types.beta import (
285
BetaTextBlockParam,
286
BetaImageBlockParam,
287
BetaToolUseBlockParam,
288
BetaToolResultBlockParam,
289
)
290
291
BetaContent = BetaTextBlockParam | BetaImageBlockParam | BetaToolUseBlockParam | BetaToolResultBlockParam
292
```
293
294
Content blocks that can be returned from tool functions for complex responses.
295