Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build LLM-powered apps with the Anthropic Claude API or SDK across Python, TypeScript, Java, Go, Ruby, C#, and PHP.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
java/claude-api/tool-use.md
1# Tool Use — Java23For conceptual overview (tool definitions, tool choice, tips), see [shared/tool-use-concepts.md](../../shared/tool-use-concepts.md).45## Tool Use (Beta)67The Java SDK supports beta tool use with annotated classes. Tool classes implement `Supplier<String>` for automatic execution via `BetaToolRunner`.89### Tool Runner (automatic loop)1011```java12import com.anthropic.models.beta.messages.MessageCreateParams;13import com.anthropic.models.beta.messages.BetaMessage;14import com.anthropic.helpers.BetaToolRunner;15import com.fasterxml.jackson.annotation.JsonClassDescription;16import com.fasterxml.jackson.annotation.JsonPropertyDescription;17import java.util.function.Supplier;1819@JsonClassDescription("Get the weather in a given location")20static class GetWeather implements Supplier<String> {21@JsonPropertyDescription("The city and state, e.g. San Francisco, CA")22public String location;2324@Override25public String get() {26return "The weather in " + location + " is sunny and 72°F";27}28}2930BetaToolRunner toolRunner = client.beta().messages().toolRunner(31MessageCreateParams.builder()32.model("claude-opus-4-8")33.maxTokens(16000L)34.putAdditionalHeader("anthropic-beta", "structured-outputs-2025-11-13")35.addTool(GetWeather.class)36.addUserMessage("What's the weather in San Francisco?")37.build());3839for (BetaMessage message : toolRunner) {40System.out.println(message);41}42```4344### Memory Tool4546The Java SDK provides `BetaMemoryToolHandler` for implementing the memory tool backend. You supply a handler that manages file storage, and the `BetaToolRunner` handles memory tool calls automatically.4748```java49import com.anthropic.helpers.BetaMemoryToolHandler;50import com.anthropic.helpers.BetaToolRunner;51import com.anthropic.models.beta.messages.BetaMemoryTool20250818;52import com.anthropic.models.beta.messages.BetaMessage;53import com.anthropic.models.beta.messages.MessageCreateParams;54import com.anthropic.models.beta.messages.ToolRunnerCreateParams;5556// Implement BetaMemoryToolHandler with your storage backend (e.g., filesystem)57BetaMemoryToolHandler memoryHandler = new FileSystemMemoryToolHandler(sandboxRoot);5859MessageCreateParams createParams = MessageCreateParams.builder()60.model("claude-opus-4-8")61.maxTokens(4096L)62.addTool(BetaMemoryTool20250818.builder().build())63.addUserMessage("Remember that my favorite color is blue")64.build();6566BetaToolRunner toolRunner = client.beta().messages().toolRunner(67ToolRunnerCreateParams.builder()68.betaMemoryToolHandler(memoryHandler)69.initialMessageParams(createParams)70.build());7172for (BetaMessage message : toolRunner) {73System.out.println(message);74}75```7677See the [shared memory tool concepts](../../shared/tool-use-concepts.md) for more details on the memory tool.7879### Non-Beta Tool Declaration (manual JSON schema)8081`Tool.InputSchema.Properties` is a freeform `Map<String, JsonValue>` wrapper — build property schemas via `putAdditionalProperty`. `type: "object"` is the default. The builder has a direct `.addTool(Tool)` overload that wraps in `ToolUnion` automatically.8283```java84import com.anthropic.core.JsonValue;85import com.anthropic.models.messages.Tool;8687Tool tool = Tool.builder()88.name("get_weather")89.description("Get the current weather in a given location")90.inputSchema(Tool.InputSchema.builder()91.properties(Tool.InputSchema.Properties.builder()92.putAdditionalProperty("location", JsonValue.from(Map.of("type", "string")))93.build())94.required(List.of("location"))95.build())96.build();9798MessageCreateParams params = MessageCreateParams.builder()99.model(Model.CLAUDE_SONNET_4_6)100.maxTokens(16000L)101.addTool(tool)102.addUserMessage("Weather in Paris?")103.build();104```105106For manual tool loops, handle `tool_use` blocks in the response, send `tool_result` back, loop until `stop_reason` is `"end_turn"`. See [shared tool use concepts](../../shared/tool-use-concepts.md).107108### Building `MessageParam` with Content Blocks (Tool Result Round-Trip)109110`MessageParam.Content` is an inner union class (string | list). Use the builder's `.contentOfBlockParams(List<ContentBlockParam>)` alias — there is NO separate `MessageParamContent` class with a static `ofBlockParams`:111112```java113import com.anthropic.models.messages.MessageParam;114import com.anthropic.models.messages.ContentBlockParam;115import com.anthropic.models.messages.ToolResultBlockParam;116117List<ContentBlockParam> results = List.of(118ContentBlockParam.ofToolResult(ToolResultBlockParam.builder()119.toolUseId(toolUseBlock.id())120.content(yourResultString)121.build())122);123124MessageParam toolResultMsg = MessageParam.builder()125.role(MessageParam.Role.USER)126.contentOfBlockParams(results) // builder alias for Content.ofBlockParams(...)127.build();128```129130---131132## Structured Output133134The class-based overload auto-derives the JSON schema from your POJO and gives you a typed `.text()` return — no manual schema, no manual parsing.135136```java137import com.anthropic.models.messages.StructuredMessageCreateParams;138139record Book(String title, String author) {}140record BookList(List<Book> books) {}141142StructuredMessageCreateParams<BookList> params = MessageCreateParams.builder()143.model(Model.CLAUDE_SONNET_4_6)144.maxTokens(16000L)145.outputConfig(BookList.class) // returns a typed builder146.addUserMessage("List 3 classic novels")147.build();148149client.messages().create(params).content().stream()150.flatMap(cb -> cb.text().stream())151.forEach(typed -> {152// typed.text() returns BookList, not String153for (Book b : typed.text().books()) System.out.println(b.title());154});155```156157Supports Jackson annotations: `@JsonPropertyDescription`, `@JsonIgnore`, `@ArraySchema(minItems=...)`. Manual schema path: `OutputConfig.builder().format(JsonOutputFormat.builder().schema(...).build())`.158159---160161## Anthropic-Defined Tools162163Version-suffixed types; `name`/`type` auto-set by builder. Direct `.addTool()` overloads exist for most tool types; where one is missing (newer or less-common tools — see the advisor note below), wrap via the union type's static factory: `.addTool(BetaToolUnion.of<ToolName>(builder…build()))`. Web search and code execution are server-executed; bash and text editor are client-executed (you handle the `tool_use` locally — see `shared/tool-use-concepts.md`).164165```java166import com.anthropic.models.messages.WebSearchTool20260209;167import com.anthropic.models.messages.ToolBash20250124;168import com.anthropic.models.messages.ToolTextEditor20250728;169import com.anthropic.models.messages.CodeExecutionTool20260120;170171.addTool(WebSearchTool20260209.builder()172.maxUses(5L) // optional173.allowedDomains(List.of("example.com")) // optional174.build())175.addTool(ToolBash20250124.builder().build())176.addTool(ToolTextEditor20250728.builder().build())177.addTool(CodeExecutionTool20260120.builder().build())178```179180Also available: `WebFetchTool20260209`, `MemoryTool20250818`, `ToolSearchToolBm25_20251119`. For the advisor tool, use `BetaAdvisorTool20260301` in the beta namespace with `.addBeta("advisor-tool-2026-03-01")` (server-side; advisor model ≥ executor model). There is no direct `.addTool(BetaAdvisorTool20260301)` overload on the beta builder — wrap it via the `BetaToolUnion` static factory for the advisor type; if `javac` rejects the specific factory method name, `javap com.anthropic.models.beta.messages.BetaToolUnion | grep -i advisor` shows the exact one.181182### Beta namespace (MCP, compaction)183184For beta-only features use `com.anthropic.models.beta.messages.*` — class names have a `Beta` prefix AND live in the beta package. The beta `MessageCreateParams.Builder` has direct `.addTool(BetaToolBash20250124)` overloads AND `.addMcpServer()`:185186```java187import com.anthropic.models.beta.messages.MessageCreateParams;188import com.anthropic.models.beta.messages.BetaToolBash20250124;189import com.anthropic.models.beta.messages.BetaCodeExecutionTool20260120;190import com.anthropic.models.beta.messages.BetaRequestMcpServerUrlDefinition;191192MessageCreateParams params = MessageCreateParams.builder()193.model(Model.CLAUDE_OPUS_4_8)194.maxTokens(16000L)195.addBeta("mcp-client-2025-11-20")196.addTool(BetaToolBash20250124.builder().build())197.addTool(BetaCodeExecutionTool20260120.builder().build())198.addMcpServer(BetaRequestMcpServerUrlDefinition.builder()199.name("my-server")200.url("https://example.com/mcp")201.build())202.addUserMessage("...")203.build();204205client.beta().messages().create(params);206```207208`BetaTool*` types are NOT interchangeable with non-beta `Tool*` — pick one namespace per request.209210**Reading server-tool blocks in the response:** `ServerToolUseBlock` has `.id()`, `.name()` (enum), and `._input()` returning raw `JsonValue` — there is NO typed `.input()`. For code execution results, unwrap two levels:211212```java213for (ContentBlock block : response.content()) {214block.serverToolUse().ifPresent(stu -> {215System.out.println("tool: " + stu.name() + " input: " + stu._input());216});217block.codeExecutionToolResult().ifPresent(r -> {218r.content().resultBlock().ifPresent(result -> {219System.out.println("stdout: " + result.stdout());220System.out.println("stderr: " + result.stderr());221System.out.println("exit: " + result.returnCode());222});223});224}225```226227---228229