or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-setup.mderrors.mdindex.mdmessages.mdplatform-adapters.mdstreaming.mdstructured-outputs.mdtools.md

tools.mddocs/

0

# Tool Use and Function Calling

1

2

Complete reference for the anthropic-java SDK's tool use (function calling) capabilities, enabling Claude to interact with external tools and functions.

3

4

## Tool Definition

5

6

### Tool Class

7

8

Custom tool definition for function calling.

9

10

```java { .api }

11

package com.anthropic.models.messages;

12

13

class Tool {

14

fun inputSchema(): InputSchema

15

fun name(): String

16

fun cacheControl(): Optional<CacheControlEphemeral>

17

fun description(): Optional<String>

18

fun type(): Optional<Type>

19

20

companion object {

21

@JvmStatic fun builder(): Builder

22

}

23

24

class Builder {

25

fun inputSchema(inputSchema: InputSchema): Builder

26

fun name(name: String): Builder

27

fun cacheControl(cacheControl: CacheControlEphemeral?): Builder

28

fun description(description: String): Builder

29

fun build(): Tool

30

}

31

}

32

```

33

34

**Fields:**

35

- `inputSchema`: JSON schema defining tool input parameters (required)

36

- `name`: Tool identifier used by model in tool_use blocks (required)

37

- `cacheControl`: Cache control breakpoint for prompt caching (optional)

38

- `description`: Detailed tool description for model guidance (optional)

39

- `type`: Tool type, defaults to "custom" (optional)

40

41

**Example:**

42

43

```java

44

Tool weatherTool = Tool.builder()

45

.name("get_weather")

46

.description("Get current weather for a location")

47

.inputSchema(Tool.InputSchema.builder()

48

.properties(Tool.InputSchema.Properties.builder()

49

.putAdditionalProperty("location", JsonValue.from(Map.of(

50

"type", "string",

51

"description", "City and state, e.g. San Francisco, CA"

52

)))

53

.putAdditionalProperty("unit", JsonValue.from(Map.of(

54

"type", "string",

55

"enum", List.of("celsius", "fahrenheit")

56

)))

57

.build())

58

.addRequired("location")

59

.build())

60

.build();

61

```

62

63

### InputSchema

64

65

JSON schema definition for tool parameters using JSON Schema Draft 2020-12.

66

67

```java { .api }

68

class InputSchema {

69

fun properties(): Optional<Properties>

70

fun required(): Optional<List<String>>

71

fun _type(): JsonValue // Always returns "object"

72

73

companion object {

74

@JvmStatic fun builder(): Builder

75

}

76

77

class Builder {

78

fun properties(properties: Properties?): Builder

79

fun required(required: List<String>?): Builder

80

fun addRequired(required: String): Builder

81

fun build(): InputSchema

82

}

83

84

class Properties {

85

fun _additionalProperties(): Map<String, JsonValue>

86

87

companion object {

88

@JvmStatic fun builder(): Builder

89

}

90

91

class Builder {

92

fun putAdditionalProperty(key: String, value: JsonValue): Builder

93

fun putAllAdditionalProperties(additionalProperties: Map<String, JsonValue>): Builder

94

fun build(): Properties

95

}

96

}

97

}

98

```

99

100

**Schema Structure:**

101

- Type is always "object"

102

- Properties define parameter schemas as JSON values

103

- Required lists mandatory parameters

104

105

## Tool Union Types

106

107

### ToolUnion

108

109

Union of all tool types (custom and built-in).

110

111

```java { .api }

112

package com.anthropic.models.messages;

113

114

class ToolUnion {

115

// Type checking

116

fun isTool(): Boolean

117

fun isBash20250124(): Boolean

118

fun isTextEditor20250124(): Boolean

119

fun isTextEditor20250429(): Boolean

120

fun isTextEditor20250728(): Boolean

121

fun isWebSearchTool20250305(): Boolean

122

123

// Type access

124

fun tool(): Optional<Tool>

125

fun bash20250124(): Optional<ToolBash20250124>

126

fun textEditor20250124(): Optional<ToolTextEditor20250124>

127

fun textEditor20250429(): Optional<ToolTextEditor20250429>

128

fun textEditor20250728(): Optional<ToolTextEditor20250728>

129

fun webSearchTool20250305(): Optional<WebSearchTool20250305>

130

131

// Type conversion

132

fun asTool(): Tool

133

fun asBash20250124(): ToolBash20250124

134

fun asTextEditor20250124(): ToolTextEditor20250124

135

fun asTextEditor20250429(): ToolTextEditor20250429

136

fun asTextEditor20250728(): ToolTextEditor20250728

137

fun asWebSearchTool20250305(): WebSearchTool20250305

138

139

// Visitor pattern

140

fun <T> accept(visitor: Visitor<T>): T

141

142

companion object {

143

@JvmStatic fun ofTool(tool: Tool): ToolUnion

144

@JvmStatic fun ofBash20250124(bash20250124: ToolBash20250124): ToolUnion

145

@JvmStatic fun ofTextEditor20250124(textEditor20250124: ToolTextEditor20250124): ToolUnion

146

@JvmStatic fun ofTextEditor20250429(textEditor20250429: ToolTextEditor20250429): ToolUnion

147

@JvmStatic fun ofTextEditor20250728(textEditor20250728: ToolTextEditor20250728): ToolUnion

148

@JvmStatic fun ofWebSearchTool20250305(webSearchTool20250305: WebSearchTool20250305): ToolUnion

149

}

150

151

interface Visitor<out T> {

152

fun visitTool(tool: Tool): T

153

fun visitBash20250124(bash20250124: ToolBash20250124): T

154

fun visitTextEditor20250124(textEditor20250124: ToolTextEditor20250124): T

155

fun visitTextEditor20250429(textEditor20250429: ToolTextEditor20250429): T

156

fun visitTextEditor20250728(textEditor20250728: ToolTextEditor20250728): T

157

fun visitWebSearchTool20250305(webSearchTool20250305: WebSearchTool20250305): T

158

fun unknown(json: JsonValue?): T

159

}

160

}

161

```

162

163

**Variants:**

164

- `Tool`: Custom user-defined tools

165

- `ToolBash20250124`: Bash execution tool

166

- `ToolTextEditor20250124/20250429/20250728`: Text editor tools (versioned)

167

- `WebSearchTool20250305`: Web search tool

168

169

**Example:**

170

171

```java

172

ToolUnion customTool = ToolUnion.ofTool(

173

Tool.builder()

174

.name("calculator")

175

.description("Perform arithmetic operations")

176

.inputSchema(/* ... */)

177

.build()

178

);

179

180

// Check type

181

if (customTool.isTool()) {

182

Tool tool = customTool.asTool();

183

System.out.println("Tool name: " + tool.name());

184

}

185

186

// Using visitor pattern

187

String toolType = customTool.accept(new ToolUnion.Visitor<String>() {

188

public String visitTool(Tool tool) {

189

return "custom: " + tool.name();

190

}

191

public String visitBash20250124(ToolBash20250124 bash) {

192

return "bash";

193

}

194

public String visitTextEditor20250124(ToolTextEditor20250124 editor) {

195

return "text_editor";

196

}

197

// ... other visit methods

198

});

199

```

200

201

## Built-in Tools

202

203

### ToolBash

204

205

Bash command execution tool.

206

207

```java { .api }

208

package com.anthropic.models.messages;

209

210

class ToolBash20250124 {

211

fun name(): Name // Returns "bash"

212

fun type(): Type // Returns "bash_20250124"

213

fun cacheControl(): Optional<CacheControlEphemeral>

214

215

companion object {

216

@JvmStatic fun builder(): Builder

217

}

218

219

class Builder {

220

fun cacheControl(cacheControl: CacheControlEphemeral?): Builder

221

fun build(): ToolBash20250124

222

}

223

}

224

```

225

226

### ToolTextEditor

227

228

Text file editing tool (multiple versions available).

229

230

```java { .api }

231

package com.anthropic.models.messages;

232

233

class ToolTextEditor20250728 {

234

fun name(): Name // Returns "str_replace_editor"

235

fun type(): Type // Returns "text_editor_20250728"

236

fun cacheControl(): Optional<CacheControlEphemeral>

237

238

companion object {

239

@JvmStatic fun builder(): Builder

240

}

241

242

class Builder {

243

fun cacheControl(cacheControl: CacheControlEphemeral?): Builder

244

fun build(): ToolTextEditor20250728

245

}

246

}

247

248

// Similar structure for ToolTextEditor20250124 and ToolTextEditor20250429

249

```

250

251

### WebSearchTool

252

253

Web search tool for retrieving online information.

254

255

```java { .api }

256

package com.anthropic.models.messages;

257

258

class WebSearchTool20250305 {

259

fun name(): Name // Returns "web_search"

260

fun type(): Type // Returns "web_search_20250305"

261

fun cacheControl(): Optional<CacheControlEphemeral>

262

263

companion object {

264

@JvmStatic fun builder(): Builder

265

}

266

267

class Builder {

268

fun cacheControl(cacheControl: CacheControlEphemeral?): Builder

269

fun build(): WebSearchTool20250305

270

}

271

}

272

```

273

274

**Example:**

275

276

```java

277

// Add bash tool

278

MessageCreateParams params = MessageCreateParams.builder()

279

.model(Model.CLAUDE_SONNET_4_5)

280

.maxTokens(1024L)

281

.addUserMessage("Run 'ls -la' command")

282

.tools(List.of(

283

ToolUnion.ofBash20250124(

284

ToolBash20250124.builder().build()

285

)

286

))

287

.build();

288

```

289

290

## Tool Choice

291

292

### ToolChoice Union

293

294

Specifies how the model should use provided tools.

295

296

```java { .api }

297

package com.anthropic.models.messages;

298

299

class ToolChoice {

300

// Type checking

301

fun isAuto(): Boolean

302

fun isAny(): Boolean

303

fun isTool(): Boolean

304

fun isNone(): Boolean

305

306

// Type access

307

fun auto(): Optional<ToolChoiceAuto>

308

fun any(): Optional<ToolChoiceAny>

309

fun tool(): Optional<ToolChoiceTool>

310

fun none(): Optional<ToolChoiceNone>

311

312

// Type conversion

313

fun asAuto(): ToolChoiceAuto

314

fun asAny(): ToolChoiceAny

315

fun asTool(): ToolChoiceTool

316

fun asNone(): ToolChoiceNone

317

318

// Visitor pattern

319

fun <T> accept(visitor: Visitor<T>): T

320

321

companion object {

322

@JvmStatic fun ofAuto(auto: ToolChoiceAuto): ToolChoice

323

@JvmStatic fun ofAny(any: ToolChoiceAny): ToolChoice

324

@JvmStatic fun ofTool(tool: ToolChoiceTool): ToolChoice

325

@JvmStatic fun ofNone(none: ToolChoiceNone): ToolChoice

326

}

327

328

interface Visitor<out T> {

329

fun visitAuto(auto: ToolChoiceAuto): T

330

fun visitAny(any: ToolChoiceAny): T

331

fun visitTool(tool: ToolChoiceTool): T

332

fun visitNone(none: ToolChoiceNone): T

333

fun unknown(json: JsonValue?): T

334

}

335

}

336

```

337

338

### ToolChoice Variants

339

340

**ToolChoiceAuto**: Model automatically decides whether to use tools.

341

342

```java { .api }

343

class ToolChoiceAuto {

344

fun type(): Type // Returns "auto"

345

fun disableParallelToolUse(): Optional<Boolean>

346

347

companion object {

348

@JvmStatic fun builder(): Builder

349

}

350

351

class Builder {

352

fun disableParallelToolUse(disableParallelToolUse: Boolean?): Builder

353

fun build(): ToolChoiceAuto

354

}

355

}

356

```

357

358

**ToolChoiceAny**: Model must use at least one available tool.

359

360

```java { .api }

361

class ToolChoiceAny {

362

fun type(): Type // Returns "any"

363

fun disableParallelToolUse(): Optional<Boolean>

364

365

companion object {

366

@JvmStatic fun builder(): Builder

367

}

368

369

class Builder {

370

fun disableParallelToolUse(disableParallelToolUse: Boolean?): Builder

371

fun build(): ToolChoiceAny

372

}

373

}

374

```

375

376

**ToolChoiceTool**: Model must use the specified tool.

377

378

```java { .api }

379

class ToolChoiceTool {

380

fun name(): String

381

fun type(): Type // Returns "tool"

382

fun disableParallelToolUse(): Optional<Boolean>

383

384

companion object {

385

@JvmStatic fun builder(): Builder

386

}

387

388

class Builder {

389

fun name(name: String): Builder

390

fun disableParallelToolUse(disableParallelToolUse: Boolean?): Builder

391

fun build(): ToolChoiceTool

392

}

393

}

394

```

395

396

**ToolChoiceNone**: Model must not use any tools.

397

398

```java { .api }

399

class ToolChoiceNone {

400

fun type(): Type // Returns "none"

401

402

companion object {

403

@JvmStatic fun builder(): Builder

404

}

405

406

class Builder {

407

fun build(): ToolChoiceNone

408

}

409

}

410

```

411

412

**Example:**

413

414

```java

415

// Auto (model decides)

416

ToolChoice autoChoice = ToolChoice.ofAuto(

417

ToolChoiceAuto.builder().build()

418

);

419

420

// Any (must use at least one tool)

421

ToolChoice anyChoice = ToolChoice.ofAny(

422

ToolChoiceAny.builder()

423

.disableParallelToolUse(true)

424

.build()

425

);

426

427

// Specific tool (must use named tool)

428

ToolChoice specificTool = ToolChoice.ofTool(

429

ToolChoiceTool.builder()

430

.name("get_weather")

431

.build()

432

);

433

434

// None (no tools allowed)

435

ToolChoice noTools = ToolChoice.ofNone(

436

ToolChoiceNone.builder().build()

437

);

438

```

439

440

## Tool Parameters

441

442

### Adding Tools to MessageCreateParams

443

444

```java { .api }

445

package com.anthropic.models.messages;

446

447

class MessageCreateParams {

448

fun tools(): Optional<List<ToolUnion>>

449

fun toolChoice(): Optional<ToolChoice>

450

451

class Builder {

452

// Tools

453

fun tools(tools: List<ToolUnion>): Builder

454

fun addTool(tool: Tool): Builder

455

456

// Tool choice

457

fun toolChoice(toolChoice: ToolChoice): Builder

458

459

fun build(): MessageCreateParams

460

}

461

}

462

```

463

464

**Example:**

465

466

```java

467

MessageCreateParams params = MessageCreateParams.builder()

468

.model(Model.CLAUDE_SONNET_4_5)

469

.maxTokens(2048L)

470

.addUserMessage("What's the weather in San Francisco?")

471

.addTool(Tool.builder()

472

.name("get_weather")

473

.description("Get current weather for a location")

474

.inputSchema(/* schema */)

475

.build())

476

.toolChoice(ToolChoice.ofAuto(

477

ToolChoiceAuto.builder().build()

478

))

479

.build();

480

481

Message response = client.messages().create(params);

482

```

483

484

## Tool Use Blocks

485

486

### ToolUseBlock

487

488

Tool use request from the model in response content.

489

490

```java { .api }

491

package com.anthropic.models.messages;

492

493

class ToolUseBlock {

494

fun id(): String

495

fun name(): String

496

fun _input(): JsonValue

497

fun _type(): JsonValue // Returns "tool_use"

498

499

fun toParam(): ToolUseBlockParam

500

501

companion object {

502

@JvmStatic fun builder(): Builder

503

}

504

505

class Builder {

506

fun id(id: String): Builder

507

fun name(name: String): Builder

508

fun input(input: JsonValue): Builder

509

fun build(): ToolUseBlock

510

}

511

}

512

```

513

514

**Fields:**

515

- `id`: Unique identifier for this tool use

516

- `name`: Name of the tool to invoke

517

- `input`: Tool parameters as JSON

518

- `type`: Always "tool_use"

519

520

**Example:**

521

522

```java

523

Message response = client.messages().create(params);

524

525

// Process tool use blocks

526

response.content().forEach(block -> {

527

if (block.isToolUse()) {

528

ToolUseBlock toolUse = block.asToolUse();

529

530

System.out.println("Tool: " + toolUse.name());

531

System.out.println("ID: " + toolUse.id());

532

System.out.println("Input: " + toolUse._input());

533

534

// Execute tool and prepare result

535

Object result = executeToolByName(toolUse.name(), toolUse._input());

536

}

537

});

538

```

539

540

## Tool Results

541

542

### ToolResultBlockParam

543

544

Tool execution result to send back to the model.

545

546

```java { .api }

547

package com.anthropic.models.messages;

548

549

class ToolResultBlockParam {

550

fun toolUseId(): String

551

fun content(): Optional<Content>

552

fun isError(): Optional<Boolean>

553

fun cacheControl(): Optional<CacheControlEphemeral>

554

fun _type(): JsonValue // Returns "tool_result"

555

556

companion object {

557

@JvmStatic fun builder(): Builder

558

}

559

560

class Builder {

561

fun toolUseId(toolUseId: String): Builder

562

fun content(content: String): Builder

563

fun content(content: Content): Builder

564

fun contentOfTextBlockParams(textBlockParams: List<TextBlockParam>): Builder

565

fun contentOfImageBlockParams(imageBlockParams: List<ImageBlockParam>): Builder

566

fun contentOfDocumentBlockParams(documentBlockParams: List<DocumentBlockParam>): Builder

567

fun isError(isError: Boolean?): Builder

568

fun cacheControl(cacheControl: CacheControlEphemeral?): Builder

569

fun build(): ToolResultBlockParam

570

}

571

572

@JsonDeserialize(using = Content.Deserializer::class)

573

@JsonSerialize(using = Content.Serializer::class)

574

class Content {

575

fun string(): Optional<String>

576

fun contentBlockParams(): Optional<List<ContentBlockParam>>

577

578

fun isString(): Boolean

579

fun isContentBlockParams(): Boolean

580

581

fun asString(): String

582

fun asContentBlockParams(): List<ContentBlockParam>

583

584

companion object {

585

@JvmStatic fun ofString(string: String): Content

586

@JvmStatic fun ofContentBlockParams(contentBlockParams: List<ContentBlockParam>): Content

587

}

588

}

589

}

590

```

591

592

**Example:**

593

594

```java

595

// Simple text result

596

ToolResultBlockParam result = ToolResultBlockParam.builder()

597

.toolUseId(toolUse.id())

598

.content("Temperature: 72°F")

599

.build();

600

601

// JSON result

602

ToolResultBlockParam jsonResult = ToolResultBlockParam.builder()

603

.toolUseId(toolUse.id())

604

.content(JsonValue.from(Map.of(

605

"temperature", 72,

606

"unit", "fahrenheit",

607

"conditions", "sunny"

608

)).toJsonString())

609

.build();

610

611

// Error result

612

ToolResultBlockParam errorResult = ToolResultBlockParam.builder()

613

.toolUseId(toolUse.id())

614

.content("Tool execution failed: Invalid location")

615

.isError(true)

616

.build();

617

618

// Send result back in next message

619

MessageCreateParams followUp = params.toBuilder()

620

.addUserMessageOfContentBlockParams(

621

List.of(ContentBlockParam.ofToolResult(result))

622

)

623

.build();

624

```

625

626

## Defining Tools from Java Classes

627

628

### addTool(Class&lt;T&gt;) Method

629

630

Automatically derive tool schema from Java class structure.

631

632

```java { .api }

633

package com.anthropic.models.beta.messages;

634

635

class MessageCreateParams {

636

class Builder {

637

fun <T> addTool(

638

toolClass: Class<T>,

639

localValidation: JsonSchemaLocalValidation = JsonSchemaLocalValidation.YES

640

): Builder

641

}

642

}

643

```

644

645

**Class-to-Schema Mapping:**

646

- Class name (camel case) → tool name (snake_case)

647

- `public` fields/getters → tool parameters

648

- Field types → JSON schema types

649

- Jackson annotations → schema metadata

650

651

**Example:**

652

653

```java

654

import com.fasterxml.jackson.annotation.JsonClassDescription;

655

import com.fasterxml.jackson.annotation.JsonPropertyDescription;

656

657

@JsonClassDescription("Get the weather in a given location")

658

static class GetWeather {

659

@JsonPropertyDescription("The city and state, e.g. San Francisco, CA")

660

public String location;

661

662

@JsonPropertyDescription("The unit of temperature")

663

public Unit unit;

664

665

public Weather execute() {

666

// Tool implementation

667

return new Weather(/* ... */);

668

}

669

}

670

671

enum Unit {

672

CELSIUS, FAHRENHEIT

673

}

674

675

static class Weather {

676

public String temperature;

677

678

public Weather(String temperature) {

679

this.temperature = temperature;

680

}

681

}

682

683

// Add tool by class

684

MessageCreateParams params = MessageCreateParams.builder()

685

.model(Model.CLAUDE_SONNET_4_5)

686

.maxTokens(2048)

687

.addTool(GetWeather.class) // Automatically derives schema

688

.addUserMessage("What's the temperature in New York?")

689

.build();

690

```

691

692

### Tool Class Conversion

693

694

**BetaToolUseBlock.input(Class&lt;T&gt;)**: Parse tool parameters JSON to class instance.

695

696

```java { .api }

697

package com.anthropic.models.beta.messages;

698

699

class BetaToolUseBlock {

700

fun <T> input(toolClass: Class<T>): T?

701

}

702

```

703

704

**BetaToolResultBlockParam.Builder.contentAsJson(Object)**: Convert result object to JSON.

705

706

```java { .api }

707

class BetaToolResultBlockParam {

708

class Builder {

709

fun contentAsJson(content: Object): Builder

710

}

711

}

712

```

713

714

**Complete Flow:**

715

716

```java

717

// 1. Add tool from class

718

MessageCreateParams.Builder paramsBuilder = MessageCreateParams.builder()

719

.model(Model.CLAUDE_SONNET_4_5)

720

.maxTokens(2048)

721

.addTool(GetWeather.class)

722

.addUserMessage("What's the temperature in New York?");

723

724

// 2. Get response with tool use

725

BetaMessage response = client.beta().messages().create(paramsBuilder.build());

726

727

// 3. Process tool uses

728

response.content().stream()

729

.flatMap(block -> block.toolUse().stream())

730

.forEach(toolUse -> {

731

// Parse parameters to class instance

732

GetWeather tool = toolUse.input(GetWeather.class);

733

734

// Execute tool

735

Weather result = tool.execute();

736

737

// Add tool request to conversation

738

paramsBuilder.addAssistantMessageOfBetaContentBlockParams(

739

List.of(BetaContentBlockParam.ofToolUse(

740

BetaToolUseBlockParam.builder()

741

.name(toolUse.name())

742

.id(toolUse.id())

743

.input(toolUse._input())

744

.build()

745

))

746

);

747

748

// Add tool result to conversation

749

paramsBuilder.addUserMessageOfBetaContentBlockParams(

750

List.of(BetaContentBlockParam.ofToolResult(

751

BetaToolResultBlockParam.builder()

752

.toolUseId(toolUse.id())

753

.contentAsJson(result) // Converts object to JSON

754

.build()

755

))

756

);

757

});

758

759

// 4. Get final response

760

BetaMessage finalResponse = client.beta().messages().create(paramsBuilder.build());

761

```

762

763

## BetaToolRunner

764

765

### Automatic Tool Conversation Loop

766

767

Helper class that handles the complete tool use conversation flow.

768

769

```java { .api }

770

package com.anthropic.helpers;

771

772

class BetaToolRunner : Iterable<BetaMessage> {

773

// Iterate through conversation turns

774

override fun iterator(): Iterator<BetaMessage>

775

776

// Stream responses instead of buffered messages

777

fun streaming(): Iterable<StreamResponse<BetaRawMessageStreamEvent>>

778

779

// Get current request parameters

780

fun params(): MessageCreateParams

781

782

// Set parameters for next API call

783

fun setNextParams(nextParams: MessageCreateParams)

784

785

// Get last tool response (cached)

786

fun lastToolResponse(): Optional<BetaMessageParam>

787

}

788

```

789

790

**Created via MessageService:**

791

792

```java { .api }

793

package com.anthropic.services.blocking.beta;

794

795

interface MessageService {

796

fun createToolRunner(params: ToolRunnerCreateParams): BetaToolRunner

797

fun createToolRunner(

798

params: ToolRunnerCreateParams,

799

requestOptions: RequestOptions

800

): BetaToolRunner

801

}

802

```

803

804

**ToolRunnerCreateParams:**

805

806

```java { .api }

807

package com.anthropic.models.beta.messages;

808

809

class ToolRunnerCreateParams {

810

fun initialMessageParams(): MessageCreateParams

811

fun maxIterations(): Optional<Long>

812

813

companion object {

814

@JvmStatic fun builder(): Builder

815

}

816

817

class Builder {

818

fun initialMessageParams(initialMessageParams: MessageCreateParams): Builder

819

fun maxIterations(maxIterations: Long?): Builder

820

fun build(): ToolRunnerCreateParams

821

}

822

}

823

```

824

825

**Example (Basic):**

826

827

```java

828

// Define tool class

829

@JsonClassDescription("Calculate the result of an arithmetic expression")

830

static class Calculator {

831

@JsonPropertyDescription("The arithmetic expression to evaluate")

832

public String expression;

833

834

public CalculatorResult execute() {

835

// Simple eval (for demo only - use proper parser in production)

836

double result = evaluateExpression(expression);

837

return new CalculatorResult(result);

838

}

839

}

840

841

static class CalculatorResult {

842

public double result;

843

844

public CalculatorResult(double result) {

845

this.result = result;

846

}

847

}

848

849

// Create initial params

850

MessageCreateParams initialParams = MessageCreateParams.builder()

851

.model(Model.CLAUDE_SONNET_4_5)

852

.maxTokens(2048)

853

.addTool(Calculator.class)

854

.addUserMessage("What is 15 * 23 + 42?")

855

.build();

856

857

// Create tool runner

858

ToolRunnerCreateParams runnerParams = ToolRunnerCreateParams.builder()

859

.initialMessageParams(initialParams)

860

.maxIterations(5)

861

.build();

862

863

BetaToolRunner runner = client.beta().messages().createToolRunner(runnerParams);

864

865

// Iterate through conversation automatically

866

for (BetaMessage message : runner) {

867

message.content().stream()

868

.flatMap(block -> block.text().stream())

869

.forEach(text -> System.out.println("Claude: " + text.text()));

870

}

871

```

872

873

**Example (Streaming):**

874

875

```java

876

BetaToolRunner runner = client.beta().messages().createToolRunner(runnerParams);

877

878

// Stream responses

879

for (StreamResponse<BetaRawMessageStreamEvent> streamResponse : runner.streaming()) {

880

streamResponse.stream()

881

.flatMap(event -> event.contentBlockDelta().stream())

882

.flatMap(delta -> delta.delta().text().stream())

883

.forEach(text -> System.out.print(text.text()));

884

885

System.out.println(); // New line after each turn

886

}

887

```

888

889

**Example (Custom Tool Execution):**

890

891

```java

892

// Custom tool handler with external API calls

893

static class WeatherAPI {

894

@JsonClassDescription("Get real-time weather data")

895

public String location;

896

897

public WeatherData execute() {

898

// Call external weather API

899

return callWeatherAPI(location);

900

}

901

}

902

903

// Runner with error handling

904

BetaToolRunner runner = client.beta().messages().createToolRunner(runnerParams);

905

906

try {

907

for (BetaMessage message : runner) {

908

// Access tool response for logging/debugging

909

runner.lastToolResponse().ifPresent(toolResponse -> {

910

System.out.println("Tool executed: " + toolResponse);

911

});

912

913

// Process message

914

message.content().forEach(block -> {

915

if (block.isText()) {

916

System.out.println(block.asText().text());

917

} else if (block.isToolUse()) {

918

BetaToolUseBlock toolUse = block.asToolUse();

919

System.out.println("Using tool: " + toolUse.name());

920

}

921

});

922

923

// Modify params for next iteration if needed

924

if (needsAdjustment(message)) {

925

MessageCreateParams nextParams = runner.params()

926

.toBuilder()

927

.temperature(0.7)

928

.build();

929

runner.setNextParams(nextParams);

930

}

931

}

932

} catch (Exception e) {

933

System.err.println("Tool runner error: " + e.getMessage());

934

}

935

```

936

937

## Annotations for Tools

938

939

### Jackson Annotations

940

941

Use Jackson Databind annotations to enhance tool schemas.

942

943

```java

944

import com.fasterxml.jackson.annotation.JsonClassDescription;

945

import com.fasterxml.jackson.annotation.JsonPropertyDescription;

946

import com.fasterxml.jackson.annotation.JsonProperty;

947

import com.fasterxml.jackson.annotation.JsonIgnore;

948

import com.fasterxml.jackson.annotation.JsonTypeName;

949

```

950

951

**@JsonClassDescription**: Tool description.

952

953

```java

954

@JsonClassDescription("Get the weather in a given location")

955

class GetWeather {

956

// ...

957

}

958

```

959

960

**@JsonPropertyDescription**: Parameter description.

961

962

```java

963

class GetWeather {

964

@JsonPropertyDescription("The city and state, e.g. San Francisco, CA")

965

public String location;

966

}

967

```

968

969

**@JsonProperty**: Include non-public fields or custom names.

970

971

```java

972

class GetWeather {

973

@JsonProperty("loc") // Use "loc" instead of "location" in schema

974

private String location;

975

976

@JsonProperty // Include private field

977

private String apiKey;

978

}

979

```

980

981

**@JsonIgnore**: Exclude public fields from schema.

982

983

```java

984

class GetWeather {

985

public String location;

986

987

@JsonIgnore

988

public String internalCache; // Excluded from tool schema

989

}

990

```

991

992

**@JsonTypeName**: Override tool name.

993

994

```java

995

@JsonTypeName("weather_api") // Use "weather_api" instead of "get_weather"

996

class GetWeather {

997

// ...

998

}

999

```

1000

1001

### Swagger/OpenAPI Annotations

1002

1003

Use Swagger annotations for type-specific constraints.

1004

1005

```java

1006

import io.swagger.v3.oas.annotations.media.Schema;

1007

import io.swagger.v3.oas.annotations.media.ArraySchema;

1008

```

1009

1010

**@Schema**: Property constraints.

1011

1012

```java

1013

class Article {

1014

@Schema(minimum = "1", maximum = "1000")

1015

public int pageCount;

1016

1017

@Schema(pattern = "^[A-Z].*$")

1018

public String title;

1019

1020

@Schema(format = "date")

1021

public String publicationDate;

1022

1023

@Schema(description = "ISBN-13 identifier", minLength = 13, maxLength = 13)

1024

public String isbn;

1025

}

1026

```

1027

1028

**@ArraySchema**: Array constraints.

1029

1030

```java

1031

class BookList {

1032

@ArraySchema(minItems = 1, maxItems = 100)

1033

public List<Book> books;

1034

}

1035

```

1036

1037

**Supported Constraints:**

1038

- Numeric: `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`

1039

- String: `minLength`, `maxLength`, `pattern`, `format`

1040

- Array: `minItems`, `maxItems`, `uniqueItems`

1041

1042

**Example:**

1043

1044

```java

1045

@JsonClassDescription("Search for books in a library catalog")

1046

class LibrarySearch {

1047

@JsonPropertyDescription("Search query terms")

1048

@Schema(minLength = 1, maxLength = 200)

1049

public String query;

1050

1051

@JsonPropertyDescription("Publication year range")

1052

@Schema(minimum = "1800", maximum = "2100")

1053

public Integer year;

1054

1055

@ArraySchema(

1056

schema = @Schema(description = "Genre filters"),

1057

minItems = 0,

1058

maxItems = 5

1059

)

1060

public List<String> genres;

1061

1062

@Schema(format = "date")

1063

public String searchDate;

1064

}

1065

```

1066

1067

## JSON Schema Validation

1068

1069

### Local Validation

1070

1071

Validate tool schemas locally before sending to API.

1072

1073

```java { .api }

1074

package com.anthropic.core;

1075

1076

enum class JsonSchemaLocalValidation {

1077

YES, // Enable local validation (default)

1078

NO // Disable local validation

1079

}

1080

```

1081

1082

**Enable/Disable:**

1083

1084

```java

1085

// Default: validation enabled

1086

MessageCreateParams params = MessageCreateParams.builder()

1087

.addTool(GetWeather.class) // Validates schema

1088

.build();

1089

1090

// Explicitly enable

1091

MessageCreateParams params = MessageCreateParams.builder()

1092

.addTool(GetWeather.class, JsonSchemaLocalValidation.YES)

1093

.build();

1094

1095

// Disable validation

1096

MessageCreateParams params = MessageCreateParams.builder()

1097

.addTool(GetWeather.class, JsonSchemaLocalValidation.NO)

1098

.build();

1099

```

1100

1101

**Validation Checks:**

1102

- Schema structure compliance with JSON Schema Draft 2020-12

1103

- Anthropic-specific restrictions (supported types, constraints)

1104

- Required properties defined

1105

- Valid constraint values

1106

1107

**When to Disable:**

1108

- SDK version older than API schema restrictions

1109

- Custom schema extensions

1110

- Troubleshooting compatibility issues

1111

1112

**Note:** Remote API always validates schemas regardless of local validation setting.

1113

1114

## Complete Tool Use Example

1115

1116

Full workflow showing tool definition, execution, and result handling.

1117

1118

```java

1119

import com.anthropic.client.AnthropicClient;

1120

import com.anthropic.client.okhttp.AnthropicOkHttpClient;

1121

import com.anthropic.models.beta.messages.*;

1122

import com.anthropic.models.messages.Model;

1123

import com.fasterxml.jackson.annotation.JsonClassDescription;

1124

import com.fasterxml.jackson.annotation.JsonPropertyDescription;

1125

import java.util.List;

1126

1127

public class ToolUseExample {

1128

1129

// 1. Define tool classes with annotations

1130

enum Unit {

1131

CELSIUS, FAHRENHEIT;

1132

1133

public String toString() {

1134

return this == CELSIUS ? "°C" : "°F";

1135

}

1136

1137

public double fromKelvin(double k) {

1138

return this == CELSIUS ? k - 273.15 : (k - 273.15) * 1.8 + 32.0;

1139

}

1140

}

1141

1142

@JsonClassDescription("Get the weather in a given location")

1143

static class GetWeather {

1144

@JsonPropertyDescription("The city and state, e.g. San Francisco, CA")

1145

public String location;

1146

1147

@JsonPropertyDescription("The unit of temperature")

1148

public Unit unit;

1149

1150

public Weather execute() {

1151

// Simulate weather lookup

1152

double tempK = switch (location) {

1153

case "San Francisco, CA" -> 300.0;

1154

case "New York, NY" -> 310.0;

1155

case "Dallas, TX" -> 305.0;

1156

default -> 295.0;

1157

};

1158

1159

return new Weather(

1160

String.format("%.0f%s", unit.fromKelvin(tempK), unit)

1161

);

1162

}

1163

}

1164

1165

static class Weather {

1166

public String temperature;

1167

1168

public Weather(String temperature) {

1169

this.temperature = temperature;

1170

}

1171

}

1172

1173

public static void main(String[] args) {

1174

// 2. Create client

1175

AnthropicClient client = AnthropicOkHttpClient.fromEnv();

1176

1177

// 3. Build initial message params with tool

1178

MessageCreateParams.Builder paramsBuilder = MessageCreateParams.builder()

1179

.model(Model.CLAUDE_SONNET_4_5)

1180

.maxTokens(2048)

1181

.addTool(GetWeather.class) // Add tool from class

1182

.addUserMessage("What's the temperature in New York?");

1183

1184

// 4. Create message and get tool use

1185

client.beta().messages()

1186

.create(paramsBuilder.build())

1187

.content()

1188

.stream()

1189

.flatMap(block -> block.toolUse().stream())

1190

.forEach(toolUse -> {

1191

System.out.println("Tool requested: " + toolUse.name());

1192

1193

// 5. Parse tool parameters

1194

GetWeather tool = toolUse.input(GetWeather.class);

1195

System.out.println("Location: " + tool.location);

1196

System.out.println("Unit: " + tool.unit);

1197

1198

// 6. Execute tool

1199

Weather result = tool.execute();

1200

System.out.println("Result: " + result.temperature);

1201

1202

// 7. Add assistant message with tool use

1203

paramsBuilder.addAssistantMessageOfBetaContentBlockParams(

1204

List.of(BetaContentBlockParam.ofToolUse(

1205

BetaToolUseBlockParam.builder()

1206

.name(toolUse.name())

1207

.id(toolUse.id())

1208

.input(toolUse._input())

1209

.build()

1210

))

1211

);

1212

1213

// 8. Add user message with tool result

1214

paramsBuilder.addUserMessageOfBetaContentBlockParams(

1215

List.of(BetaContentBlockParam.ofToolResult(

1216

BetaToolResultBlockParam.builder()

1217

.toolUseId(toolUse.id())

1218

.contentAsJson(result) // Convert to JSON

1219

.build()

1220

))

1221

);

1222

});

1223

1224

// 9. Get final response from Claude

1225

client.beta().messages()

1226

.create(paramsBuilder.build())

1227

.content()

1228

.stream()

1229

.flatMap(block -> block.text().stream())

1230

.forEach(text -> System.out.println("Claude: " + text.text()));

1231

}

1232

}

1233

```

1234

1235

**Output:**

1236

```

1237

Tool requested: get_weather

1238

Location: New York, NY

1239

Unit: FAHRENHEIT

1240

Result: 99°F

1241

Claude: The temperature in New York is 99°F.

1242

```

1243

1244

---

1245

1246

**See Also:**

1247

- [Messages API](/docs/index.md#message-api) - Core messaging functionality

1248

- [Streaming](/docs/index.md#streaming) - Streaming responses

1249

- [Structured Outputs](README section on structured outputs) - JSON schema outputs

1250