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<T>) 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<T>)**: 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