Follow Discord
Sweep 25 Sep 2026 · 19:33Z Build v2.1.283 504 read Stable v2.1.274 Latest v2.1.283 Next v2.1.283 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · api

Log at info level changedagents-and-tools/tool-use/tool-runner

Nearest release: v2.1.281, published 5 hours before this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Recorded here
Lines+54added
Lines−42removed
From line 14 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits9to this page, all time

The whole hunk

from line 14, old and new numbered
/
lines
from line 14
1414* Provides type safety and validation
1515 
1616<Note>
17 The tool runner is in beta and available in the [Python SDK](https://github.com/anthropics/anthropic-sdk-python/blob/main/tools.md), [TypeScript SDK](https://github.com/anthropics/anthropic-sdk-typescript/blob/main/helpers.md#tool-helpers), [C# SDK](https://github.com/anthropics/anthropic-sdk-csharp/blob/main/examples/ToolRunnerExample/Program.cs), [Go SDK](https://github.com/anthropics/anthropic-sdk-go/blob/main/tools.md), [Java SDK](https://github.com/anthropics/anthropic-sdk-java/blob/main/anthropic-java-example/src/main/java/com/anthropic/example/BetaToolRunnerExample.java), [PHP SDK](https://github.com/anthropics/anthropic-sdk-php/blob/main/examples/beta/beta_tool_runner.php), and [Ruby SDK](https://github.com/anthropics/anthropic-sdk-ruby/blob/main/helpers.md#3-auto-looping-tool-runner-beta).
17 The tool runner is in beta and available in the [Python SDK](https://github.com/anthropics/anthropic-sdk-python/blob/main/tools.md), [TypeScript SDK](https://github.com/anthropics/anthropic-sdk-typescript/blob/main/helpers.md#tool-helpers), [C# SDK](https://github.com/anthropics/anthropic-sdk-csharp/blob/main/examples/ToolRunnerExample/Program.cs), [Go SDK](https://github.com/anthropics/anthropic-sdk-go/blob/main/tools.md), [Java SDK](https://github.com/anthropics/anthropic-sdk-java/blob/main/anthropic-java-example/src/main/java/com/anthropic/example/BetaToolRunnerRunnableToolExample.java), [PHP SDK](https://github.com/anthropics/anthropic-sdk-php/blob/main/examples/beta/beta_tool_runner.php), and [Ruby SDK](https://github.com/anthropics/anthropic-sdk-ruby/blob/main/helpers.md#3-auto-looping-tool-runner-beta).
1818</Note>
1919 
2020## Basic usage
from line 350
350350 </Tab>
351351 
352352 <Tab title="Java">
353 Define each tool as a class implementing `Supplier<String>`. Annotate the class with `@JsonClassDescription` for the tool description, and each public field with `@JsonPropertyDescription` for parameter descriptions. The SDK derives the JSON schema, tool name (snake-cased class name), and input parsing from the class, and marks the tool with `strict: true` ([strict tool use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use)).
353 Define each tool as a `BetaRunnableTool` that pairs an input class with a function that runs when Claude calls the tool. Annotate the input class with `@JsonClassDescription` for the tool description, and each public field with `@JsonPropertyDescription` for parameter descriptions. The SDK derives the JSON schema, tool name (snake-cased class name), and input parsing from the class, and marks the tool with `strict: true` ([strict tool use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use)).
354354 
355 The function receives the parsed input as an instance of that class and returns a `BetaToolResultBlockParam.Content`. To return text, wrap it with `BetaToolResultBlockParam.Content.ofString()`. Because the function is a lambda, it can use objects from your application, such as the `WeatherService` in the following example.
356 
355357 ```java
356358 import com.anthropic.client.AnthropicClient;
357359 import com.anthropic.client.okhttp.AnthropicOkHttpClient;
360 import com.anthropic.helpers.BetaRunnableTool;
358361 import com.anthropic.helpers.BetaToolRunner;
359362 import com.anthropic.models.beta.messages.BetaMessage;
363 import com.anthropic.models.beta.messages.BetaToolResultBlockParam;
360364 import com.anthropic.models.beta.messages.MessageCreateParams;
361365 import com.anthropic.models.messages.Model;
362366 import com.fasterxml.jackson.annotation.JsonClassDescription;
363367 import com.fasterxml.jackson.annotation.JsonPropertyDescription;
364 import java.util.function.Supplier;
365368 
366369 @JsonClassDescription("Get the current weather in a given location")
367 static class GetWeather implements Supplier<String> {
370 static class GetWeather {
368371 @JsonPropertyDescription("The city and state, e.g. San Francisco, CA")
369372 public String location;
370373 
371374 @JsonPropertyDescription("Temperature unit, either 'celsius' or 'fahrenheit'")
372375 public String unit;
373 
374 @Override
375 public String get() {
376 return "{\"temperature\": \"20°C\", \"condition\": \"Sunny\"}";
377 }
378376 }
379377 
380378 @JsonClassDescription("Add two numbers together")
381 static class CalculateSum implements Supplier<String> {
379 static class CalculateSum {
382380 @JsonPropertyDescription("First number")
383381 public double a;
384382 
385383 @JsonPropertyDescription("Second number")
386384 public double b;
385 }
387386 
388 @Override
389 public String get() {
390 return String.valueOf(a + b);
387 // Stands in for a class your application already has,
388 // such as a database client or an API wrapper.
389 static class WeatherService {
390 String currentWeather(String location, String unit) {
391 return "{\"temperature\": \"20°C\", \"condition\": \"Sunny\"}";
391392 }
392393 }
393394 
394395 void main() {
395396 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
397 WeatherService weatherService = new WeatherService();
396398 
399 // The lambda can use weatherService.
400 BetaRunnableTool getWeather = BetaRunnableTool.of(
401 GetWeather.class,
402 input -> BetaToolResultBlockParam.Content.ofString(
403 weatherService.currentWeather(input.location, input.unit)));
404 
405 BetaRunnableTool calculateSum = BetaRunnableTool.of(
406 CalculateSum.class,
407 input -> BetaToolResultBlockParam.Content.ofString(
408 String.valueOf(input.a + input.b)));
409 
397410 BetaToolRunner runner = client.beta()
398411 .messages()
399412 .toolRunner(MessageCreateParams.builder()
from line 414
401414 .maxTokens(1024)
402415 .addBeta("structured-outputs-2025-11-13")
403416 .addUserMessage("What's the weather like in Paris? Also, what's 15 + 27?")
404 .addTool(GetWeather.class)
405 .addTool(CalculateSum.class)
417 .addTool(getWeather)
418 .addTool(calculateSum)
406419 .build());
407420 
408421 for (BetaMessage message : runner) {
from line 721
708721 .maxTokens(1024)
709722 .addBeta("structured-outputs-2025-11-13")
710723 .addUserMessage("What's the weather like in Paris? Also, what's 15 + 27?")
711 .addTool(GetWeather.class)
712 .addTool(CalculateSum.class)
724 .addTool(getWeather)
725 .addTool(calculateSum)
713726 .build());
714727 
715728 BetaMessage finalMessage = null;
from line 1004
9911004 .maxTokens(1024)
9921005 .addBeta("structured-outputs-2025-11-13")
9931006 .addUserMessage("Give me a detailed weather report for every major US city.")
994 .addTool(GetWeather.class)
1007 .addTool(getWeather)
9951008 .build())
9961009 .maxIterations(10L)
9971010 .build());
from line 1255
12421255 </Tab>
12431256 
12441257 <Tab title="Java">
1245 Intercepting tool errors before they're sent to Claude is not currently supported in the Java SDK. The runner catches any exception thrown from a tool's `get()` method and converts it into a tool result with `is_error: true` automatically. To control the error content, catch the exception inside your tool and return a custom string.
1258 Intercepting tool errors before they're sent to Claude is not currently supported in the Java SDK. The runner catches any exception thrown from a tool's function and converts it into a tool result with `is_error: true` automatically. To control the error content, catch the exception inside the function and return your own content.
12461259 </Tab>
12471260 
12481261 <Tab title="PHP">
from line 1429
14161429 </Tab>
14171430 
14181431 <Tab title="Java">
1419 To set `cache_control` on a tool result, return `BetaToolResultBlockParam.Content` from the tool instead of `String` and set `cacheControl` on the inner text block. The runner does not currently support setting `cache_control` on the outer `tool_result` block.
1432 To set `cache_control` on a tool result, build the returned `BetaToolResultBlockParam.Content` with `ofBlocks()` instead of `ofString()` and set `cacheControl` on the inner text block. The runner does not currently support setting `cache_control` on the outer `tool_result` block.
14201433 
14211434 ```java
14221435 @JsonClassDescription("Look up reference documentation for a topic")
1423 static class SearchDocuments implements Supplier<BetaToolResultBlockParam.Content> {
1436 static class SearchDocuments {
14241437 @JsonPropertyDescription("The search query")
14251438 public String query;
1426 
1427 @Override
1428 public BetaToolResultBlockParam.Content get() {
1429 String largeResult = "..."; // a long document worth caching
1430 return BetaToolResultBlockParam.Content.ofBlocks(List.of(
1431 BetaToolResultBlockParam.Content.Block.ofText(
1432 BetaTextBlockParam.builder()
1433 .text(largeResult)
1434 .cacheControl(BetaCacheControlEphemeral.builder().build())
1435 .build())));
1436 }
14371439 }
1440 
1441 BetaRunnableTool searchDocuments = BetaRunnableTool.of(SearchDocuments.class, input -> {
1442 String largeResult = "..."; // a long document worth caching
1443 return BetaToolResultBlockParam.Content.ofBlocks(List.of(
1444 BetaToolResultBlockParam.Content.Block.ofText(
1445 BetaTextBlockParam.builder()
1446 .text(largeResult)
1447 .cacheControl(BetaCacheControlEphemeral.builder().build())
1448 .build())));
1449 });
14381450 ```
14391451 </Tab>
14401452 
from line 1680
16681680 .maxTokens(1024)
16691681 .addBeta("structured-outputs-2025-11-13")
16701682 .addUserMessage("What is 15 + 27?")
1671 .addTool(CalculateSum.class)
1683 .addTool(calculateSum)
16721684 .build());
16731685 
16741686 for (StreamResponse<BetaRawMessageStreamEvent> stream : runner.streaming()) {
Feedback