or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

batches.mdbeta.mdclient-initialization.mderrors.mdindex.mdmessages.mdmodels.mdplatform-clients.mdstreaming.mdtools-builtin.mdtools-decorators.mdtools-function.mdtools-memory.mdtools-runners.mdtools.mdtypes.md

tools-function.mddocs/

0

# Function Tool Classes

1

2

Function tool classes wrap Python functions and provide methods for schema generation, parameter validation, and execution. They are typically created automatically by the `@beta_tool` and `@beta_async_tool` decorators but can also be instantiated directly for more control.

3

4

## Capabilities

5

6

### Synchronous Function Tool

7

8

Wrapper class for synchronous tool functions that handles schema generation, validation, and execution.

9

10

```python { .api }

11

class BetaFunctionTool:

12

"""

13

Synchronous function tool wrapper.

14

15

Wraps a Python function and provides:

16

- Automatic JSON schema generation from type hints

17

- Parameter validation using Pydantic

18

- Description extraction from docstrings

19

- Tool definition for Claude API

20

21

Attributes:

22

func: The wrapped function

23

name: Tool name sent to the API

24

description: Tool description

25

input_schema: JSON schema for tool parameters

26

"""

27

28

def __init__(

29

self,

30

func: Callable[..., str | Iterable[BetaContent]],

31

*,

32

name: str | None = None,

33

description: str | None = None,

34

input_schema: dict | type[BaseModel] | None = None

35

) -> None:

36

"""

37

Create a synchronous function tool.

38

39

Args:

40

func: The function to wrap (must be synchronous)

41

name: Custom tool name (defaults to func.__name__)

42

description: Tool description (defaults to func.__doc__)

43

input_schema: Custom JSON schema or Pydantic model for parameters

44

(defaults to auto-generated from function signature)

45

46

Raises:

47

RuntimeError: If used with Pydantic v1 (requires Pydantic v2)

48

"""

49

50

def to_dict(self) -> ToolParam:

51

"""

52

Convert tool to API parameter dictionary.

53

54

Returns:

55

Dictionary with name, description, and input_schema keys

56

suitable for passing to the messages.create() tools parameter

57

"""

58

59

def call(self, input: object) -> str | Iterable[BetaContent]:

60

"""

61

Execute the wrapped function with validated input.

62

63

Args:

64

input: Dictionary of parameters to pass to the function

65

66

Returns:

67

Function result as string or content blocks

68

69

Raises:

70

RuntimeError: If attempting to call an async function synchronously

71

TypeError: If input is not a dictionary

72

ValueError: If input fails validation

73

"""

74

75

@property

76

def __call__(self) -> Callable[..., str | Iterable[BetaContent]]:

77

"""

78

Access the wrapped function directly.

79

80

Returns:

81

The original function

82

"""

83

```

84

85

#### Usage Examples

86

87

**Direct instantiation:**

88

89

```python

90

from anthropic.lib.tools import BetaFunctionTool

91

92

def multiply(x: float, y: float) -> str:

93

"""Multiply two numbers.

94

95

Args:

96

x: First number

97

y: Second number

98

"""

99

return str(x * y)

100

101

# Create tool wrapper directly

102

multiply_tool = BetaFunctionTool(multiply)

103

104

# Use with Claude

105

tool_dict = multiply_tool.to_dict()

106

print(tool_dict)

107

# {

108

# "name": "multiply",

109

# "description": "Multiply two numbers.",

110

# "input_schema": {

111

# "type": "object",

112

# "properties": {

113

# "x": {"type": "number"},

114

# "y": {"type": "number"}

115

# },

116

# "required": ["x", "y"]

117

# }

118

# }

119

```

120

121

**Custom name and description:**

122

123

```python

124

def internal_calc(a: int, b: int) -> str:

125

return str(a + b)

126

127

tool = BetaFunctionTool(

128

internal_calc,

129

name="add_numbers",

130

description="Add two integers together"

131

)

132

```

133

134

**Custom schema with Pydantic:**

135

136

```python

137

from pydantic import BaseModel, Field

138

139

class EmailParams(BaseModel):

140

to: str = Field(description="Recipient email address")

141

subject: str = Field(description="Email subject line")

142

body: str = Field(description="Email body content")

143

cc: list[str] = Field(default_factory=list, description="CC recipients")

144

145

def send_email(to: str, subject: str, body: str, cc: list[str] = None) -> str:

146

"""Send an email."""

147

cc = cc or []

148

# Email sending logic

149

return f"Email sent to {to}"

150

151

email_tool = BetaFunctionTool(

152

send_email,

153

input_schema=EmailParams

154

)

155

```

156

157

**Manual tool execution:**

158

159

```python

160

from anthropic import Anthropic

161

162

# Create tool

163

@beta_tool

164

def get_time(timezone: str = "UTC") -> str:

165

"""Get current time in timezone.

166

167

Args:

168

timezone: IANA timezone name

169

"""

170

from datetime import datetime

171

import zoneinfo

172

tz = zoneinfo.ZoneInfo(timezone)

173

return datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")

174

175

client = Anthropic()

176

177

# First request

178

message = client.beta.messages.create(

179

model="claude-3-5-sonnet-20241022",

180

max_tokens=1024,

181

tools=[get_time.to_dict()],

182

messages=[{"role": "user", "content": "What time is it in Tokyo?"}]

183

)

184

185

# Extract and execute tool call

186

if message.stop_reason == "tool_use":

187

tool_use = next(block for block in message.content if block.type == "tool_use")

188

result = get_time.call(tool_use.input)

189

190

# Send result back to Claude

191

response = client.beta.messages.create(

192

model="claude-3-5-sonnet-20241022",

193

max_tokens=1024,

194

tools=[get_time.to_dict()],

195

messages=[

196

{"role": "user", "content": "What time is it in Tokyo?"},

197

{"role": "assistant", "content": message.content},

198

{

199

"role": "user",

200

"content": [

201

{

202

"type": "tool_result",

203

"tool_use_id": tool_use.id,

204

"content": result

205

}

206

]

207

}

208

]

209

)

210

print(response.content[0].text)

211

```

212

213

**Complex return types:**

214

215

```python

216

from anthropic.types.beta import BetaTextBlockParam

217

218

@beta_tool

219

def format_report(data: dict) -> list[BetaTextBlockParam]:

220

"""Format data as structured report.

221

222

Args:

223

data: Dictionary of report data

224

"""

225

return [

226

{"type": "text", "text": "# Report\n\n"},

227

{"type": "text", "text": f"Total: {data.get('total', 0)}\n"},

228

{"type": "text", "text": f"Status: {data.get('status', 'unknown')}"}

229

]

230

231

# Tool call returns multiple content blocks

232

result = format_report.call({"total": 100, "status": "complete"})

233

```

234

235

### Asynchronous Function Tool

236

237

Wrapper class for asynchronous tool functions that handles schema generation, validation, and async execution.

238

239

```python { .api }

240

class BetaAsyncFunctionTool:

241

"""

242

Asynchronous function tool wrapper.

243

244

Wraps an async Python function and provides the same features as

245

BetaFunctionTool but with async execution support.

246

247

Attributes:

248

func: The wrapped async function

249

name: Tool name sent to the API

250

description: Tool description

251

input_schema: JSON schema for tool parameters

252

"""

253

254

def __init__(

255

self,

256

func: Callable[..., Coroutine[Any, Any, str | Iterable[BetaContent]]],

257

*,

258

name: str | None = None,

259

description: str | None = None,

260

input_schema: dict | type[BaseModel] | None = None

261

) -> None:

262

"""

263

Create an asynchronous function tool.

264

265

Args:

266

func: The async function to wrap (must be defined with async def)

267

name: Custom tool name (defaults to func.__name__)

268

description: Tool description (defaults to func.__doc__)

269

input_schema: Custom JSON schema or Pydantic model for parameters

270

271

Raises:

272

RuntimeError: If used with Pydantic v1 (requires Pydantic v2)

273

"""

274

275

def to_dict(self) -> ToolParam:

276

"""

277

Convert tool to API parameter dictionary.

278

279

Returns:

280

Dictionary with name, description, and input_schema keys

281

"""

282

283

async def call(self, input: object) -> str | Iterable[BetaContent]:

284

"""

285

Execute the wrapped async function with validated input.

286

287

Args:

288

input: Dictionary of parameters to pass to the function

289

290

Returns:

291

Function result as string or content blocks

292

293

Raises:

294

RuntimeError: If attempting to call a sync function asynchronously

295

TypeError: If input is not a dictionary

296

ValueError: If input fails validation

297

"""

298

299

@property

300

def __call__(self) -> Callable[..., Coroutine[Any, Any, str | Iterable[BetaContent]]]:

301

"""

302

Access the wrapped async function directly.

303

304

Returns:

305

The original async function

306

"""

307

```

308

309

#### Usage Examples

310

311

**Basic async tool:**

312

313

```python

314

from anthropic.lib.tools import BetaAsyncFunctionTool

315

import httpx

316

317

async def fetch_url(url: str) -> str:

318

"""Fetch content from URL.

319

320

Args:

321

url: The URL to fetch

322

"""

323

async with httpx.AsyncClient() as client:

324

response = await client.get(url)

325

return response.text[:500]

326

327

# Create async tool

328

fetch_tool = BetaAsyncFunctionTool(fetch_url)

329

330

# Execute manually

331

result = await fetch_tool.call({"url": "https://example.com"})

332

```

333

334

**Async tool with database:**

335

336

```python

337

@beta_async_tool

338

async def save_to_db(table: str, data: dict) -> str:

339

"""Save data to database table.

340

341

Args:

342

table: Database table name

343

data: Data to save as key-value pairs

344

"""

345

# Using hypothetical async database library

346

async with db.transaction() as txn:

347

await txn.execute(f"INSERT INTO {table} VALUES (?)", data)

348

await txn.commit()

349

return f"Saved {len(data)} fields to {table}"

350

```

351

352

**Async tool with error handling:**

353

354

```python

355

@beta_async_tool

356

async def call_api(endpoint: str, params: dict = None) -> str:

357

"""Call external API endpoint.

358

359

Args:

360

endpoint: API endpoint path

361

params: Query parameters

362

"""

363

try:

364

async with httpx.AsyncClient() as client:

365

response = await client.get(

366

f"https://api.example.com/{endpoint}",

367

params=params or {}

368

)

369

response.raise_for_status()

370

return response.text

371

except httpx.HTTPError as e:

372

return f"API Error: {str(e)}"

373

```

374

375

**Manual async tool execution:**

376

377

```python

378

from anthropic import AsyncAnthropic

379

380

@beta_async_tool

381

async def async_computation(n: int) -> str:

382

"""Perform async computation.

383

384

Args:

385

n: Input number

386

"""

387

await asyncio.sleep(0.1) # Simulate work

388

return f"Result: {n * 2}"

389

390

client = AsyncAnthropic()

391

392

# Get tool use from Claude

393

message = await client.beta.messages.create(

394

model="claude-3-5-sonnet-20241022",

395

max_tokens=1024,

396

tools=[async_computation.to_dict()],

397

messages=[{"role": "user", "content": "Double the number 42"}]

398

)

399

400

# Execute async tool

401

if message.stop_reason == "tool_use":

402

tool_use = next(block for block in message.content if block.type == "tool_use")

403

result = await async_computation.call(tool_use.input)

404

print(result) # "Result: 84"

405

```

406

407

## Types

408

409

### Tool Parameter Schema

410

411

```python { .api }

412

class ToolParam(TypedDict):

413

"""

414

Tool definition for the API.

415

"""

416

name: str

417

description: str

418

input_schema: dict

419

```

420

421

### Input Schema Type

422

423

```python { .api }

424

InputSchema = dict

425

```

426

427

JSON schema dictionary or Pydantic model defining tool parameters.

428