diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index add56ef9e..b2a3d87b9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
- name: Set up Java
uses: actions/setup-java@v4
@@ -40,11 +40,14 @@ jobs:
build:
timeout-minutes: 15
name: build
+ permissions:
+ contents: read
+ id-token: write
runs-on: ${{ github.repository == 'stainless-sdks/anthropic-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
- name: Set up Java
uses: actions/setup-java@v4
@@ -61,13 +64,28 @@ jobs:
- name: Build SDK
run: ./scripts/build
+ - name: Get GitHub OIDC Token
+ if: github.repository == 'stainless-sdks/anthropic-java'
+ id: github-oidc
+ uses: actions/github-script@v6
+ with:
+ script: core.setOutput('github_token', await core.getIDToken());
+
+ - name: Build and upload Maven artifacts
+ if: github.repository == 'stainless-sdks/anthropic-java'
+ env:
+ URL: https://pkg.stainless.com/s
+ AUTH: ${{ steps.github-oidc.outputs.github_token }}
+ SHA: ${{ github.sha }}
+ PROJECT: anthropic-java
+ run: ./scripts/upload-artifacts
test:
timeout-minutes: 15
name: test
runs-on: ${{ github.repository == 'stainless-sdks/anthropic-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
- name: Set up Java
uses: actions/setup-java@v4
diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml
new file mode 100644
index 000000000..a4c8f6a89
--- /dev/null
+++ b/.github/workflows/claude-code-review.yml
@@ -0,0 +1,57 @@
+name: Claude Code Review
+
+on:
+ pull_request:
+ types: [opened, synchronize]
+ # Optional: Only run on specific file changes
+ # paths:
+ # - "src/**/*.ts"
+ # - "src/**/*.tsx"
+ # - "src/**/*.js"
+ # - "src/**/*.jsx"
+
+jobs:
+ claude-review:
+ # Optional: Filter by PR author
+ # if: |
+ # github.event.pull_request.user.login == 'external-contributor' ||
+ # github.event.pull_request.user.login == 'new-developer' ||
+ # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
+
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: read
+ issues: read
+ id-token: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 1
+
+ - name: Run Claude Code Review
+ id: claude-review
+ uses: anthropics/claude-code-action@v1
+ with:
+ anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
+ prompt: |
+ REPO: ${{ github.repository }}
+ PR NUMBER: ${{ github.event.pull_request.number }}
+
+ Please review this pull request and provide feedback on:
+ - Code quality and best practices
+ - Potential bugs or issues
+ - Performance considerations
+ - Security concerns
+ - Test coverage
+
+ Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.
+
+ Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.
+
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
+ # or https://code.claude.com/docs/en/cli-reference for available options
+ claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'
+
diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml
new file mode 100644
index 000000000..79fe05647
--- /dev/null
+++ b/.github/workflows/claude.yml
@@ -0,0 +1,50 @@
+name: Claude Code
+
+on:
+ issue_comment:
+ types: [created]
+ pull_request_review_comment:
+ types: [created]
+ issues:
+ types: [opened, assigned]
+ pull_request_review:
+ types: [submitted]
+
+jobs:
+ claude:
+ if: |
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: read
+ issues: read
+ id-token: write
+ actions: read # Required for Claude to read CI results on PRs
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 1
+
+ - name: Run Claude Code
+ id: claude
+ uses: anthropics/claude-code-action@v1
+ with:
+ anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
+
+ # This is an optional setting that allows Claude to read CI results on PRs
+ additional_permissions: |
+ actions: read
+
+ # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
+ # prompt: 'Update the pull request description to include a summary of changes.'
+
+ # Optional: Add claude_args to customize behavior and configuration
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
+ # or https://code.claude.com/docs/en/cli-reference for available options
+ # claude_args: '--allowed-tools Bash(gh pr:*)'
+
diff --git a/.github/workflows/create-releases.yml b/.github/workflows/create-releases.yml
index d357b52ea..857136025 100644
--- a/.github/workflows/create-releases.yml
+++ b/.github/workflows/create-releases.yml
@@ -14,7 +14,7 @@ jobs:
environment: production-release
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
- uses: stainless-api/trigger-release-please@v1
id: release
diff --git a/.github/workflows/detect-breaking-changes.yml b/.github/workflows/detect-breaking-changes.yml
index c830916cd..fd4ce3351 100644
--- a/.github/workflows/detect-breaking-changes.yml
+++ b/.github/workflows/detect-breaking-changes.yml
@@ -15,7 +15,7 @@ jobs:
run: |
echo "FETCH_DEPTH=$(expr ${{ github.event.pull_request.commits }} + 1)" >> $GITHUB_ENV
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
with:
# Ensure we can check out the pull request base in the script below.
fetch-depth: ${{ env.FETCH_DEPTH }}
diff --git a/.github/workflows/publish-sonatype.yml b/.github/workflows/publish-sonatype.yml
index 16037fffc..e44b9dfa7 100644
--- a/.github/workflows/publish-sonatype.yml
+++ b/.github/workflows/publish-sonatype.yml
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
- name: Set up Java
uses: actions/setup-java@v4
diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml
index df93f731a..06b970ce4 100644
--- a/.github/workflows/release-doctor.yml
+++ b/.github/workflows/release-doctor.yml
@@ -13,7 +13,7 @@ jobs:
if: github.repository == 'anthropics/anthropic-sdk-java' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next')
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
- name: Check release environment
run: |
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index c9ba66432..0746cbe20 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "2.11.1"
+ ".": "2.12.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index d60086d1e..ef0794149 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 34
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic%2Fanthropic-2f35b2ff9174d526a6d35796d2703490bfa5692312af67cbdfa4500283dabe31.yml
-openapi_spec_hash: dc52b25c487e97d355ef645644aa13e7
-config_hash: d23c4d678fcf7ff829a2891b3196edb6
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic%2Fanthropic-f7bcdc13402c6129b30be620021a724945de44cffc6add091798f9cce33a1e32.yml
+openapi_spec_hash: e78807e31b9233abc50ccc00304bfa4d
+config_hash: 92ca93edc068c543f2da38737239322d
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9f1f86894..e01dacb7c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,48 @@
# Changelog
+## 2.12.0 (2026-01-16)
+
+Full Changelog: [v2.11.1...v2.12.0](https://github.com/anthropics/anthropic-sdk-java/compare/v2.11.1...v2.12.0)
+
+### Features
+
+* **api:** Add new methods to tests ([#748](https://github.com/anthropics/anthropic-sdk-java/issues/748)) ([2c2ebdc](https://github.com/anthropics/anthropic-sdk-java/commit/2c2ebdc6a732b4adf595dbe1b422da1b02fc000f))
+* **api:** adds support for Claude Opus 4.5, Effort, Advance Tool Use Features, Autocompaction, and Computer Use v5 ([4689271](https://github.com/anthropics/anthropic-sdk-java/commit/4689271c4dba2de056356d314429af36b7ad7205))
+* **api:** migrate sending message format in output_config rather than output_format ([c0103c6](https://github.com/anthropics/anthropic-sdk-java/commit/c0103c6f83ce4df65bab9aaa7def6d628c644a64))
+* **api:** migrate sending message format in output_config rather than output_format ([a6ea665](https://github.com/anthropics/anthropic-sdk-java/commit/a6ea6657640fcd0ec4c9645503d0d87843ec094b))
+* **client:** add `HttpRequest#url()` method ([49afe52](https://github.com/anthropics/anthropic-sdk-java/commit/49afe52d1f478b167d343a94e703d75abc5e09ba))
+* **client:** allow configuring dispatcher executor service ([60554ea](https://github.com/anthropics/anthropic-sdk-java/commit/60554eafb104057399672deefe0bbdb9b82c64bb))
+* **client:** support Anthropic models on Microsoft Foundry ([#698](https://github.com/anthropics/anthropic-sdk-java/issues/698)) ([8077051](https://github.com/anthropics/anthropic-sdk-java/commit/80770511530e0a897d55aeebcaa307d679147f1d))
+
+
+### Bug Fixes
+
+* **client:** BetaMessageAccumulator crash on empty tool input ([e0fe678](https://github.com/anthropics/anthropic-sdk-java/commit/e0fe6788bd8a5529fdc493e73cbc532497622bc3))
+* **client:** cancel okhttp call when future cancelled ([b52f783](https://github.com/anthropics/anthropic-sdk-java/commit/b52f7831db730af1e398df4362b84002f82d025e))
+* **client:** disallow coercion from float to int ([492286b](https://github.com/anthropics/anthropic-sdk-java/commit/492286bc3dfe1848cfa4b3002f0578124a68b00f))
+* **client:** implement visitToolSearchToolResult for Beta Accumulator ([41191ed](https://github.com/anthropics/anthropic-sdk-java/commit/41191edae162caaf9572c5d1d786160413bdc39c))
+* **client:** run linter ([73e141d](https://github.com/anthropics/anthropic-sdk-java/commit/73e141d1df0cd094f6544b2bd51d5fccf989f28a))
+* date time deserialization leniency ([f6f7ad1](https://github.com/anthropics/anthropic-sdk-java/commit/f6f7ad13a7774c92079dbed38944369f519ebcf8))
+
+
+### Chores
+
+* **ci:** add Claude Code GitHub Workflow ([4eec6e8](https://github.com/anthropics/anthropic-sdk-java/commit/4eec6e844e9914150462ccbe017be1f2acfcd34a))
+* **client:** mark claude-3-5-haiku as deprecated ([46bf679](https://github.com/anthropics/anthropic-sdk-java/commit/46bf679190664f37269dabcefcff82c4bad7f899))
+* fix merge conflict ([e307fa0](https://github.com/anthropics/anthropic-sdk-java/commit/e307fa0b01207b77210cfc1c6957ca8f4ffbfb5b))
+* fix test ([b612010](https://github.com/anthropics/anthropic-sdk-java/commit/b612010dd341f8f7ebcdf2cd719db9f45ef36841))
+* **internal:** clean up maven repo artifact script and add html documentation to repo root ([d319dd7](https://github.com/anthropics/anthropic-sdk-java/commit/d319dd7ac5f06a1a575f5cb9ad8508a4b5d365d3))
+* **internal:** improve maven repo docs ([852f6dc](https://github.com/anthropics/anthropic-sdk-java/commit/852f6dcc104540ef4871e94de2ed1b9f714f341a))
+* **internal:** support uploading Maven repo artifacts to stainless package server ([17e663a](https://github.com/anthropics/anthropic-sdk-java/commit/17e663afa3096c8869bcce18aa2753f23b3320c0))
+* **internal:** update `actions/checkout` version ([7fd4f0a](https://github.com/anthropics/anthropic-sdk-java/commit/7fd4f0aeed9b6dee1d94361b0c654339f3cfb5ba))
+* **internal:** use different example values for some enums ([5d45a2f](https://github.com/anthropics/anthropic-sdk-java/commit/5d45a2fbd45aa2fb6561063f80bc2ca984a76150))
+* test on Jackson 2.14.0 to avoid encountering FasterXML/jackson-databind[#3240](https://github.com/anthropics/anthropic-sdk-java/issues/3240) in tests ([f6f7ad1](https://github.com/anthropics/anthropic-sdk-java/commit/f6f7ad13a7774c92079dbed38944369f519ebcf8))
+
+
+### Documentation
+
+* remove `$` for better copy-pasteabality ([b2315f9](https://github.com/anthropics/anthropic-sdk-java/commit/b2315f9d756ad473cd52c4daf52590341e9d3bce))
+
## 2.11.1 (2025-11-19)
Full Changelog: [v2.11.0...v2.11.1](https://github.com/anthropics/anthropic-sdk-java/compare/v2.11.0...v2.11.1)
diff --git a/README.md b/README.md
index aefcd052b..c3f070181 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,8 @@
-[](https://central.sonatype.com/artifact/com.anthropic/anthropic-java/2.11.1)
-[](https://javadoc.io/doc/com.anthropic/anthropic-java/2.11.1)
+[](https://central.sonatype.com/artifact/com.anthropic/anthropic-java/2.12.0)
+[](https://javadoc.io/doc/com.anthropic/anthropic-java/2.12.0)
@@ -11,7 +11,7 @@ The Anthropic Java SDK provides convenient access to the [Anthropic REST API](ht
-The REST API documentation can be found on [docs.anthropic.com](https://docs.anthropic.com/claude/reference/). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.anthropic/anthropic-java/2.11.1).
+The REST API documentation can be found on [docs.anthropic.com](https://docs.anthropic.com/claude/reference/). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.anthropic/anthropic-java/2.12.0).
@@ -22,7 +22,7 @@ The REST API documentation can be found on [docs.anthropic.com](https://docs.ant
### Gradle
```kotlin
-implementation("com.anthropic:anthropic-java:2.11.1")
+implementation("com.anthropic:anthropic-java:2.12.0")
```
### Maven
@@ -31,7 +31,7 @@ implementation("com.anthropic:anthropic-java:2.11.1")
com.anthropic
anthropic-java
- 2.11.1
+ 2.12.0
```
@@ -59,7 +59,7 @@ AnthropicClient client = AnthropicOkHttpClient.fromEnv();
MessageCreateParams params = MessageCreateParams.builder()
.maxTokens(1024L)
.addUserMessage("Hello, Claude")
- .model(Model.CLAUDE_SONNET_4_20250514)
+ .model(Model.CLAUDE_SONNET_4_5_20250929)
.build();
Message message = client.messages().create(params);
```
@@ -173,7 +173,7 @@ AnthropicClient client = AnthropicOkHttpClient.fromEnv();
MessageCreateParams params = MessageCreateParams.builder()
.maxTokens(1024L)
.addUserMessage("Hello, Claude")
- .model(Model.CLAUDE_SONNET_4_20250514)
+ .model(Model.CLAUDE_SONNET_4_5_20250929)
.build();
CompletableFuture message = client.async().messages().create(params);
```
@@ -195,7 +195,7 @@ AnthropicClientAsync client = AnthropicOkHttpClientAsync.fromEnv();
MessageCreateParams params = MessageCreateParams.builder()
.maxTokens(1024L)
.addUserMessage("Hello, Claude")
- .model(Model.CLAUDE_SONNET_4_20250514)
+ .model(Model.CLAUDE_SONNET_4_5_20250929)
.build();
CompletableFuture message = client.messages().create(params);
```
@@ -975,7 +975,7 @@ import com.anthropic.models.messages.Model;
MessageCreateParams params = MessageCreateParams.builder()
.maxTokens(1024L)
.addUserMessage("Hello, Claude")
- .model(Model.CLAUDE_SONNET_4_20250514)
+ .model(Model.CLAUDE_SONNET_4_5_20250929)
.build();
HttpResponseFor message = client.messages().withRawResponse().create(params);
@@ -1146,16 +1146,16 @@ requires the `anthropic-java-bedrock` library dependency.
### Gradle
```kotlin
-implementation("com.anthropic:anthropic-java-bedrock:2.11.1")
+implementation("com.anthropic:anthropic-java-bedrock:2.12.0")
```
### Maven
```xml
- com.anthropic
- anthropic-java-bedrock
- 2.11.1
+ com.anthropic
+ anthropic-java-bedrock
+ 2.12.0
```
@@ -1279,16 +1279,16 @@ This support requires the `anthropic-java-vertex` library dependency.
### Gradle
```kotlin
-implementation("com.anthropic:anthropic-java-vertex:2.11.1")
+implementation("com.anthropic:anthropic-java-vertex:2.12.0")
```
### Maven
```xml
- com.anthropic
- anthropic-java-vertex
- 2.11.1
+ com.anthropic
+ anthropic-java-vertex
+ 2.12.0
```
@@ -1297,7 +1297,8 @@ implementation("com.anthropic:anthropic-java-vertex:2.11.1")
### Usage
To use Anthropic on Vertex AI, create the Anthropic client with the
-`VertexBackend`. Usage of the API is otherwise the same.
+[`VertexBackend`](anthropic-java-vertex/src/main/kotlin/com/anthropic/vertex/backends/VertexBackend.kt).
+Usage of the API is otherwise the same.
```java
import com.anthropic.client.AnthropicClient;
@@ -1353,6 +1354,132 @@ Currently, the Vertex backend does _not_ support the following:
- Anthropic Batch API
+## Microsoft Foundry
+
+This SDK also provides support for Anthropic Claude models on the
+[Microsoft Foundry](https://azure.microsoft.com/en-us/products/ai-foundry) platform. This support
+requires the `anthropic-java-foundry` library dependency.
+
+
+
+### Gradle
+
+```kotlin
+implementation("com.anthropic:anthropic-java-foundry:2.12.0")
+```
+
+### Maven
+
+```xml
+
+ com.anthropic
+ anthropic-java-foundry
+ 2.12.0
+
+```
+
+
+
+### Usage
+
+To use Claude on Microsoft Foundry, create the Anthropic client with the
+[`FoundryBackend`](anthropic-java-foundry/src/main/kotlin/com/anthropic/foundry/backends/FoundryBackend.kt).
+Usage of the API is otherwise the same.
+
+```java
+import com.anthropic.client.AnthropicClient;
+import com.anthropic.client.okhttp.AnthropicOkHttpClient;
+import com.anthropic.foundry.backends.FoundryBackend;
+
+AnthropicClient client = AnthropicOkHttpClient.builder()
+ .backend(FoundryBackend.fromEnv())
+ .build();
+```
+
+`FoundryBackend.fromEnv()` automatically resolves the Foundry API key and the Foundry resource name
+or base URL from environment variables.
+
+ - Set `ANTHROPIC_FOUNDRY_API_KEY` to the API key for your Foundry resource.
+ - Set `ANTHROPIC_FOUNDRY_RESOURCE` to the name of the Foundry resource.
+ - Set `ANTHROPIC_FOUNDRY_BASE_URL` to the custom base URL for your resource. If not set, the
+ default Foundry base URL (incorporating your resource name) will be used.
+
+If defined, the base URL will include a resource name. You must set either the resource name or the
+base URL, but not both.
+
+Instead of resolving the API key and resource name or base URL automatically using `fromEnv()`, you
+can resolve them independently using an alternative Foundry facility, or any scheme of your choice,
+and pass them directly to the `FoundryBackend` during building. For example, you could resolve the
+API key directly from an environment variable and hard-code the resource name:
+
+```java
+import com.anthropic.client.AnthropicClient;
+import com.anthropic.client.okhttp.AnthropicOkHttpClient;
+import com.anthropic.foundry.backends.FoundryBackend;
+
+String apiKey = System.getenv("ANTHROPIC_FOUNDRY_API_KEY");
+
+AnthropicClient client = AnthropicOkHttpClient.builder()
+ .backend(FoundryBackend.builder()
+ .apiKey(apiKey)
+ .resource("my-foundry-resource")
+ .build())
+ .build();
+```
+
+You can also set a custom base URL instead of a resource name with `FoundryBackend.Builder.baseUrl`.
+
+Currently, the Foundry backend does _not_ support the following:
+
+- Anthropic Text Completions API
+- Anthropic Batch API
+- Anthropic Admin API
+- Anthropic Models API
+- Anthropic Experimental APIs
+
+### Usage with a token supplier
+
+The SDK supports request authorization for Foundry endpoints using a token supplier. This may be
+used to implement authorization using
+[Microsoft Entra ID](https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id),
+or other authorization scheme supported by the service.
+
+For each service request, a new call is issued to the `get()` method your implementation of a
+[`Supplier`](https://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html).
+The result of the method call is set as the value of the `Bearer` in the request `authorization`
+header.
+
+To use a token supplier to supply an Entra ID token for authorization, set the client ID, tenant ID
+and client secret in environment variables (or some other secure source), implement a token
+supplier, and set that on the `FoundryBackend`. In the following example, assume that the required
+values are set in the `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, and `AZURE_CLIENT_SECRET` environment
+variables.
+
+For Entra ID authorization, you will need the
+[Azure Identity client library](https://learn.microsoft.com/en-us/java/api/overview/azure/identity-readme?view=azure-java-stable).
+See that documentation for details on the configuration of the necessary dependencies.
+
+```java
+import com.anthropic.client.AnthropicClient;
+import com.anthropic.client.okhttp.AnthropicOkHttpClient;
+import com.anthropic.foundry.backends.FoundryBackend;
+import com.azure.identity.AuthenticationUtil;
+import com.azure.identity.DefaultAzureCredentialBuilder;
+import java.util.function.Supplier;
+
+Supplier bearerTokenSupplier = AuthenticationUtil.getBearerTokenSupplier(
+ new DefaultAzureCredentialBuilder().build(),
+ "https://cognitiveservices.azure.com/.default"
+);
+
+AnthropicClient client = AnthropicOkHttpClient.builder()
+ .backend(FoundryBackend.builder()
+ .bearerTokenSupplier(bearerTokenSupplier)
+ .resource("my-foundry-resource")
+ .build())
+ .build();
+```
+
## Logging
The SDK uses the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor).
@@ -1360,13 +1487,13 @@ The SDK uses the standard [OkHttp logging interceptor](https://github.com/square
Enable logging by setting the `ANTHROPIC_LOG` environment variable to `info`:
```sh
-$ export ANTHROPIC_LOG=info
+export ANTHROPIC_LOG=info
```
Or to `debug` for more verbose logging:
```sh
-$ export ANTHROPIC_LOG=debug
+export ANTHROPIC_LOG=debug
```
## ProGuard and R8
@@ -1386,6 +1513,8 @@ If the SDK threw an exception, but you're _certain_ the version is compatible, t
> [!CAUTION]
> We make no guarantee that the SDK works correctly when the Jackson version check is disabled.
+Also note that there are bugs in older Jackson versions that can affect the SDK. We don't work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead.
+
## Network options
### Retries
@@ -1586,7 +1715,7 @@ import com.anthropic.models.messages.Model;
MessageCreateParams params = MessageCreateParams.builder()
.maxTokens(JsonValue.from(3.14))
.addUserMessage("Hello, Claude")
- .model(Model.CLAUDE_SONNET_4_20250514)
+ .model(Model.CLAUDE_SONNET_4_5_20250929)
.build();
```
@@ -1640,7 +1769,7 @@ import com.anthropic.models.messages.Model;
MessageCreateParams params = MessageCreateParams.builder()
.addUserMessage("Hello, world")
- .model(Model.CLAUDE_SONNET_4_20250514)
+ .model(Model.CLAUDE_SONNET_4_5_20250929)
.maxTokens(JsonMissing.of())
.build();
```
diff --git a/anthropic-java-client-okhttp/build.gradle.kts b/anthropic-java-client-okhttp/build.gradle.kts
index b43c2e6e7..e5ba5c32a 100644
--- a/anthropic-java-client-okhttp/build.gradle.kts
+++ b/anthropic-java-client-okhttp/build.gradle.kts
@@ -11,4 +11,5 @@ dependencies {
testImplementation(kotlin("test"))
testImplementation("org.assertj:assertj-core:3.25.3")
+ testImplementation("com.github.tomakehurst:wiremock-jre8:2.35.2")
}
diff --git a/anthropic-java-client-okhttp/src/main/kotlin/com/anthropic/client/okhttp/AnthropicOkHttpClient.kt b/anthropic-java-client-okhttp/src/main/kotlin/com/anthropic/client/okhttp/AnthropicOkHttpClient.kt
index 74e5edd2e..1a1d903dc 100644
--- a/anthropic-java-client-okhttp/src/main/kotlin/com/anthropic/client/okhttp/AnthropicOkHttpClient.kt
+++ b/anthropic-java-client-okhttp/src/main/kotlin/com/anthropic/client/okhttp/AnthropicOkHttpClient.kt
@@ -20,6 +20,7 @@ import java.time.Clock
import java.time.Duration
import java.util.Optional
import java.util.concurrent.Executor
+import java.util.concurrent.ExecutorService
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
@@ -48,6 +49,7 @@ class AnthropicOkHttpClient private constructor() {
class Builder internal constructor() {
private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
+ private var dispatcherExecutorService: ExecutorService? = null
private var proxy: Proxy? = null
private var sslSocketFactory: SSLSocketFactory? = null
private var trustManager: X509TrustManager? = null
@@ -55,6 +57,25 @@ class AnthropicOkHttpClient private constructor() {
private var backend: Backend? = null
private var defaultBackendBuilder: AnthropicBackend.Builder? = null
+ /**
+ * The executor service to use for running HTTP requests.
+ *
+ * Defaults to OkHttp's
+ * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104).
+ *
+ * This class takes ownership of the executor service and shuts it down when closed.
+ */
+ fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply {
+ this.dispatcherExecutorService = dispatcherExecutorService
+ }
+
+ /**
+ * Alias for calling [Builder.dispatcherExecutorService] with
+ * `dispatcherExecutorService.orElse(null)`.
+ */
+ fun dispatcherExecutorService(dispatcherExecutorService: Optional) =
+ dispatcherExecutorService(dispatcherExecutorService.getOrNull())
+
fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }
/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
@@ -356,6 +377,7 @@ class AnthropicOkHttpClient private constructor() {
OkHttpClient.builder()
.timeout(clientOptions.timeout())
.proxy(proxy)
+ .dispatcherExecutorService(dispatcherExecutorService)
.sslSocketFactory(sslSocketFactory)
.trustManager(trustManager)
.hostnameVerifier(hostnameVerifier)
diff --git a/anthropic-java-client-okhttp/src/main/kotlin/com/anthropic/client/okhttp/AnthropicOkHttpClientAsync.kt b/anthropic-java-client-okhttp/src/main/kotlin/com/anthropic/client/okhttp/AnthropicOkHttpClientAsync.kt
index 2004460ff..cd9fd73d0 100644
--- a/anthropic-java-client-okhttp/src/main/kotlin/com/anthropic/client/okhttp/AnthropicOkHttpClientAsync.kt
+++ b/anthropic-java-client-okhttp/src/main/kotlin/com/anthropic/client/okhttp/AnthropicOkHttpClientAsync.kt
@@ -20,6 +20,7 @@ import java.time.Clock
import java.time.Duration
import java.util.Optional
import java.util.concurrent.Executor
+import java.util.concurrent.ExecutorService
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
@@ -48,6 +49,7 @@ class AnthropicOkHttpClientAsync private constructor() {
class Builder internal constructor() {
private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
+ private var dispatcherExecutorService: ExecutorService? = null
private var proxy: Proxy? = null
private var sslSocketFactory: SSLSocketFactory? = null
private var trustManager: X509TrustManager? = null
@@ -55,6 +57,25 @@ class AnthropicOkHttpClientAsync private constructor() {
private var backend: Backend? = null
private var defaultBackendBuilder: AnthropicBackend.Builder? = null
+ /**
+ * The executor service to use for running HTTP requests.
+ *
+ * Defaults to OkHttp's
+ * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104).
+ *
+ * This class takes ownership of the executor service and shuts it down when closed.
+ */
+ fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply {
+ this.dispatcherExecutorService = dispatcherExecutorService
+ }
+
+ /**
+ * Alias for calling [Builder.dispatcherExecutorService] with
+ * `dispatcherExecutorService.orElse(null)`.
+ */
+ fun dispatcherExecutorService(dispatcherExecutorService: Optional) =
+ dispatcherExecutorService(dispatcherExecutorService.getOrNull())
+
fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }
/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
@@ -356,6 +377,7 @@ class AnthropicOkHttpClientAsync private constructor() {
OkHttpClient.builder()
.timeout(clientOptions.timeout())
.proxy(proxy)
+ .dispatcherExecutorService(dispatcherExecutorService)
.sslSocketFactory(sslSocketFactory)
.trustManager(trustManager)
.hostnameVerifier(hostnameVerifier)
diff --git a/anthropic-java-client-okhttp/src/main/kotlin/com/anthropic/client/okhttp/OkHttpClient.kt b/anthropic-java-client-okhttp/src/main/kotlin/com/anthropic/client/okhttp/OkHttpClient.kt
index 691d367de..b2592f84d 100644
--- a/anthropic-java-client-okhttp/src/main/kotlin/com/anthropic/client/okhttp/OkHttpClient.kt
+++ b/anthropic-java-client-okhttp/src/main/kotlin/com/anthropic/client/okhttp/OkHttpClient.kt
@@ -15,12 +15,15 @@ import java.io.IOException
import java.io.InputStream
import java.net.Proxy
import java.time.Duration
+import java.util.concurrent.CancellationException
import java.util.concurrent.CompletableFuture
+import java.util.concurrent.ExecutorService
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
import okhttp3.Call
import okhttp3.Callback
+import okhttp3.Dispatcher
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaType
@@ -32,8 +35,10 @@ import okhttp3.logging.HttpLoggingInterceptor
import okio.BufferedSink
class OkHttpClient
-private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val backend: Backend) :
- HttpClient {
+private constructor(
+ @JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClient,
+ private val backend: Backend,
+) : HttpClient {
override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse {
val preparedRequest = prepareRequest(request)
@@ -55,20 +60,25 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
val preparedRequest = prepareRequest(request)
val future = CompletableFuture()
- preparedRequest.body?.run { future.whenComplete { _, _ -> close() } }
-
- newCall(preparedRequest, requestOptions)
- .enqueue(
- object : Callback {
- override fun onResponse(call: Call, response: Response) {
- future.complete(backend.prepareResponse(response.toResponse()))
- }
+ val call = newCall(preparedRequest, requestOptions)
+ call.enqueue(
+ object : Callback {
+ override fun onResponse(call: Call, response: Response) {
+ future.complete(backend.prepareResponse(response.toResponse()))
+ }
- override fun onFailure(call: Call, e: IOException) {
- future.completeExceptionally(AnthropicIoException("Request failed", e))
- }
+ override fun onFailure(call: Call, e: IOException) {
+ future.completeExceptionally(AnthropicIoException("Request failed", e))
}
- )
+ }
+ )
+
+ future.whenComplete { _, e ->
+ if (e is CancellationException) {
+ call.cancel()
+ }
+ preparedRequest.body?.close()
+ }
return future
}
@@ -214,6 +224,8 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
private var timeout: Timeout = Timeout.default()
private var proxy: Proxy? = null
private var backend: Backend? = null
+
+ private var dispatcherExecutorService: ExecutorService? = null
private var sslSocketFactory: SSLSocketFactory? = null
private var trustManager: X509TrustManager? = null
private var hostnameVerifier: HostnameVerifier? = null
@@ -226,6 +238,10 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
fun backend(backend: Backend) = apply { this.backend = backend }
+ fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply {
+ this.dispatcherExecutorService = dispatcherExecutorService
+ }
+
fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply {
this.sslSocketFactory = sslSocketFactory
}
@@ -248,6 +264,8 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
.callTimeout(timeout.request())
.proxy(proxy)
.apply {
+ dispatcherExecutorService?.let { dispatcher(Dispatcher(it)) }
+
val sslSocketFactory = sslSocketFactory
val trustManager = trustManager
if (sslSocketFactory != null && trustManager != null) {
diff --git a/anthropic-java-client-okhttp/src/test/kotlin/com/anthropic/client/okhttp/OkHttpClientTest.kt b/anthropic-java-client-okhttp/src/test/kotlin/com/anthropic/client/okhttp/OkHttpClientTest.kt
new file mode 100644
index 000000000..9ec156c2c
--- /dev/null
+++ b/anthropic-java-client-okhttp/src/test/kotlin/com/anthropic/client/okhttp/OkHttpClientTest.kt
@@ -0,0 +1,51 @@
+package com.anthropic.client.okhttp
+
+import com.anthropic.backends.Backend
+import com.anthropic.core.http.HttpMethod
+import com.anthropic.core.http.HttpRequest
+import com.github.tomakehurst.wiremock.client.WireMock.*
+import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo
+import com.github.tomakehurst.wiremock.junit5.WireMockTest
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.parallel.ResourceLock
+
+@WireMockTest
+@ResourceLock("https://github.com/wiremock/wiremock/issues/169")
+internal class OkHttpClientTest {
+
+ private class TestBackend(private val baseUrl: String) : Backend {
+ override fun baseUrl(): String = baseUrl
+
+ override fun close() {}
+ }
+
+ private lateinit var baseUrl: String
+ private lateinit var httpClient: OkHttpClient
+
+ @BeforeEach
+ fun beforeEach(wmRuntimeInfo: WireMockRuntimeInfo) {
+ baseUrl = wmRuntimeInfo.httpBaseUrl
+ httpClient = OkHttpClient.builder().backend(TestBackend(baseUrl)).build()
+ }
+
+ @Test
+ fun executeAsync_whenFutureCancelled_cancelsUnderlyingCall() {
+ stubFor(post(urlPathEqualTo("/something")).willReturn(ok()))
+ val responseFuture =
+ httpClient.executeAsync(
+ HttpRequest.builder()
+ .method(HttpMethod.POST)
+ .baseUrl(baseUrl)
+ .addPathSegment("something")
+ .build()
+ )
+ val call = httpClient.okHttpClient.dispatcher.runningCalls().single()
+
+ responseFuture.cancel(false)
+
+ // Should have cancelled the underlying call
+ assertThat(call.isCanceled()).isTrue()
+ }
+}
diff --git a/anthropic-java-core/build.gradle.kts b/anthropic-java-core/build.gradle.kts
index 99b623fda..969ce622d 100644
--- a/anthropic-java-core/build.gradle.kts
+++ b/anthropic-java-core/build.gradle.kts
@@ -5,14 +5,16 @@ plugins {
configurations.all {
resolutionStrategy {
- // Compile and test against a lower Jackson version to ensure we're compatible with it.
- // We publish with a higher version (see below) to ensure users depend on a secure version by default.
- force("com.fasterxml.jackson.core:jackson-core:2.13.4")
- force("com.fasterxml.jackson.core:jackson-databind:2.13.4")
- force("com.fasterxml.jackson.core:jackson-annotations:2.13.4")
- force("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.4")
- force("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.4")
- force("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.4")
+ // Compile and test against a lower Jackson version to ensure we're compatible with it. Note that
+ // we generally support 2.13.4, but test against 2.14.0 because 2.13.4 has some annoying (but
+ // niche) bugs (users should upgrade if they encounter them). We publish with a higher version
+ // (see below) to ensure users depend on a secure version by default.
+ force("com.fasterxml.jackson.core:jackson-core:2.14.0")
+ force("com.fasterxml.jackson.core:jackson-databind:2.14.0")
+ force("com.fasterxml.jackson.core:jackson-annotations:2.14.0")
+ force("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.14.0")
+ force("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.0")
+ force("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.0")
}
}
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/core/ObjectMappers.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/core/ObjectMappers.kt
index 9c38f4fb9..22c20f88c 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/core/ObjectMappers.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/core/ObjectMappers.kt
@@ -24,6 +24,7 @@ import java.io.InputStream
import java.time.DateTimeException
import java.time.LocalDate
import java.time.LocalDateTime
+import java.time.OffsetDateTime
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoField
@@ -36,7 +37,7 @@ fun jsonMapper(): JsonMapper =
.addModule(
SimpleModule()
.addSerializer(InputStreamSerializer)
- .addDeserializer(LocalDateTime::class.java, LenientLocalDateTimeDeserializer())
+ .addDeserializer(OffsetDateTime::class.java, LenientOffsetDateTimeDeserializer())
)
.withCoercionConfig(LogicalType.Boolean) {
it.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail)
@@ -47,6 +48,7 @@ fun jsonMapper(): JsonMapper =
}
.withCoercionConfig(LogicalType.Integer) {
it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail)
+ .setCoercion(CoercionInputShape.Float, CoercionAction.Fail)
.setCoercion(CoercionInputShape.String, CoercionAction.Fail)
.setCoercion(CoercionInputShape.Array, CoercionAction.Fail)
.setCoercion(CoercionInputShape.Object, CoercionAction.Fail)
@@ -64,6 +66,12 @@ fun jsonMapper(): JsonMapper =
.setCoercion(CoercionInputShape.Array, CoercionAction.Fail)
.setCoercion(CoercionInputShape.Object, CoercionAction.Fail)
}
+ .withCoercionConfig(LogicalType.DateTime) {
+ it.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail)
+ .setCoercion(CoercionInputShape.Float, CoercionAction.Fail)
+ .setCoercion(CoercionInputShape.Array, CoercionAction.Fail)
+ .setCoercion(CoercionInputShape.Object, CoercionAction.Fail)
+ }
.withCoercionConfig(LogicalType.Array) {
it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail)
.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail)
@@ -124,10 +132,10 @@ private object InputStreamSerializer : BaseSerializer(InputStream::
}
/**
- * A deserializer that can deserialize [LocalDateTime] from datetimes, dates, and zoned datetimes.
+ * A deserializer that can deserialize [OffsetDateTime] from datetimes, dates, and zoned datetimes.
*/
-private class LenientLocalDateTimeDeserializer :
- StdDeserializer(LocalDateTime::class.java) {
+private class LenientOffsetDateTimeDeserializer :
+ StdDeserializer(OffsetDateTime::class.java) {
companion object {
@@ -141,7 +149,7 @@ private class LenientLocalDateTimeDeserializer :
override fun logicalType(): LogicalType = LogicalType.DateTime
- override fun deserialize(p: JsonParser, context: DeserializationContext?): LocalDateTime {
+ override fun deserialize(p: JsonParser, context: DeserializationContext): OffsetDateTime {
val exceptions = mutableListOf()
for (formatter in DATE_TIME_FORMATTERS) {
@@ -149,18 +157,20 @@ private class LenientLocalDateTimeDeserializer :
val temporal = formatter.parse(p.text)
return when {
- !temporal.isSupported(ChronoField.HOUR_OF_DAY) ->
- LocalDate.from(temporal).atStartOfDay()
- !temporal.isSupported(ChronoField.OFFSET_SECONDS) ->
- LocalDateTime.from(temporal)
- else -> ZonedDateTime.from(temporal).toLocalDateTime()
- }
+ !temporal.isSupported(ChronoField.HOUR_OF_DAY) ->
+ LocalDate.from(temporal).atStartOfDay()
+ !temporal.isSupported(ChronoField.OFFSET_SECONDS) ->
+ LocalDateTime.from(temporal)
+ else -> ZonedDateTime.from(temporal).toLocalDateTime()
+ }
+ .atZone(context.timeZone.toZoneId())
+ .toOffsetDateTime()
} catch (e: DateTimeException) {
exceptions.add(e)
}
}
- throw JsonParseException(p, "Cannot parse `LocalDateTime` from value: ${p.text}").apply {
+ throw JsonParseException(p, "Cannot parse `OffsetDateTime` from value: ${p.text}").apply {
exceptions.forEach { addSuppressed(it) }
}
}
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/core/http/HttpRequest.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/core/http/HttpRequest.kt
index 9f983a4a1..8f9b61130 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/core/http/HttpRequest.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/core/http/HttpRequest.kt
@@ -2,6 +2,7 @@ package com.anthropic.core.http
import com.anthropic.core.checkRequired
import com.anthropic.core.toImmutable
+import java.net.URLEncoder
import java.util.Optional
import kotlin.jvm.optionals.getOrNull
@@ -15,6 +16,35 @@ private constructor(
@get:JvmName("body") val body: HttpRequestBody?,
) {
+ fun url(): String = buildString {
+ append(baseUrl)
+
+ pathSegments.forEach { segment ->
+ if (!endsWith("/")) {
+ append("/")
+ }
+ append(URLEncoder.encode(segment, "UTF-8"))
+ }
+
+ if (queryParams.isEmpty()) {
+ return@buildString
+ }
+
+ append("?")
+ var isFirst = true
+ queryParams.keys().forEach { key ->
+ queryParams.values(key).forEach { value ->
+ if (!isFirst) {
+ append("&")
+ }
+ append(URLEncoder.encode(key, "UTF-8"))
+ append("=")
+ append(URLEncoder.encode(value, "UTF-8"))
+ isFirst = false
+ }
+ }
+ }
+
fun toBuilder(): Builder = Builder().from(this)
override fun toString(): String =
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/helpers/BetaMessageAccumulator.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/helpers/BetaMessageAccumulator.kt
index bcbfbfc80..b5d05cd10 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/helpers/BetaMessageAccumulator.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/helpers/BetaMessageAccumulator.kt
@@ -1,5 +1,6 @@
package com.anthropic.helpers
+import com.anthropic.core.JsonMissing
import com.anthropic.core.JsonObject
import com.anthropic.core.jsonMapper
import com.anthropic.errors.AnthropicInvalidDataException
@@ -329,6 +330,13 @@ class BetaMessageAccumulator private constructor() {
): BetaContentBlock =
BetaContentBlock.ofWebFetchToolResult(webFetchToolResult)
+ override fun visitToolSearchToolResult(
+ toolSearchToolResult: BetaToolSearchToolResultBlock
+ ): BetaContentBlock =
+ BetaContentBlock.ofToolSearchToolResult(
+ toolSearchToolResult
+ )
+
override fun visitCodeExecutionToolResult(
codeExecutionToolResult: BetaCodeExecutionToolResultBlock
): BetaContentBlock =
@@ -448,14 +456,20 @@ class BetaMessageAccumulator private constructor() {
"Missing input JSON for index $index."
)
+ // Anthropic Streaming Messages API: "the final `tool_use.input`
+ // is always an _object_." However, if a tool function has no
+ // arguments, the concatenated `inputJson` can be an empty
+ // string. In that case, interpret it as a missing field.
val parsedInput =
- try {
- JSON_MAPPER.readValue(inputJson, JsonObject::class.java)
- } catch (e: Exception) {
- throw AnthropicInvalidDataException(
- "Unable to parse tool parameter JSON from model. Please retry your request or adjust your prompt. Error: ${e}. JSON: $inputJson"
- )
- }
+ if (inputJson.trim() == "") JsonMissing.of()
+ else
+ try {
+ JSON_MAPPER.readValue(inputJson, JsonObject::class.java)
+ } catch (e: Exception) {
+ throw AnthropicInvalidDataException(
+ "Unable to parse tool parameter JSON from model. Please retry your request or adjust your prompt. Error: ${e}. JSON: $inputJson"
+ )
+ }
messageContent[index] =
when {
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/AnthropicBeta.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/AnthropicBeta.kt
index d3b7eaad4..88fc191aa 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/AnthropicBeta.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/AnthropicBeta.kt
@@ -40,6 +40,8 @@ class AnthropicBeta @JsonCreator private constructor(private val value: JsonFiel
@JvmField val MCP_CLIENT_2025_04_04 = of("mcp-client-2025-04-04")
+ @JvmField val MCP_CLIENT_2025_11_20 = of("mcp-client-2025-11-20")
+
@JvmField val DEV_FULL_THINKING_2025_05_14 = of("dev-full-thinking-2025-05-14")
@JvmField val INTERLEAVED_THINKING_2025_05_14 = of("interleaved-thinking-2025-05-14")
@@ -73,6 +75,7 @@ class AnthropicBeta @JsonCreator private constructor(private val value: JsonFiel
OUTPUT_128K_2025_02_19,
FILES_API_2025_04_14,
MCP_CLIENT_2025_04_04,
+ MCP_CLIENT_2025_11_20,
DEV_FULL_THINKING_2025_05_14,
INTERLEAVED_THINKING_2025_05_14,
CODE_EXECUTION_2025_05_22,
@@ -103,6 +106,7 @@ class AnthropicBeta @JsonCreator private constructor(private val value: JsonFiel
OUTPUT_128K_2025_02_19,
FILES_API_2025_04_14,
MCP_CLIENT_2025_04_04,
+ MCP_CLIENT_2025_11_20,
DEV_FULL_THINKING_2025_05_14,
INTERLEAVED_THINKING_2025_05_14,
CODE_EXECUTION_2025_05_22,
@@ -136,6 +140,7 @@ class AnthropicBeta @JsonCreator private constructor(private val value: JsonFiel
OUTPUT_128K_2025_02_19 -> Value.OUTPUT_128K_2025_02_19
FILES_API_2025_04_14 -> Value.FILES_API_2025_04_14
MCP_CLIENT_2025_04_04 -> Value.MCP_CLIENT_2025_04_04
+ MCP_CLIENT_2025_11_20 -> Value.MCP_CLIENT_2025_11_20
DEV_FULL_THINKING_2025_05_14 -> Value.DEV_FULL_THINKING_2025_05_14
INTERLEAVED_THINKING_2025_05_14 -> Value.INTERLEAVED_THINKING_2025_05_14
CODE_EXECUTION_2025_05_22 -> Value.CODE_EXECUTION_2025_05_22
@@ -168,6 +173,7 @@ class AnthropicBeta @JsonCreator private constructor(private val value: JsonFiel
OUTPUT_128K_2025_02_19 -> Known.OUTPUT_128K_2025_02_19
FILES_API_2025_04_14 -> Known.FILES_API_2025_04_14
MCP_CLIENT_2025_04_04 -> Known.MCP_CLIENT_2025_04_04
+ MCP_CLIENT_2025_11_20 -> Known.MCP_CLIENT_2025_11_20
DEV_FULL_THINKING_2025_05_14 -> Known.DEV_FULL_THINKING_2025_05_14
INTERLEAVED_THINKING_2025_05_14 -> Known.INTERLEAVED_THINKING_2025_05_14
CODE_EXECUTION_2025_05_22 -> Known.CODE_EXECUTION_2025_05_22
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaClearThinking20251015Edit.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaClearThinking20251015Edit.kt
index 8573fb725..ed0c3a86b 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaClearThinking20251015Edit.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaClearThinking20251015Edit.kt
@@ -396,7 +396,7 @@ private constructor(
.toList()
return when (bestMatches.size) {
// This can happen if what we're deserializing is completely incompatible with
- // all the possible variants (e.g. deserializing from array).
+ // all the possible variants (e.g. deserializing from boolean).
0 -> Keep(_json = json)
1 -> bestMatches.single()
// If there's more than one match with the highest validity, then use the first
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaCodeExecutionTool20250522.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaCodeExecutionTool20250522.kt
index 2f9d4ed2a..e77a51bac 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaCodeExecutionTool20250522.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaCodeExecutionTool20250522.kt
@@ -2,10 +2,13 @@
package com.anthropic.models.beta.messages
+import com.anthropic.core.Enum
import com.anthropic.core.ExcludeMissing
import com.anthropic.core.JsonField
import com.anthropic.core.JsonMissing
import com.anthropic.core.JsonValue
+import com.anthropic.core.checkKnown
+import com.anthropic.core.toImmutable
import com.anthropic.errors.AnthropicInvalidDataException
import com.fasterxml.jackson.annotation.JsonAnyGetter
import com.fasterxml.jackson.annotation.JsonAnySetter
@@ -21,7 +24,9 @@ class BetaCodeExecutionTool20250522
private constructor(
private val name: JsonValue,
private val type: JsonValue,
+ private val allowedCallers: JsonField>,
private val cacheControl: JsonField,
+ private val deferLoading: JsonField,
private val strict: JsonField,
private val additionalProperties: MutableMap,
) {
@@ -30,11 +35,17 @@ private constructor(
private constructor(
@JsonProperty("name") @ExcludeMissing name: JsonValue = JsonMissing.of(),
@JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(),
+ @JsonProperty("allowed_callers")
+ @ExcludeMissing
+ allowedCallers: JsonField> = JsonMissing.of(),
@JsonProperty("cache_control")
@ExcludeMissing
cacheControl: JsonField = JsonMissing.of(),
+ @JsonProperty("defer_loading")
+ @ExcludeMissing
+ deferLoading: JsonField = JsonMissing.of(),
@JsonProperty("strict") @ExcludeMissing strict: JsonField = JsonMissing.of(),
- ) : this(name, type, cacheControl, strict, mutableMapOf())
+ ) : this(name, type, allowedCallers, cacheControl, deferLoading, strict, mutableMapOf())
/**
* Name of the tool.
@@ -62,6 +73,13 @@ private constructor(
*/
@JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type
+ /**
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun allowedCallers(): Optional> =
+ allowedCallers.getOptional("allowed_callers")
+
/**
* Create a cache control breakpoint at this content block.
*
@@ -71,12 +89,30 @@ private constructor(
fun cacheControl(): Optional =
cacheControl.getOptional("cache_control")
+ /**
+ * If true, tool will not be included in initial system prompt. Only loaded when returned via
+ * tool_reference from tool search.
+ *
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun deferLoading(): Optional = deferLoading.getOptional("defer_loading")
+
/**
* @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
* server responded with an unexpected value).
*/
fun strict(): Optional = strict.getOptional("strict")
+ /**
+ * Returns the raw JSON value of [allowedCallers].
+ *
+ * Unlike [allowedCallers], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("allowed_callers")
+ @ExcludeMissing
+ fun _allowedCallers(): JsonField> = allowedCallers
+
/**
* Returns the raw JSON value of [cacheControl].
*
@@ -86,6 +122,15 @@ private constructor(
@ExcludeMissing
fun _cacheControl(): JsonField = cacheControl
+ /**
+ * Returns the raw JSON value of [deferLoading].
+ *
+ * Unlike [deferLoading], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("defer_loading")
+ @ExcludeMissing
+ fun _deferLoading(): JsonField = deferLoading
+
/**
* Returns the raw JSON value of [strict].
*
@@ -119,7 +164,9 @@ private constructor(
private var name: JsonValue = JsonValue.from("code_execution")
private var type: JsonValue = JsonValue.from("code_execution_20250522")
+ private var allowedCallers: JsonField>? = null
private var cacheControl: JsonField = JsonMissing.of()
+ private var deferLoading: JsonField = JsonMissing.of()
private var strict: JsonField = JsonMissing.of()
private var additionalProperties: MutableMap = mutableMapOf()
@@ -127,7 +174,9 @@ private constructor(
internal fun from(betaCodeExecutionTool20250522: BetaCodeExecutionTool20250522) = apply {
name = betaCodeExecutionTool20250522.name
type = betaCodeExecutionTool20250522.type
+ allowedCallers = betaCodeExecutionTool20250522.allowedCallers.map { it.toMutableList() }
cacheControl = betaCodeExecutionTool20250522.cacheControl
+ deferLoading = betaCodeExecutionTool20250522.deferLoading
strict = betaCodeExecutionTool20250522.strict
additionalProperties = betaCodeExecutionTool20250522.additionalProperties.toMutableMap()
}
@@ -160,6 +209,32 @@ private constructor(
*/
fun type(type: JsonValue) = apply { this.type = type }
+ fun allowedCallers(allowedCallers: List) =
+ allowedCallers(JsonField.of(allowedCallers))
+
+ /**
+ * Sets [Builder.allowedCallers] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.allowedCallers] with a well-typed `List`
+ * value instead. This method is primarily for setting the field to an undocumented or not
+ * yet supported value.
+ */
+ fun allowedCallers(allowedCallers: JsonField>) = apply {
+ this.allowedCallers = allowedCallers.map { it.toMutableList() }
+ }
+
+ /**
+ * Adds a single [AllowedCaller] to [allowedCallers].
+ *
+ * @throws IllegalStateException if the field was previously set to a non-list.
+ */
+ fun addAllowedCaller(allowedCaller: AllowedCaller) = apply {
+ allowedCallers =
+ (allowedCallers ?: JsonField.of(mutableListOf())).also {
+ checkKnown("allowedCallers", it).add(allowedCaller)
+ }
+ }
+
/** Create a cache control breakpoint at this content block. */
fun cacheControl(cacheControl: BetaCacheControlEphemeral?) =
cacheControl(JsonField.ofNullable(cacheControl))
@@ -179,6 +254,23 @@ private constructor(
this.cacheControl = cacheControl
}
+ /**
+ * If true, tool will not be included in initial system prompt. Only loaded when returned
+ * via tool_reference from tool search.
+ */
+ fun deferLoading(deferLoading: Boolean) = deferLoading(JsonField.of(deferLoading))
+
+ /**
+ * Sets [Builder.deferLoading] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.deferLoading] with a well-typed [Boolean] value instead.
+ * This method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun deferLoading(deferLoading: JsonField) = apply {
+ this.deferLoading = deferLoading
+ }
+
fun strict(strict: Boolean) = strict(JsonField.of(strict))
/**
@@ -217,7 +309,9 @@ private constructor(
BetaCodeExecutionTool20250522(
name,
type,
+ (allowedCallers ?: JsonMissing.of()).map { it.toImmutable() },
cacheControl,
+ deferLoading,
strict,
additionalProperties.toMutableMap(),
)
@@ -240,7 +334,9 @@ private constructor(
throw AnthropicInvalidDataException("'type' is invalid, received $it")
}
}
+ allowedCallers().ifPresent { it.forEach { it.validate() } }
cacheControl().ifPresent { it.validate() }
+ deferLoading()
strict()
validated = true
}
@@ -262,9 +358,142 @@ private constructor(
internal fun validity(): Int =
name.let { if (it == JsonValue.from("code_execution")) 1 else 0 } +
type.let { if (it == JsonValue.from("code_execution_20250522")) 1 else 0 } +
+ (allowedCallers.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) +
(cacheControl.asKnown().getOrNull()?.validity() ?: 0) +
+ (if (deferLoading.asKnown().isPresent) 1 else 0) +
(if (strict.asKnown().isPresent) 1 else 0)
+ class AllowedCaller @JsonCreator private constructor(private val value: JsonField) :
+ Enum {
+
+ /**
+ * Returns this class instance's raw value.
+ *
+ * This is usually only useful if this instance was deserialized from data that doesn't
+ * match any known member, and you want to know that value. For example, if the SDK is on an
+ * older version than the API, then the API may respond with new members that the SDK is
+ * unaware of.
+ */
+ @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value
+
+ companion object {
+
+ @JvmField val DIRECT = of("direct")
+
+ @JvmField val CODE_EXECUTION_20250825 = of("code_execution_20250825")
+
+ @JvmStatic fun of(value: String) = AllowedCaller(JsonField.of(value))
+ }
+
+ /** An enum containing [AllowedCaller]'s known values. */
+ enum class Known {
+ DIRECT,
+ CODE_EXECUTION_20250825,
+ }
+
+ /**
+ * An enum containing [AllowedCaller]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [AllowedCaller] can contain an unknown value in a couple of cases:
+ * - It was deserialized from data that doesn't match any known member. For example, if the
+ * SDK is on an older version than the API, then the API may respond with new members that
+ * the SDK is unaware of.
+ * - It was constructed with an arbitrary value using the [of] method.
+ */
+ enum class Value {
+ DIRECT,
+ CODE_EXECUTION_20250825,
+ /**
+ * An enum member indicating that [AllowedCaller] was instantiated with an unknown
+ * value.
+ */
+ _UNKNOWN,
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN]
+ * if the class was instantiated with an unknown value.
+ *
+ * Use the [known] method instead if you're certain the value is always known or if you want
+ * to throw for the unknown case.
+ */
+ fun value(): Value =
+ when (this) {
+ DIRECT -> Value.DIRECT
+ CODE_EXECUTION_20250825 -> Value.CODE_EXECUTION_20250825
+ else -> Value._UNKNOWN
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value.
+ *
+ * Use the [value] method instead if you're uncertain the value is always known and don't
+ * want to throw for the unknown case.
+ *
+ * @throws AnthropicInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ DIRECT -> Known.DIRECT
+ CODE_EXECUTION_20250825 -> Known.CODE_EXECUTION_20250825
+ else -> throw AnthropicInvalidDataException("Unknown AllowedCaller: $value")
+ }
+
+ /**
+ * Returns this class instance's primitive wire representation.
+ *
+ * This differs from the [toString] method because that method is primarily for debugging
+ * and generally doesn't throw.
+ *
+ * @throws AnthropicInvalidDataException if this class instance's value does not have the
+ * expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString().orElseThrow {
+ AnthropicInvalidDataException("Value is not a String")
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): AllowedCaller = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: AnthropicInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is AllowedCaller && value == other.value
+ }
+
+ override fun hashCode() = value.hashCode()
+
+ override fun toString() = value.toString()
+ }
+
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
@@ -273,17 +502,27 @@ private constructor(
return other is BetaCodeExecutionTool20250522 &&
name == other.name &&
type == other.type &&
+ allowedCallers == other.allowedCallers &&
cacheControl == other.cacheControl &&
+ deferLoading == other.deferLoading &&
strict == other.strict &&
additionalProperties == other.additionalProperties
}
private val hashCode: Int by lazy {
- Objects.hash(name, type, cacheControl, strict, additionalProperties)
+ Objects.hash(
+ name,
+ type,
+ allowedCallers,
+ cacheControl,
+ deferLoading,
+ strict,
+ additionalProperties,
+ )
}
override fun hashCode(): Int = hashCode
override fun toString() =
- "BetaCodeExecutionTool20250522{name=$name, type=$type, cacheControl=$cacheControl, strict=$strict, additionalProperties=$additionalProperties}"
+ "BetaCodeExecutionTool20250522{name=$name, type=$type, allowedCallers=$allowedCallers, cacheControl=$cacheControl, deferLoading=$deferLoading, strict=$strict, additionalProperties=$additionalProperties}"
}
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaCodeExecutionTool20250825.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaCodeExecutionTool20250825.kt
index d662caceb..ff9ab46b7 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaCodeExecutionTool20250825.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaCodeExecutionTool20250825.kt
@@ -2,10 +2,13 @@
package com.anthropic.models.beta.messages
+import com.anthropic.core.Enum
import com.anthropic.core.ExcludeMissing
import com.anthropic.core.JsonField
import com.anthropic.core.JsonMissing
import com.anthropic.core.JsonValue
+import com.anthropic.core.checkKnown
+import com.anthropic.core.toImmutable
import com.anthropic.errors.AnthropicInvalidDataException
import com.fasterxml.jackson.annotation.JsonAnyGetter
import com.fasterxml.jackson.annotation.JsonAnySetter
@@ -21,7 +24,9 @@ class BetaCodeExecutionTool20250825
private constructor(
private val name: JsonValue,
private val type: JsonValue,
+ private val allowedCallers: JsonField>,
private val cacheControl: JsonField,
+ private val deferLoading: JsonField,
private val strict: JsonField,
private val additionalProperties: MutableMap,
) {
@@ -30,11 +35,17 @@ private constructor(
private constructor(
@JsonProperty("name") @ExcludeMissing name: JsonValue = JsonMissing.of(),
@JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(),
+ @JsonProperty("allowed_callers")
+ @ExcludeMissing
+ allowedCallers: JsonField> = JsonMissing.of(),
@JsonProperty("cache_control")
@ExcludeMissing
cacheControl: JsonField = JsonMissing.of(),
+ @JsonProperty("defer_loading")
+ @ExcludeMissing
+ deferLoading: JsonField = JsonMissing.of(),
@JsonProperty("strict") @ExcludeMissing strict: JsonField = JsonMissing.of(),
- ) : this(name, type, cacheControl, strict, mutableMapOf())
+ ) : this(name, type, allowedCallers, cacheControl, deferLoading, strict, mutableMapOf())
/**
* Name of the tool.
@@ -62,6 +73,13 @@ private constructor(
*/
@JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type
+ /**
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun allowedCallers(): Optional> =
+ allowedCallers.getOptional("allowed_callers")
+
/**
* Create a cache control breakpoint at this content block.
*
@@ -71,12 +89,30 @@ private constructor(
fun cacheControl(): Optional =
cacheControl.getOptional("cache_control")
+ /**
+ * If true, tool will not be included in initial system prompt. Only loaded when returned via
+ * tool_reference from tool search.
+ *
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun deferLoading(): Optional = deferLoading.getOptional("defer_loading")
+
/**
* @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
* server responded with an unexpected value).
*/
fun strict(): Optional = strict.getOptional("strict")
+ /**
+ * Returns the raw JSON value of [allowedCallers].
+ *
+ * Unlike [allowedCallers], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("allowed_callers")
+ @ExcludeMissing
+ fun _allowedCallers(): JsonField> = allowedCallers
+
/**
* Returns the raw JSON value of [cacheControl].
*
@@ -86,6 +122,15 @@ private constructor(
@ExcludeMissing
fun _cacheControl(): JsonField = cacheControl
+ /**
+ * Returns the raw JSON value of [deferLoading].
+ *
+ * Unlike [deferLoading], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("defer_loading")
+ @ExcludeMissing
+ fun _deferLoading(): JsonField = deferLoading
+
/**
* Returns the raw JSON value of [strict].
*
@@ -119,7 +164,9 @@ private constructor(
private var name: JsonValue = JsonValue.from("code_execution")
private var type: JsonValue = JsonValue.from("code_execution_20250825")
+ private var allowedCallers: JsonField>? = null
private var cacheControl: JsonField = JsonMissing.of()
+ private var deferLoading: JsonField = JsonMissing.of()
private var strict: JsonField = JsonMissing.of()
private var additionalProperties: MutableMap = mutableMapOf()
@@ -127,7 +174,9 @@ private constructor(
internal fun from(betaCodeExecutionTool20250825: BetaCodeExecutionTool20250825) = apply {
name = betaCodeExecutionTool20250825.name
type = betaCodeExecutionTool20250825.type
+ allowedCallers = betaCodeExecutionTool20250825.allowedCallers.map { it.toMutableList() }
cacheControl = betaCodeExecutionTool20250825.cacheControl
+ deferLoading = betaCodeExecutionTool20250825.deferLoading
strict = betaCodeExecutionTool20250825.strict
additionalProperties = betaCodeExecutionTool20250825.additionalProperties.toMutableMap()
}
@@ -160,6 +209,32 @@ private constructor(
*/
fun type(type: JsonValue) = apply { this.type = type }
+ fun allowedCallers(allowedCallers: List) =
+ allowedCallers(JsonField.of(allowedCallers))
+
+ /**
+ * Sets [Builder.allowedCallers] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.allowedCallers] with a well-typed `List`
+ * value instead. This method is primarily for setting the field to an undocumented or not
+ * yet supported value.
+ */
+ fun allowedCallers(allowedCallers: JsonField>) = apply {
+ this.allowedCallers = allowedCallers.map { it.toMutableList() }
+ }
+
+ /**
+ * Adds a single [AllowedCaller] to [allowedCallers].
+ *
+ * @throws IllegalStateException if the field was previously set to a non-list.
+ */
+ fun addAllowedCaller(allowedCaller: AllowedCaller) = apply {
+ allowedCallers =
+ (allowedCallers ?: JsonField.of(mutableListOf())).also {
+ checkKnown("allowedCallers", it).add(allowedCaller)
+ }
+ }
+
/** Create a cache control breakpoint at this content block. */
fun cacheControl(cacheControl: BetaCacheControlEphemeral?) =
cacheControl(JsonField.ofNullable(cacheControl))
@@ -179,6 +254,23 @@ private constructor(
this.cacheControl = cacheControl
}
+ /**
+ * If true, tool will not be included in initial system prompt. Only loaded when returned
+ * via tool_reference from tool search.
+ */
+ fun deferLoading(deferLoading: Boolean) = deferLoading(JsonField.of(deferLoading))
+
+ /**
+ * Sets [Builder.deferLoading] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.deferLoading] with a well-typed [Boolean] value instead.
+ * This method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun deferLoading(deferLoading: JsonField) = apply {
+ this.deferLoading = deferLoading
+ }
+
fun strict(strict: Boolean) = strict(JsonField.of(strict))
/**
@@ -217,7 +309,9 @@ private constructor(
BetaCodeExecutionTool20250825(
name,
type,
+ (allowedCallers ?: JsonMissing.of()).map { it.toImmutable() },
cacheControl,
+ deferLoading,
strict,
additionalProperties.toMutableMap(),
)
@@ -240,7 +334,9 @@ private constructor(
throw AnthropicInvalidDataException("'type' is invalid, received $it")
}
}
+ allowedCallers().ifPresent { it.forEach { it.validate() } }
cacheControl().ifPresent { it.validate() }
+ deferLoading()
strict()
validated = true
}
@@ -262,9 +358,142 @@ private constructor(
internal fun validity(): Int =
name.let { if (it == JsonValue.from("code_execution")) 1 else 0 } +
type.let { if (it == JsonValue.from("code_execution_20250825")) 1 else 0 } +
+ (allowedCallers.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) +
(cacheControl.asKnown().getOrNull()?.validity() ?: 0) +
+ (if (deferLoading.asKnown().isPresent) 1 else 0) +
(if (strict.asKnown().isPresent) 1 else 0)
+ class AllowedCaller @JsonCreator private constructor(private val value: JsonField) :
+ Enum {
+
+ /**
+ * Returns this class instance's raw value.
+ *
+ * This is usually only useful if this instance was deserialized from data that doesn't
+ * match any known member, and you want to know that value. For example, if the SDK is on an
+ * older version than the API, then the API may respond with new members that the SDK is
+ * unaware of.
+ */
+ @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value
+
+ companion object {
+
+ @JvmField val DIRECT = of("direct")
+
+ @JvmField val CODE_EXECUTION_20250825 = of("code_execution_20250825")
+
+ @JvmStatic fun of(value: String) = AllowedCaller(JsonField.of(value))
+ }
+
+ /** An enum containing [AllowedCaller]'s known values. */
+ enum class Known {
+ DIRECT,
+ CODE_EXECUTION_20250825,
+ }
+
+ /**
+ * An enum containing [AllowedCaller]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [AllowedCaller] can contain an unknown value in a couple of cases:
+ * - It was deserialized from data that doesn't match any known member. For example, if the
+ * SDK is on an older version than the API, then the API may respond with new members that
+ * the SDK is unaware of.
+ * - It was constructed with an arbitrary value using the [of] method.
+ */
+ enum class Value {
+ DIRECT,
+ CODE_EXECUTION_20250825,
+ /**
+ * An enum member indicating that [AllowedCaller] was instantiated with an unknown
+ * value.
+ */
+ _UNKNOWN,
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN]
+ * if the class was instantiated with an unknown value.
+ *
+ * Use the [known] method instead if you're certain the value is always known or if you want
+ * to throw for the unknown case.
+ */
+ fun value(): Value =
+ when (this) {
+ DIRECT -> Value.DIRECT
+ CODE_EXECUTION_20250825 -> Value.CODE_EXECUTION_20250825
+ else -> Value._UNKNOWN
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value.
+ *
+ * Use the [value] method instead if you're uncertain the value is always known and don't
+ * want to throw for the unknown case.
+ *
+ * @throws AnthropicInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ DIRECT -> Known.DIRECT
+ CODE_EXECUTION_20250825 -> Known.CODE_EXECUTION_20250825
+ else -> throw AnthropicInvalidDataException("Unknown AllowedCaller: $value")
+ }
+
+ /**
+ * Returns this class instance's primitive wire representation.
+ *
+ * This differs from the [toString] method because that method is primarily for debugging
+ * and generally doesn't throw.
+ *
+ * @throws AnthropicInvalidDataException if this class instance's value does not have the
+ * expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString().orElseThrow {
+ AnthropicInvalidDataException("Value is not a String")
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): AllowedCaller = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: AnthropicInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is AllowedCaller && value == other.value
+ }
+
+ override fun hashCode() = value.hashCode()
+
+ override fun toString() = value.toString()
+ }
+
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
@@ -273,17 +502,27 @@ private constructor(
return other is BetaCodeExecutionTool20250825 &&
name == other.name &&
type == other.type &&
+ allowedCallers == other.allowedCallers &&
cacheControl == other.cacheControl &&
+ deferLoading == other.deferLoading &&
strict == other.strict &&
additionalProperties == other.additionalProperties
}
private val hashCode: Int by lazy {
- Objects.hash(name, type, cacheControl, strict, additionalProperties)
+ Objects.hash(
+ name,
+ type,
+ allowedCallers,
+ cacheControl,
+ deferLoading,
+ strict,
+ additionalProperties,
+ )
}
override fun hashCode(): Int = hashCode
override fun toString() =
- "BetaCodeExecutionTool20250825{name=$name, type=$type, cacheControl=$cacheControl, strict=$strict, additionalProperties=$additionalProperties}"
+ "BetaCodeExecutionTool20250825{name=$name, type=$type, allowedCallers=$allowedCallers, cacheControl=$cacheControl, deferLoading=$deferLoading, strict=$strict, additionalProperties=$additionalProperties}"
}
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaContentBlock.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaContentBlock.kt
index f14c8f5c0..dff951d15 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaContentBlock.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaContentBlock.kt
@@ -34,6 +34,7 @@ private constructor(
private val bashCodeExecutionToolResult: BetaBashCodeExecutionToolResultBlock? = null,
private val textEditorCodeExecutionToolResult: BetaTextEditorCodeExecutionToolResultBlock? =
null,
+ private val toolSearchToolResult: BetaToolSearchToolResultBlock? = null,
private val mcpToolUse: BetaMcpToolUseBlock? = null,
private val mcpToolResult: BetaMcpToolResultBlock? = null,
private val containerUpload: BetaContainerUploadBlock? = null,
@@ -93,6 +94,11 @@ private constructor(
textEditorCodeExecutionToolResult.toParam()
)
+ override fun visitToolSearchToolResult(
+ toolSearchToolResult: BetaToolSearchToolResultBlock
+ ): BetaContentBlockParam =
+ BetaContentBlockParam.ofToolSearchToolResult(toolSearchToolResult.toParam())
+
override fun visitMcpToolUse(
mcpToolUse: BetaMcpToolUseBlock
): BetaContentBlockParam = BetaContentBlockParam.ofMcpToolUse(mcpToolUse.toParam())
@@ -135,6 +141,9 @@ private constructor(
fun textEditorCodeExecutionToolResult(): Optional =
Optional.ofNullable(textEditorCodeExecutionToolResult)
+ fun toolSearchToolResult(): Optional =
+ Optional.ofNullable(toolSearchToolResult)
+
fun mcpToolUse(): Optional = Optional.ofNullable(mcpToolUse)
fun mcpToolResult(): Optional = Optional.ofNullable(mcpToolResult)
@@ -162,6 +171,8 @@ private constructor(
fun isTextEditorCodeExecutionToolResult(): Boolean = textEditorCodeExecutionToolResult != null
+ fun isToolSearchToolResult(): Boolean = toolSearchToolResult != null
+
fun isMcpToolUse(): Boolean = mcpToolUse != null
fun isMcpToolResult(): Boolean = mcpToolResult != null
@@ -194,6 +205,9 @@ private constructor(
fun asTextEditorCodeExecutionToolResult(): BetaTextEditorCodeExecutionToolResultBlock =
textEditorCodeExecutionToolResult.getOrThrow("textEditorCodeExecutionToolResult")
+ fun asToolSearchToolResult(): BetaToolSearchToolResultBlock =
+ toolSearchToolResult.getOrThrow("toolSearchToolResult")
+
fun asMcpToolUse(): BetaMcpToolUseBlock = mcpToolUse.getOrThrow("mcpToolUse")
fun asMcpToolResult(): BetaMcpToolResultBlock = mcpToolResult.getOrThrow("mcpToolResult")
@@ -219,6 +233,7 @@ private constructor(
visitor.visitBashCodeExecutionToolResult(bashCodeExecutionToolResult)
textEditorCodeExecutionToolResult != null ->
visitor.visitTextEditorCodeExecutionToolResult(textEditorCodeExecutionToolResult)
+ toolSearchToolResult != null -> visitor.visitToolSearchToolResult(toolSearchToolResult)
mcpToolUse != null -> visitor.visitMcpToolUse(mcpToolUse)
mcpToolResult != null -> visitor.visitMcpToolResult(mcpToolResult)
containerUpload != null -> visitor.visitContainerUpload(containerUpload)
@@ -284,6 +299,12 @@ private constructor(
textEditorCodeExecutionToolResult.validate()
}
+ override fun visitToolSearchToolResult(
+ toolSearchToolResult: BetaToolSearchToolResultBlock
+ ) {
+ toolSearchToolResult.validate()
+ }
+
override fun visitMcpToolUse(mcpToolUse: BetaMcpToolUseBlock) {
mcpToolUse.validate()
}
@@ -349,6 +370,10 @@ private constructor(
textEditorCodeExecutionToolResult: BetaTextEditorCodeExecutionToolResultBlock
) = textEditorCodeExecutionToolResult.validity()
+ override fun visitToolSearchToolResult(
+ toolSearchToolResult: BetaToolSearchToolResultBlock
+ ) = toolSearchToolResult.validity()
+
override fun visitMcpToolUse(mcpToolUse: BetaMcpToolUseBlock) =
mcpToolUse.validity()
@@ -378,6 +403,7 @@ private constructor(
codeExecutionToolResult == other.codeExecutionToolResult &&
bashCodeExecutionToolResult == other.bashCodeExecutionToolResult &&
textEditorCodeExecutionToolResult == other.textEditorCodeExecutionToolResult &&
+ toolSearchToolResult == other.toolSearchToolResult &&
mcpToolUse == other.mcpToolUse &&
mcpToolResult == other.mcpToolResult &&
containerUpload == other.containerUpload
@@ -395,6 +421,7 @@ private constructor(
codeExecutionToolResult,
bashCodeExecutionToolResult,
textEditorCodeExecutionToolResult,
+ toolSearchToolResult,
mcpToolUse,
mcpToolResult,
containerUpload,
@@ -416,6 +443,8 @@ private constructor(
"BetaContentBlock{bashCodeExecutionToolResult=$bashCodeExecutionToolResult}"
textEditorCodeExecutionToolResult != null ->
"BetaContentBlock{textEditorCodeExecutionToolResult=$textEditorCodeExecutionToolResult}"
+ toolSearchToolResult != null ->
+ "BetaContentBlock{toolSearchToolResult=$toolSearchToolResult}"
mcpToolUse != null -> "BetaContentBlock{mcpToolUse=$mcpToolUse}"
mcpToolResult != null -> "BetaContentBlock{mcpToolResult=$mcpToolResult}"
containerUpload != null -> "BetaContentBlock{containerUpload=$containerUpload}"
@@ -462,6 +491,10 @@ private constructor(
textEditorCodeExecutionToolResult: BetaTextEditorCodeExecutionToolResultBlock
) = BetaContentBlock(textEditorCodeExecutionToolResult = textEditorCodeExecutionToolResult)
+ @JvmStatic
+ fun ofToolSearchToolResult(toolSearchToolResult: BetaToolSearchToolResultBlock) =
+ BetaContentBlock(toolSearchToolResult = toolSearchToolResult)
+
@JvmStatic
fun ofMcpToolUse(mcpToolUse: BetaMcpToolUseBlock) =
BetaContentBlock(mcpToolUse = mcpToolUse)
@@ -508,6 +541,8 @@ private constructor(
textEditorCodeExecutionToolResult: BetaTextEditorCodeExecutionToolResultBlock
): T
+ fun visitToolSearchToolResult(toolSearchToolResult: BetaToolSearchToolResultBlock): T
+
fun visitMcpToolUse(mcpToolUse: BetaMcpToolUseBlock): T
fun visitMcpToolResult(mcpToolResult: BetaMcpToolResultBlock): T
@@ -594,6 +629,11 @@ private constructor(
BetaContentBlock(textEditorCodeExecutionToolResult = it, _json = json)
} ?: BetaContentBlock(_json = json)
}
+ "tool_search_tool_result" -> {
+ return tryDeserialize(node, jacksonTypeRef())
+ ?.let { BetaContentBlock(toolSearchToolResult = it, _json = json) }
+ ?: BetaContentBlock(_json = json)
+ }
"mcp_tool_use" -> {
return tryDeserialize(node, jacksonTypeRef())?.let {
BetaContentBlock(mcpToolUse = it, _json = json)
@@ -637,6 +677,8 @@ private constructor(
generator.writeObject(value.bashCodeExecutionToolResult)
value.textEditorCodeExecutionToolResult != null ->
generator.writeObject(value.textEditorCodeExecutionToolResult)
+ value.toolSearchToolResult != null ->
+ generator.writeObject(value.toolSearchToolResult)
value.mcpToolUse != null -> generator.writeObject(value.mcpToolUse)
value.mcpToolResult != null -> generator.writeObject(value.mcpToolResult)
value.containerUpload != null -> generator.writeObject(value.containerUpload)
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaContentBlockParam.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaContentBlockParam.kt
index 300e97a54..451b6e60a 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaContentBlockParam.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaContentBlockParam.kt
@@ -39,6 +39,7 @@ private constructor(
private val textEditorCodeExecutionToolResult:
BetaTextEditorCodeExecutionToolResultBlockParam? =
null,
+ private val toolSearchToolResult: BetaToolSearchToolResultBlockParam? = null,
private val mcpToolUse: BetaMcpToolUseBlockParam? = null,
private val mcpToolResult: BetaRequestMcpToolResultBlockParam? = null,
private val containerUpload: BetaContainerUploadBlockParam? = null,
@@ -91,6 +92,9 @@ private constructor(
Optional =
Optional.ofNullable(textEditorCodeExecutionToolResult)
+ fun toolSearchToolResult(): Optional =
+ Optional.ofNullable(toolSearchToolResult)
+
fun mcpToolUse(): Optional = Optional.ofNullable(mcpToolUse)
fun mcpToolResult(): Optional =
@@ -131,6 +135,8 @@ private constructor(
fun isTextEditorCodeExecutionToolResult(): Boolean = textEditorCodeExecutionToolResult != null
+ fun isToolSearchToolResult(): Boolean = toolSearchToolResult != null
+
fun isMcpToolUse(): Boolean = mcpToolUse != null
fun isMcpToolResult(): Boolean = mcpToolResult != null
@@ -182,6 +188,9 @@ private constructor(
fun asTextEditorCodeExecutionToolResult(): BetaTextEditorCodeExecutionToolResultBlockParam =
textEditorCodeExecutionToolResult.getOrThrow("textEditorCodeExecutionToolResult")
+ fun asToolSearchToolResult(): BetaToolSearchToolResultBlockParam =
+ toolSearchToolResult.getOrThrow("toolSearchToolResult")
+
fun asMcpToolUse(): BetaMcpToolUseBlockParam = mcpToolUse.getOrThrow("mcpToolUse")
fun asMcpToolResult(): BetaRequestMcpToolResultBlockParam =
@@ -215,6 +224,7 @@ private constructor(
visitor.visitBashCodeExecutionToolResult(bashCodeExecutionToolResult)
textEditorCodeExecutionToolResult != null ->
visitor.visitTextEditorCodeExecutionToolResult(textEditorCodeExecutionToolResult)
+ toolSearchToolResult != null -> visitor.visitToolSearchToolResult(toolSearchToolResult)
mcpToolUse != null -> visitor.visitMcpToolUse(mcpToolUse)
mcpToolResult != null -> visitor.visitMcpToolResult(mcpToolResult)
containerUpload != null -> visitor.visitContainerUpload(containerUpload)
@@ -299,6 +309,12 @@ private constructor(
textEditorCodeExecutionToolResult.validate()
}
+ override fun visitToolSearchToolResult(
+ toolSearchToolResult: BetaToolSearchToolResultBlockParam
+ ) {
+ toolSearchToolResult.validate()
+ }
+
override fun visitMcpToolUse(mcpToolUse: BetaMcpToolUseBlockParam) {
mcpToolUse.validate()
}
@@ -376,6 +392,10 @@ private constructor(
BetaTextEditorCodeExecutionToolResultBlockParam
) = textEditorCodeExecutionToolResult.validity()
+ override fun visitToolSearchToolResult(
+ toolSearchToolResult: BetaToolSearchToolResultBlockParam
+ ) = toolSearchToolResult.validity()
+
override fun visitMcpToolUse(mcpToolUse: BetaMcpToolUseBlockParam) =
mcpToolUse.validity()
@@ -409,6 +429,7 @@ private constructor(
codeExecutionToolResult == other.codeExecutionToolResult &&
bashCodeExecutionToolResult == other.bashCodeExecutionToolResult &&
textEditorCodeExecutionToolResult == other.textEditorCodeExecutionToolResult &&
+ toolSearchToolResult == other.toolSearchToolResult &&
mcpToolUse == other.mcpToolUse &&
mcpToolResult == other.mcpToolResult &&
containerUpload == other.containerUpload
@@ -430,6 +451,7 @@ private constructor(
codeExecutionToolResult,
bashCodeExecutionToolResult,
textEditorCodeExecutionToolResult,
+ toolSearchToolResult,
mcpToolUse,
mcpToolResult,
containerUpload,
@@ -456,6 +478,8 @@ private constructor(
"BetaContentBlockParam{bashCodeExecutionToolResult=$bashCodeExecutionToolResult}"
textEditorCodeExecutionToolResult != null ->
"BetaContentBlockParam{textEditorCodeExecutionToolResult=$textEditorCodeExecutionToolResult}"
+ toolSearchToolResult != null ->
+ "BetaContentBlockParam{toolSearchToolResult=$toolSearchToolResult}"
mcpToolUse != null -> "BetaContentBlockParam{mcpToolUse=$mcpToolUse}"
mcpToolResult != null -> "BetaContentBlockParam{mcpToolResult=$mcpToolResult}"
containerUpload != null -> "BetaContentBlockParam{containerUpload=$containerUpload}"
@@ -533,6 +557,10 @@ private constructor(
textEditorCodeExecutionToolResult = textEditorCodeExecutionToolResult
)
+ @JvmStatic
+ fun ofToolSearchToolResult(toolSearchToolResult: BetaToolSearchToolResultBlockParam) =
+ BetaContentBlockParam(toolSearchToolResult = toolSearchToolResult)
+
@JvmStatic
fun ofMcpToolUse(mcpToolUse: BetaMcpToolUseBlockParam) =
BetaContentBlockParam(mcpToolUse = mcpToolUse)
@@ -601,6 +629,8 @@ private constructor(
textEditorCodeExecutionToolResult: BetaTextEditorCodeExecutionToolResultBlockParam
): T
+ fun visitToolSearchToolResult(toolSearchToolResult: BetaToolSearchToolResultBlockParam): T
+
fun visitMcpToolUse(mcpToolUse: BetaMcpToolUseBlockParam): T
fun visitMcpToolResult(mcpToolResult: BetaRequestMcpToolResultBlockParam): T
@@ -718,6 +748,14 @@ private constructor(
)
} ?: BetaContentBlockParam(_json = json)
}
+ "tool_search_tool_result" -> {
+ return tryDeserialize(
+ node,
+ jacksonTypeRef(),
+ )
+ ?.let { BetaContentBlockParam(toolSearchToolResult = it, _json = json) }
+ ?: BetaContentBlockParam(_json = json)
+ }
"mcp_tool_use" -> {
return tryDeserialize(node, jacksonTypeRef())?.let {
BetaContentBlockParam(mcpToolUse = it, _json = json)
@@ -769,6 +807,8 @@ private constructor(
generator.writeObject(value.bashCodeExecutionToolResult)
value.textEditorCodeExecutionToolResult != null ->
generator.writeObject(value.textEditorCodeExecutionToolResult)
+ value.toolSearchToolResult != null ->
+ generator.writeObject(value.toolSearchToolResult)
value.mcpToolUse != null -> generator.writeObject(value.mcpToolUse)
value.mcpToolResult != null -> generator.writeObject(value.mcpToolResult)
value.containerUpload != null -> generator.writeObject(value.containerUpload)
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaContentBlockSource.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaContentBlockSource.kt
index 6ea7b909c..625d16ec7 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaContentBlockSource.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaContentBlockSource.kt
@@ -374,7 +374,7 @@ private constructor(
.toList()
return when (bestMatches.size) {
// This can happen if what we're deserializing is completely incompatible with
- // all the possible variants (e.g. deserializing from object).
+ // all the possible variants (e.g. deserializing from boolean).
0 -> Content(_json = json)
1 -> bestMatches.single()
// If there's more than one match with the highest validity, then use the first
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaDirectCaller.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaDirectCaller.kt
new file mode 100644
index 000000000..b7e14a681
--- /dev/null
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaDirectCaller.kt
@@ -0,0 +1,158 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.anthropic.models.beta.messages
+
+import com.anthropic.core.ExcludeMissing
+import com.anthropic.core.JsonMissing
+import com.anthropic.core.JsonValue
+import com.anthropic.errors.AnthropicInvalidDataException
+import com.fasterxml.jackson.annotation.JsonAnyGetter
+import com.fasterxml.jackson.annotation.JsonAnySetter
+import com.fasterxml.jackson.annotation.JsonCreator
+import com.fasterxml.jackson.annotation.JsonProperty
+import java.util.Collections
+import java.util.Objects
+
+/** Tool invocation directly from the model. */
+class BetaDirectCaller
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
+private constructor(
+ private val type: JsonValue,
+ private val additionalProperties: MutableMap,
+) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of()
+ ) : this(type, mutableMapOf())
+
+ /**
+ * Expected to always return the following:
+ * ```java
+ * JsonValue.from("direct")
+ * ```
+ *
+ * However, this method can be useful for debugging and logging (e.g. if the server responded
+ * with an unexpected value).
+ */
+ @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type
+
+ @JsonAnySetter
+ private fun putAdditionalProperty(key: String, value: JsonValue) {
+ additionalProperties.put(key, value)
+ }
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map =
+ Collections.unmodifiableMap(additionalProperties)
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /** Returns a mutable builder for constructing an instance of [BetaDirectCaller]. */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [BetaDirectCaller]. */
+ class Builder internal constructor() {
+
+ private var type: JsonValue = JsonValue.from("direct")
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(betaDirectCaller: BetaDirectCaller) = apply {
+ type = betaDirectCaller.type
+ additionalProperties = betaDirectCaller.additionalProperties.toMutableMap()
+ }
+
+ /**
+ * Sets the field to an arbitrary JSON value.
+ *
+ * It is usually unnecessary to call this method because the field defaults to the
+ * following:
+ * ```java
+ * JsonValue.from("direct")
+ * ```
+ *
+ * This method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun type(type: JsonValue) = apply { this.type = type }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [BetaDirectCaller].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ */
+ fun build(): BetaDirectCaller = BetaDirectCaller(type, additionalProperties.toMutableMap())
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): BetaDirectCaller = apply {
+ if (validated) {
+ return@apply
+ }
+
+ _type().let {
+ if (it != JsonValue.from("direct")) {
+ throw AnthropicInvalidDataException("'type' is invalid, received $it")
+ }
+ }
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: AnthropicInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int = type.let { if (it == JsonValue.from("direct")) 1 else 0 }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is BetaDirectCaller &&
+ type == other.type &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy { Objects.hash(type, additionalProperties) }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "BetaDirectCaller{type=$type, additionalProperties=$additionalProperties}"
+}
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMcpToolConfig.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMcpToolConfig.kt
new file mode 100644
index 000000000..7bf14a5c3
--- /dev/null
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMcpToolConfig.kt
@@ -0,0 +1,193 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.anthropic.models.beta.messages
+
+import com.anthropic.core.ExcludeMissing
+import com.anthropic.core.JsonField
+import com.anthropic.core.JsonMissing
+import com.anthropic.core.JsonValue
+import com.anthropic.errors.AnthropicInvalidDataException
+import com.fasterxml.jackson.annotation.JsonAnyGetter
+import com.fasterxml.jackson.annotation.JsonAnySetter
+import com.fasterxml.jackson.annotation.JsonCreator
+import com.fasterxml.jackson.annotation.JsonProperty
+import java.util.Collections
+import java.util.Objects
+import java.util.Optional
+
+/** Configuration for a specific tool in an MCP toolset. */
+class BetaMcpToolConfig
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
+private constructor(
+ private val deferLoading: JsonField,
+ private val enabled: JsonField,
+ private val additionalProperties: MutableMap,
+) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("defer_loading")
+ @ExcludeMissing
+ deferLoading: JsonField = JsonMissing.of(),
+ @JsonProperty("enabled") @ExcludeMissing enabled: JsonField = JsonMissing.of(),
+ ) : this(deferLoading, enabled, mutableMapOf())
+
+ /**
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun deferLoading(): Optional = deferLoading.getOptional("defer_loading")
+
+ /**
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun enabled(): Optional = enabled.getOptional("enabled")
+
+ /**
+ * Returns the raw JSON value of [deferLoading].
+ *
+ * Unlike [deferLoading], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("defer_loading")
+ @ExcludeMissing
+ fun _deferLoading(): JsonField = deferLoading
+
+ /**
+ * Returns the raw JSON value of [enabled].
+ *
+ * Unlike [enabled], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("enabled") @ExcludeMissing fun _enabled(): JsonField = enabled
+
+ @JsonAnySetter
+ private fun putAdditionalProperty(key: String, value: JsonValue) {
+ additionalProperties.put(key, value)
+ }
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map =
+ Collections.unmodifiableMap(additionalProperties)
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /** Returns a mutable builder for constructing an instance of [BetaMcpToolConfig]. */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [BetaMcpToolConfig]. */
+ class Builder internal constructor() {
+
+ private var deferLoading: JsonField = JsonMissing.of()
+ private var enabled: JsonField = JsonMissing.of()
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(betaMcpToolConfig: BetaMcpToolConfig) = apply {
+ deferLoading = betaMcpToolConfig.deferLoading
+ enabled = betaMcpToolConfig.enabled
+ additionalProperties = betaMcpToolConfig.additionalProperties.toMutableMap()
+ }
+
+ fun deferLoading(deferLoading: Boolean) = deferLoading(JsonField.of(deferLoading))
+
+ /**
+ * Sets [Builder.deferLoading] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.deferLoading] with a well-typed [Boolean] value instead.
+ * This method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun deferLoading(deferLoading: JsonField) = apply {
+ this.deferLoading = deferLoading
+ }
+
+ fun enabled(enabled: Boolean) = enabled(JsonField.of(enabled))
+
+ /**
+ * Sets [Builder.enabled] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.enabled] with a well-typed [Boolean] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun enabled(enabled: JsonField) = apply { this.enabled = enabled }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [BetaMcpToolConfig].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ */
+ fun build(): BetaMcpToolConfig =
+ BetaMcpToolConfig(deferLoading, enabled, additionalProperties.toMutableMap())
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): BetaMcpToolConfig = apply {
+ if (validated) {
+ return@apply
+ }
+
+ deferLoading()
+ enabled()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: AnthropicInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int =
+ (if (deferLoading.asKnown().isPresent) 1 else 0) +
+ (if (enabled.asKnown().isPresent) 1 else 0)
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is BetaMcpToolConfig &&
+ deferLoading == other.deferLoading &&
+ enabled == other.enabled &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy { Objects.hash(deferLoading, enabled, additionalProperties) }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "BetaMcpToolConfig{deferLoading=$deferLoading, enabled=$enabled, additionalProperties=$additionalProperties}"
+}
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMcpToolDefaultConfig.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMcpToolDefaultConfig.kt
new file mode 100644
index 000000000..1157f8808
--- /dev/null
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMcpToolDefaultConfig.kt
@@ -0,0 +1,193 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.anthropic.models.beta.messages
+
+import com.anthropic.core.ExcludeMissing
+import com.anthropic.core.JsonField
+import com.anthropic.core.JsonMissing
+import com.anthropic.core.JsonValue
+import com.anthropic.errors.AnthropicInvalidDataException
+import com.fasterxml.jackson.annotation.JsonAnyGetter
+import com.fasterxml.jackson.annotation.JsonAnySetter
+import com.fasterxml.jackson.annotation.JsonCreator
+import com.fasterxml.jackson.annotation.JsonProperty
+import java.util.Collections
+import java.util.Objects
+import java.util.Optional
+
+/** Default configuration for tools in an MCP toolset. */
+class BetaMcpToolDefaultConfig
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
+private constructor(
+ private val deferLoading: JsonField,
+ private val enabled: JsonField,
+ private val additionalProperties: MutableMap,
+) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("defer_loading")
+ @ExcludeMissing
+ deferLoading: JsonField = JsonMissing.of(),
+ @JsonProperty("enabled") @ExcludeMissing enabled: JsonField = JsonMissing.of(),
+ ) : this(deferLoading, enabled, mutableMapOf())
+
+ /**
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun deferLoading(): Optional = deferLoading.getOptional("defer_loading")
+
+ /**
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun enabled(): Optional = enabled.getOptional("enabled")
+
+ /**
+ * Returns the raw JSON value of [deferLoading].
+ *
+ * Unlike [deferLoading], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("defer_loading")
+ @ExcludeMissing
+ fun _deferLoading(): JsonField = deferLoading
+
+ /**
+ * Returns the raw JSON value of [enabled].
+ *
+ * Unlike [enabled], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("enabled") @ExcludeMissing fun _enabled(): JsonField = enabled
+
+ @JsonAnySetter
+ private fun putAdditionalProperty(key: String, value: JsonValue) {
+ additionalProperties.put(key, value)
+ }
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map =
+ Collections.unmodifiableMap(additionalProperties)
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /** Returns a mutable builder for constructing an instance of [BetaMcpToolDefaultConfig]. */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [BetaMcpToolDefaultConfig]. */
+ class Builder internal constructor() {
+
+ private var deferLoading: JsonField = JsonMissing.of()
+ private var enabled: JsonField = JsonMissing.of()
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(betaMcpToolDefaultConfig: BetaMcpToolDefaultConfig) = apply {
+ deferLoading = betaMcpToolDefaultConfig.deferLoading
+ enabled = betaMcpToolDefaultConfig.enabled
+ additionalProperties = betaMcpToolDefaultConfig.additionalProperties.toMutableMap()
+ }
+
+ fun deferLoading(deferLoading: Boolean) = deferLoading(JsonField.of(deferLoading))
+
+ /**
+ * Sets [Builder.deferLoading] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.deferLoading] with a well-typed [Boolean] value instead.
+ * This method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun deferLoading(deferLoading: JsonField) = apply {
+ this.deferLoading = deferLoading
+ }
+
+ fun enabled(enabled: Boolean) = enabled(JsonField.of(enabled))
+
+ /**
+ * Sets [Builder.enabled] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.enabled] with a well-typed [Boolean] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun enabled(enabled: JsonField) = apply { this.enabled = enabled }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [BetaMcpToolDefaultConfig].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ */
+ fun build(): BetaMcpToolDefaultConfig =
+ BetaMcpToolDefaultConfig(deferLoading, enabled, additionalProperties.toMutableMap())
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): BetaMcpToolDefaultConfig = apply {
+ if (validated) {
+ return@apply
+ }
+
+ deferLoading()
+ enabled()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: AnthropicInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int =
+ (if (deferLoading.asKnown().isPresent) 1 else 0) +
+ (if (enabled.asKnown().isPresent) 1 else 0)
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is BetaMcpToolDefaultConfig &&
+ deferLoading == other.deferLoading &&
+ enabled == other.enabled &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy { Objects.hash(deferLoading, enabled, additionalProperties) }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "BetaMcpToolDefaultConfig{deferLoading=$deferLoading, enabled=$enabled, additionalProperties=$additionalProperties}"
+}
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMcpToolResultBlock.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMcpToolResultBlock.kt
index 0dc9f6d9a..06bf685c2 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMcpToolResultBlock.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMcpToolResultBlock.kt
@@ -464,7 +464,7 @@ private constructor(
.toList()
return when (bestMatches.size) {
// This can happen if what we're deserializing is completely incompatible with
- // all the possible variants (e.g. deserializing from object).
+ // all the possible variants (e.g. deserializing from boolean).
0 -> Content(_json = json)
1 -> bestMatches.single()
// If there's more than one match with the highest validity, then use the first
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMcpToolset.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMcpToolset.kt
new file mode 100644
index 000000000..725aef43d
--- /dev/null
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMcpToolset.kt
@@ -0,0 +1,464 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.anthropic.models.beta.messages
+
+import com.anthropic.core.ExcludeMissing
+import com.anthropic.core.JsonField
+import com.anthropic.core.JsonMissing
+import com.anthropic.core.JsonValue
+import com.anthropic.core.checkRequired
+import com.anthropic.core.toImmutable
+import com.anthropic.errors.AnthropicInvalidDataException
+import com.fasterxml.jackson.annotation.JsonAnyGetter
+import com.fasterxml.jackson.annotation.JsonAnySetter
+import com.fasterxml.jackson.annotation.JsonCreator
+import com.fasterxml.jackson.annotation.JsonProperty
+import java.util.Collections
+import java.util.Objects
+import java.util.Optional
+import kotlin.jvm.optionals.getOrNull
+
+/**
+ * Configuration for a group of tools from an MCP server.
+ *
+ * Allows configuring enabled status and defer_loading for all tools from an MCP server, with
+ * optional per-tool overrides.
+ */
+class BetaMcpToolset
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
+private constructor(
+ private val mcpServerName: JsonField,
+ private val type: JsonValue,
+ private val cacheControl: JsonField,
+ private val configs: JsonField,
+ private val defaultConfig: JsonField,
+ private val additionalProperties: MutableMap,
+) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("mcp_server_name")
+ @ExcludeMissing
+ mcpServerName: JsonField = JsonMissing.of(),
+ @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(),
+ @JsonProperty("cache_control")
+ @ExcludeMissing
+ cacheControl: JsonField = JsonMissing.of(),
+ @JsonProperty("configs") @ExcludeMissing configs: JsonField = JsonMissing.of(),
+ @JsonProperty("default_config")
+ @ExcludeMissing
+ defaultConfig: JsonField = JsonMissing.of(),
+ ) : this(mcpServerName, type, cacheControl, configs, defaultConfig, mutableMapOf())
+
+ /**
+ * Name of the MCP server to configure tools for
+ *
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type or is
+ * unexpectedly missing or null (e.g. if the server responded with an unexpected value).
+ */
+ fun mcpServerName(): String = mcpServerName.getRequired("mcp_server_name")
+
+ /**
+ * Expected to always return the following:
+ * ```java
+ * JsonValue.from("mcp_toolset")
+ * ```
+ *
+ * However, this method can be useful for debugging and logging (e.g. if the server responded
+ * with an unexpected value).
+ */
+ @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type
+
+ /**
+ * Create a cache control breakpoint at this content block.
+ *
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun cacheControl(): Optional =
+ cacheControl.getOptional("cache_control")
+
+ /**
+ * Configuration overrides for specific tools, keyed by tool name
+ *
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun configs(): Optional = configs.getOptional("configs")
+
+ /**
+ * Default configuration applied to all tools from this server
+ *
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun defaultConfig(): Optional =
+ defaultConfig.getOptional("default_config")
+
+ /**
+ * Returns the raw JSON value of [mcpServerName].
+ *
+ * Unlike [mcpServerName], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("mcp_server_name")
+ @ExcludeMissing
+ fun _mcpServerName(): JsonField = mcpServerName
+
+ /**
+ * Returns the raw JSON value of [cacheControl].
+ *
+ * Unlike [cacheControl], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("cache_control")
+ @ExcludeMissing
+ fun _cacheControl(): JsonField = cacheControl
+
+ /**
+ * Returns the raw JSON value of [configs].
+ *
+ * Unlike [configs], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("configs") @ExcludeMissing fun _configs(): JsonField = configs
+
+ /**
+ * Returns the raw JSON value of [defaultConfig].
+ *
+ * Unlike [defaultConfig], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("default_config")
+ @ExcludeMissing
+ fun _defaultConfig(): JsonField = defaultConfig
+
+ @JsonAnySetter
+ private fun putAdditionalProperty(key: String, value: JsonValue) {
+ additionalProperties.put(key, value)
+ }
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map =
+ Collections.unmodifiableMap(additionalProperties)
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /**
+ * Returns a mutable builder for constructing an instance of [BetaMcpToolset].
+ *
+ * The following fields are required:
+ * ```java
+ * .mcpServerName()
+ * ```
+ */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [BetaMcpToolset]. */
+ class Builder internal constructor() {
+
+ private var mcpServerName: JsonField? = null
+ private var type: JsonValue = JsonValue.from("mcp_toolset")
+ private var cacheControl: JsonField = JsonMissing.of()
+ private var configs: JsonField = JsonMissing.of()
+ private var defaultConfig: JsonField = JsonMissing.of()
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(betaMcpToolset: BetaMcpToolset) = apply {
+ mcpServerName = betaMcpToolset.mcpServerName
+ type = betaMcpToolset.type
+ cacheControl = betaMcpToolset.cacheControl
+ configs = betaMcpToolset.configs
+ defaultConfig = betaMcpToolset.defaultConfig
+ additionalProperties = betaMcpToolset.additionalProperties.toMutableMap()
+ }
+
+ /** Name of the MCP server to configure tools for */
+ fun mcpServerName(mcpServerName: String) = mcpServerName(JsonField.of(mcpServerName))
+
+ /**
+ * Sets [Builder.mcpServerName] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.mcpServerName] with a well-typed [String] value instead.
+ * This method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun mcpServerName(mcpServerName: JsonField) = apply {
+ this.mcpServerName = mcpServerName
+ }
+
+ /**
+ * Sets the field to an arbitrary JSON value.
+ *
+ * It is usually unnecessary to call this method because the field defaults to the
+ * following:
+ * ```java
+ * JsonValue.from("mcp_toolset")
+ * ```
+ *
+ * This method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun type(type: JsonValue) = apply { this.type = type }
+
+ /** Create a cache control breakpoint at this content block. */
+ fun cacheControl(cacheControl: BetaCacheControlEphemeral?) =
+ cacheControl(JsonField.ofNullable(cacheControl))
+
+ /** Alias for calling [Builder.cacheControl] with `cacheControl.orElse(null)`. */
+ fun cacheControl(cacheControl: Optional) =
+ cacheControl(cacheControl.getOrNull())
+
+ /**
+ * Sets [Builder.cacheControl] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.cacheControl] with a well-typed
+ * [BetaCacheControlEphemeral] value instead. This method is primarily for setting the field
+ * to an undocumented or not yet supported value.
+ */
+ fun cacheControl(cacheControl: JsonField) = apply {
+ this.cacheControl = cacheControl
+ }
+
+ /** Configuration overrides for specific tools, keyed by tool name */
+ fun configs(configs: Configs?) = configs(JsonField.ofNullable(configs))
+
+ /** Alias for calling [Builder.configs] with `configs.orElse(null)`. */
+ fun configs(configs: Optional) = configs(configs.getOrNull())
+
+ /**
+ * Sets [Builder.configs] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.configs] with a well-typed [Configs] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun configs(configs: JsonField) = apply { this.configs = configs }
+
+ /** Default configuration applied to all tools from this server */
+ fun defaultConfig(defaultConfig: BetaMcpToolDefaultConfig) =
+ defaultConfig(JsonField.of(defaultConfig))
+
+ /**
+ * Sets [Builder.defaultConfig] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.defaultConfig] with a well-typed
+ * [BetaMcpToolDefaultConfig] value instead. This method is primarily for setting the field
+ * to an undocumented or not yet supported value.
+ */
+ fun defaultConfig(defaultConfig: JsonField) = apply {
+ this.defaultConfig = defaultConfig
+ }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [BetaMcpToolset].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ *
+ * The following fields are required:
+ * ```java
+ * .mcpServerName()
+ * ```
+ *
+ * @throws IllegalStateException if any required field is unset.
+ */
+ fun build(): BetaMcpToolset =
+ BetaMcpToolset(
+ checkRequired("mcpServerName", mcpServerName),
+ type,
+ cacheControl,
+ configs,
+ defaultConfig,
+ additionalProperties.toMutableMap(),
+ )
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): BetaMcpToolset = apply {
+ if (validated) {
+ return@apply
+ }
+
+ mcpServerName()
+ _type().let {
+ if (it != JsonValue.from("mcp_toolset")) {
+ throw AnthropicInvalidDataException("'type' is invalid, received $it")
+ }
+ }
+ cacheControl().ifPresent { it.validate() }
+ configs().ifPresent { it.validate() }
+ defaultConfig().ifPresent { it.validate() }
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: AnthropicInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int =
+ (if (mcpServerName.asKnown().isPresent) 1 else 0) +
+ type.let { if (it == JsonValue.from("mcp_toolset")) 1 else 0 } +
+ (cacheControl.asKnown().getOrNull()?.validity() ?: 0) +
+ (configs.asKnown().getOrNull()?.validity() ?: 0) +
+ (defaultConfig.asKnown().getOrNull()?.validity() ?: 0)
+
+ /** Configuration overrides for specific tools, keyed by tool name */
+ class Configs
+ @JsonCreator
+ private constructor(
+ @com.fasterxml.jackson.annotation.JsonValue
+ private val additionalProperties: Map
+ ) {
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map = additionalProperties
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /** Returns a mutable builder for constructing an instance of [Configs]. */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [Configs]. */
+ class Builder internal constructor() {
+
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(configs: Configs) = apply {
+ additionalProperties = configs.additionalProperties.toMutableMap()
+ }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [Configs].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ */
+ fun build(): Configs = Configs(additionalProperties.toImmutable())
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): Configs = apply {
+ if (validated) {
+ return@apply
+ }
+
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: AnthropicInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int =
+ additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is Configs && additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy { Objects.hash(additionalProperties) }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() = "Configs{additionalProperties=$additionalProperties}"
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is BetaMcpToolset &&
+ mcpServerName == other.mcpServerName &&
+ type == other.type &&
+ cacheControl == other.cacheControl &&
+ configs == other.configs &&
+ defaultConfig == other.defaultConfig &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy {
+ Objects.hash(
+ mcpServerName,
+ type,
+ cacheControl,
+ configs,
+ defaultConfig,
+ additionalProperties,
+ )
+ }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "BetaMcpToolset{mcpServerName=$mcpServerName, type=$type, cacheControl=$cacheControl, configs=$configs, defaultConfig=$defaultConfig, additionalProperties=$additionalProperties}"
+}
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMemoryTool20250818.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMemoryTool20250818.kt
index 9ebe66c86..952d2eb5f 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMemoryTool20250818.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMemoryTool20250818.kt
@@ -2,10 +2,13 @@
package com.anthropic.models.beta.messages
+import com.anthropic.core.Enum
import com.anthropic.core.ExcludeMissing
import com.anthropic.core.JsonField
import com.anthropic.core.JsonMissing
import com.anthropic.core.JsonValue
+import com.anthropic.core.checkKnown
+import com.anthropic.core.toImmutable
import com.anthropic.errors.AnthropicInvalidDataException
import com.fasterxml.jackson.annotation.JsonAnyGetter
import com.fasterxml.jackson.annotation.JsonAnySetter
@@ -21,7 +24,10 @@ class BetaMemoryTool20250818
private constructor(
private val name: JsonValue,
private val type: JsonValue,
+ private val allowedCallers: JsonField>,
private val cacheControl: JsonField,
+ private val deferLoading: JsonField,
+ private val inputExamples: JsonField>,
private val strict: JsonField,
private val additionalProperties: MutableMap,
) {
@@ -30,11 +36,29 @@ private constructor(
private constructor(
@JsonProperty("name") @ExcludeMissing name: JsonValue = JsonMissing.of(),
@JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(),
+ @JsonProperty("allowed_callers")
+ @ExcludeMissing
+ allowedCallers: JsonField> = JsonMissing.of(),
@JsonProperty("cache_control")
@ExcludeMissing
cacheControl: JsonField = JsonMissing.of(),
+ @JsonProperty("defer_loading")
+ @ExcludeMissing
+ deferLoading: JsonField = JsonMissing.of(),
+ @JsonProperty("input_examples")
+ @ExcludeMissing
+ inputExamples: JsonField> = JsonMissing.of(),
@JsonProperty("strict") @ExcludeMissing strict: JsonField = JsonMissing.of(),
- ) : this(name, type, cacheControl, strict, mutableMapOf())
+ ) : this(
+ name,
+ type,
+ allowedCallers,
+ cacheControl,
+ deferLoading,
+ inputExamples,
+ strict,
+ mutableMapOf(),
+ )
/**
* Name of the tool.
@@ -62,6 +86,13 @@ private constructor(
*/
@JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type
+ /**
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun allowedCallers(): Optional> =
+ allowedCallers.getOptional("allowed_callers")
+
/**
* Create a cache control breakpoint at this content block.
*
@@ -71,12 +102,36 @@ private constructor(
fun cacheControl(): Optional =
cacheControl.getOptional("cache_control")
+ /**
+ * If true, tool will not be included in initial system prompt. Only loaded when returned via
+ * tool_reference from tool search.
+ *
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun deferLoading(): Optional = deferLoading.getOptional("defer_loading")
+
+ /**
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun inputExamples(): Optional> = inputExamples.getOptional("input_examples")
+
/**
* @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
* server responded with an unexpected value).
*/
fun strict(): Optional = strict.getOptional("strict")
+ /**
+ * Returns the raw JSON value of [allowedCallers].
+ *
+ * Unlike [allowedCallers], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("allowed_callers")
+ @ExcludeMissing
+ fun _allowedCallers(): JsonField> = allowedCallers
+
/**
* Returns the raw JSON value of [cacheControl].
*
@@ -86,6 +141,24 @@ private constructor(
@ExcludeMissing
fun _cacheControl(): JsonField = cacheControl
+ /**
+ * Returns the raw JSON value of [deferLoading].
+ *
+ * Unlike [deferLoading], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("defer_loading")
+ @ExcludeMissing
+ fun _deferLoading(): JsonField = deferLoading
+
+ /**
+ * Returns the raw JSON value of [inputExamples].
+ *
+ * Unlike [inputExamples], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("input_examples")
+ @ExcludeMissing
+ fun _inputExamples(): JsonField> = inputExamples
+
/**
* Returns the raw JSON value of [strict].
*
@@ -116,7 +189,10 @@ private constructor(
private var name: JsonValue = JsonValue.from("memory")
private var type: JsonValue = JsonValue.from("memory_20250818")
+ private var allowedCallers: JsonField>? = null
private var cacheControl: JsonField = JsonMissing.of()
+ private var deferLoading: JsonField = JsonMissing.of()
+ private var inputExamples: JsonField>? = null
private var strict: JsonField = JsonMissing.of()
private var additionalProperties: MutableMap = mutableMapOf()
@@ -124,7 +200,10 @@ private constructor(
internal fun from(betaMemoryTool20250818: BetaMemoryTool20250818) = apply {
name = betaMemoryTool20250818.name
type = betaMemoryTool20250818.type
+ allowedCallers = betaMemoryTool20250818.allowedCallers.map { it.toMutableList() }
cacheControl = betaMemoryTool20250818.cacheControl
+ deferLoading = betaMemoryTool20250818.deferLoading
+ inputExamples = betaMemoryTool20250818.inputExamples.map { it.toMutableList() }
strict = betaMemoryTool20250818.strict
additionalProperties = betaMemoryTool20250818.additionalProperties.toMutableMap()
}
@@ -157,6 +236,32 @@ private constructor(
*/
fun type(type: JsonValue) = apply { this.type = type }
+ fun allowedCallers(allowedCallers: List) =
+ allowedCallers(JsonField.of(allowedCallers))
+
+ /**
+ * Sets [Builder.allowedCallers] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.allowedCallers] with a well-typed `List`
+ * value instead. This method is primarily for setting the field to an undocumented or not
+ * yet supported value.
+ */
+ fun allowedCallers(allowedCallers: JsonField>) = apply {
+ this.allowedCallers = allowedCallers.map { it.toMutableList() }
+ }
+
+ /**
+ * Adds a single [AllowedCaller] to [allowedCallers].
+ *
+ * @throws IllegalStateException if the field was previously set to a non-list.
+ */
+ fun addAllowedCaller(allowedCaller: AllowedCaller) = apply {
+ allowedCallers =
+ (allowedCallers ?: JsonField.of(mutableListOf())).also {
+ checkKnown("allowedCallers", it).add(allowedCaller)
+ }
+ }
+
/** Create a cache control breakpoint at this content block. */
fun cacheControl(cacheControl: BetaCacheControlEphemeral?) =
cacheControl(JsonField.ofNullable(cacheControl))
@@ -176,6 +281,49 @@ private constructor(
this.cacheControl = cacheControl
}
+ /**
+ * If true, tool will not be included in initial system prompt. Only loaded when returned
+ * via tool_reference from tool search.
+ */
+ fun deferLoading(deferLoading: Boolean) = deferLoading(JsonField.of(deferLoading))
+
+ /**
+ * Sets [Builder.deferLoading] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.deferLoading] with a well-typed [Boolean] value instead.
+ * This method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun deferLoading(deferLoading: JsonField) = apply {
+ this.deferLoading = deferLoading
+ }
+
+ fun inputExamples(inputExamples: List) =
+ inputExamples(JsonField.of(inputExamples))
+
+ /**
+ * Sets [Builder.inputExamples] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.inputExamples] with a well-typed `List`
+ * value instead. This method is primarily for setting the field to an undocumented or not
+ * yet supported value.
+ */
+ fun inputExamples(inputExamples: JsonField>) = apply {
+ this.inputExamples = inputExamples.map { it.toMutableList() }
+ }
+
+ /**
+ * Adds a single [InputExample] to [inputExamples].
+ *
+ * @throws IllegalStateException if the field was previously set to a non-list.
+ */
+ fun addInputExample(inputExample: InputExample) = apply {
+ inputExamples =
+ (inputExamples ?: JsonField.of(mutableListOf())).also {
+ checkKnown("inputExamples", it).add(inputExample)
+ }
+ }
+
fun strict(strict: Boolean) = strict(JsonField.of(strict))
/**
@@ -214,7 +362,10 @@ private constructor(
BetaMemoryTool20250818(
name,
type,
+ (allowedCallers ?: JsonMissing.of()).map { it.toImmutable() },
cacheControl,
+ deferLoading,
+ (inputExamples ?: JsonMissing.of()).map { it.toImmutable() },
strict,
additionalProperties.toMutableMap(),
)
@@ -237,7 +388,10 @@ private constructor(
throw AnthropicInvalidDataException("'type' is invalid, received $it")
}
}
+ allowedCallers().ifPresent { it.forEach { it.validate() } }
cacheControl().ifPresent { it.validate() }
+ deferLoading()
+ inputExamples().ifPresent { it.forEach { it.validate() } }
strict()
validated = true
}
@@ -259,9 +413,242 @@ private constructor(
internal fun validity(): Int =
name.let { if (it == JsonValue.from("memory")) 1 else 0 } +
type.let { if (it == JsonValue.from("memory_20250818")) 1 else 0 } +
+ (allowedCallers.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) +
(cacheControl.asKnown().getOrNull()?.validity() ?: 0) +
+ (if (deferLoading.asKnown().isPresent) 1 else 0) +
+ (inputExamples.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) +
(if (strict.asKnown().isPresent) 1 else 0)
+ class AllowedCaller @JsonCreator private constructor(private val value: JsonField) :
+ Enum {
+
+ /**
+ * Returns this class instance's raw value.
+ *
+ * This is usually only useful if this instance was deserialized from data that doesn't
+ * match any known member, and you want to know that value. For example, if the SDK is on an
+ * older version than the API, then the API may respond with new members that the SDK is
+ * unaware of.
+ */
+ @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value
+
+ companion object {
+
+ @JvmField val DIRECT = of("direct")
+
+ @JvmField val CODE_EXECUTION_20250825 = of("code_execution_20250825")
+
+ @JvmStatic fun of(value: String) = AllowedCaller(JsonField.of(value))
+ }
+
+ /** An enum containing [AllowedCaller]'s known values. */
+ enum class Known {
+ DIRECT,
+ CODE_EXECUTION_20250825,
+ }
+
+ /**
+ * An enum containing [AllowedCaller]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [AllowedCaller] can contain an unknown value in a couple of cases:
+ * - It was deserialized from data that doesn't match any known member. For example, if the
+ * SDK is on an older version than the API, then the API may respond with new members that
+ * the SDK is unaware of.
+ * - It was constructed with an arbitrary value using the [of] method.
+ */
+ enum class Value {
+ DIRECT,
+ CODE_EXECUTION_20250825,
+ /**
+ * An enum member indicating that [AllowedCaller] was instantiated with an unknown
+ * value.
+ */
+ _UNKNOWN,
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN]
+ * if the class was instantiated with an unknown value.
+ *
+ * Use the [known] method instead if you're certain the value is always known or if you want
+ * to throw for the unknown case.
+ */
+ fun value(): Value =
+ when (this) {
+ DIRECT -> Value.DIRECT
+ CODE_EXECUTION_20250825 -> Value.CODE_EXECUTION_20250825
+ else -> Value._UNKNOWN
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value.
+ *
+ * Use the [value] method instead if you're uncertain the value is always known and don't
+ * want to throw for the unknown case.
+ *
+ * @throws AnthropicInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ DIRECT -> Known.DIRECT
+ CODE_EXECUTION_20250825 -> Known.CODE_EXECUTION_20250825
+ else -> throw AnthropicInvalidDataException("Unknown AllowedCaller: $value")
+ }
+
+ /**
+ * Returns this class instance's primitive wire representation.
+ *
+ * This differs from the [toString] method because that method is primarily for debugging
+ * and generally doesn't throw.
+ *
+ * @throws AnthropicInvalidDataException if this class instance's value does not have the
+ * expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString().orElseThrow {
+ AnthropicInvalidDataException("Value is not a String")
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): AllowedCaller = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: AnthropicInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is AllowedCaller && value == other.value
+ }
+
+ override fun hashCode() = value.hashCode()
+
+ override fun toString() = value.toString()
+ }
+
+ class InputExample
+ @JsonCreator
+ private constructor(
+ @com.fasterxml.jackson.annotation.JsonValue
+ private val additionalProperties: Map
+ ) {
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map = additionalProperties
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /** Returns a mutable builder for constructing an instance of [InputExample]. */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [InputExample]. */
+ class Builder internal constructor() {
+
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(inputExample: InputExample) = apply {
+ additionalProperties = inputExample.additionalProperties.toMutableMap()
+ }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [InputExample].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ */
+ fun build(): InputExample = InputExample(additionalProperties.toImmutable())
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): InputExample = apply {
+ if (validated) {
+ return@apply
+ }
+
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: AnthropicInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int =
+ additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is InputExample && additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy { Objects.hash(additionalProperties) }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() = "InputExample{additionalProperties=$additionalProperties}"
+ }
+
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
@@ -270,17 +657,29 @@ private constructor(
return other is BetaMemoryTool20250818 &&
name == other.name &&
type == other.type &&
+ allowedCallers == other.allowedCallers &&
cacheControl == other.cacheControl &&
+ deferLoading == other.deferLoading &&
+ inputExamples == other.inputExamples &&
strict == other.strict &&
additionalProperties == other.additionalProperties
}
private val hashCode: Int by lazy {
- Objects.hash(name, type, cacheControl, strict, additionalProperties)
+ Objects.hash(
+ name,
+ type,
+ allowedCallers,
+ cacheControl,
+ deferLoading,
+ inputExamples,
+ strict,
+ additionalProperties,
+ )
}
override fun hashCode(): Int = hashCode
override fun toString() =
- "BetaMemoryTool20250818{name=$name, type=$type, cacheControl=$cacheControl, strict=$strict, additionalProperties=$additionalProperties}"
+ "BetaMemoryTool20250818{name=$name, type=$type, allowedCallers=$allowedCallers, cacheControl=$cacheControl, deferLoading=$deferLoading, inputExamples=$inputExamples, strict=$strict, additionalProperties=$additionalProperties}"
}
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMessage.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMessage.kt
index 585472aa1..de6459884 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMessage.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMessage.kt
@@ -519,6 +519,13 @@ private constructor(
)
)
+ /**
+ * Alias for calling [addContent] with
+ * `BetaContentBlock.ofToolSearchToolResult(toolSearchToolResult)`.
+ */
+ fun addContent(toolSearchToolResult: BetaToolSearchToolResultBlock) =
+ addContent(BetaContentBlock.ofToolSearchToolResult(toolSearchToolResult))
+
/** Alias for calling [addContent] with `BetaContentBlock.ofMcpToolUse(mcpToolUse)`. */
fun addContent(mcpToolUse: BetaMcpToolUseBlock) =
addContent(BetaContentBlock.ofMcpToolUse(mcpToolUse))
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMessageParam.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMessageParam.kt
index 17bfe73ee..610f6512c 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMessageParam.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaMessageParam.kt
@@ -364,7 +364,7 @@ private constructor(
.toList()
return when (bestMatches.size) {
// This can happen if what we're deserializing is completely incompatible with
- // all the possible variants (e.g. deserializing from object).
+ // all the possible variants (e.g. deserializing from boolean).
0 -> Content(_json = json)
1 -> bestMatches.single()
// If there's more than one match with the highest validity, then use the first
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaOutputConfig.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaOutputConfig.kt
new file mode 100644
index 000000000..eb6aa7d77
--- /dev/null
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaOutputConfig.kt
@@ -0,0 +1,340 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.anthropic.models.beta.messages
+
+import com.anthropic.core.Enum
+import com.anthropic.core.ExcludeMissing
+import com.anthropic.core.JsonField
+import com.anthropic.core.JsonMissing
+import com.anthropic.core.JsonValue
+import com.anthropic.errors.AnthropicInvalidDataException
+import com.fasterxml.jackson.annotation.JsonAnyGetter
+import com.fasterxml.jackson.annotation.JsonAnySetter
+import com.fasterxml.jackson.annotation.JsonCreator
+import com.fasterxml.jackson.annotation.JsonProperty
+import java.util.Collections
+import java.util.Objects
+import java.util.Optional
+import kotlin.jvm.optionals.getOrNull
+
+class BetaOutputConfig
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
+private constructor(
+ private val effort: JsonField,
+ private val format: JsonField,
+ private val additionalProperties: MutableMap,
+) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("effort") @ExcludeMissing effort: JsonField = JsonMissing.of(),
+ @JsonProperty("format")
+ @ExcludeMissing
+ format: JsonField = JsonMissing.of(),
+ ) : this(effort, format, mutableMapOf())
+
+ /**
+ * All possible effort levels.
+ *
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun effort(): Optional = effort.getOptional("effort")
+
+ /**
+ * A schema to specify Claude's output format in responses. See
+ * [structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs)
+ *
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun format(): Optional = format.getOptional("format")
+
+ /**
+ * Returns the raw JSON value of [effort].
+ *
+ * Unlike [effort], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("effort") @ExcludeMissing fun _effort(): JsonField = effort
+
+ /**
+ * Returns the raw JSON value of [format].
+ *
+ * Unlike [format], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("format") @ExcludeMissing fun _format(): JsonField = format
+
+ @JsonAnySetter
+ private fun putAdditionalProperty(key: String, value: JsonValue) {
+ additionalProperties.put(key, value)
+ }
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map =
+ Collections.unmodifiableMap(additionalProperties)
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /** Returns a mutable builder for constructing an instance of [BetaOutputConfig]. */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [BetaOutputConfig]. */
+ class Builder internal constructor() {
+
+ private var effort: JsonField = JsonMissing.of()
+ private var format: JsonField = JsonMissing.of()
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(betaOutputConfig: BetaOutputConfig) = apply {
+ effort = betaOutputConfig.effort
+ format = betaOutputConfig.format
+ additionalProperties = betaOutputConfig.additionalProperties.toMutableMap()
+ }
+
+ /** All possible effort levels. */
+ fun effort(effort: Effort?) = effort(JsonField.ofNullable(effort))
+
+ /** Alias for calling [Builder.effort] with `effort.orElse(null)`. */
+ fun effort(effort: Optional) = effort(effort.getOrNull())
+
+ /**
+ * Sets [Builder.effort] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.effort] with a well-typed [Effort] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun effort(effort: JsonField) = apply { this.effort = effort }
+
+ /**
+ * A schema to specify Claude's output format in responses. See
+ * [structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs)
+ */
+ fun format(format: BetaJsonOutputFormat?) = format(JsonField.ofNullable(format))
+
+ /** Alias for calling [Builder.format] with `format.orElse(null)`. */
+ fun format(format: Optional) = format(format.getOrNull())
+
+ /**
+ * Sets [Builder.format] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.format] with a well-typed [BetaJsonOutputFormat] value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun format(format: JsonField) = apply { this.format = format }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [BetaOutputConfig].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ */
+ fun build(): BetaOutputConfig =
+ BetaOutputConfig(effort, format, additionalProperties.toMutableMap())
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): BetaOutputConfig = apply {
+ if (validated) {
+ return@apply
+ }
+
+ effort().ifPresent { it.validate() }
+ format().ifPresent { it.validate() }
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: AnthropicInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int =
+ (effort.asKnown().getOrNull()?.validity() ?: 0) +
+ (format.asKnown().getOrNull()?.validity() ?: 0)
+
+ /** All possible effort levels. */
+ class Effort @JsonCreator private constructor(private val value: JsonField) : Enum {
+
+ /**
+ * Returns this class instance's raw value.
+ *
+ * This is usually only useful if this instance was deserialized from data that doesn't
+ * match any known member, and you want to know that value. For example, if the SDK is on an
+ * older version than the API, then the API may respond with new members that the SDK is
+ * unaware of.
+ */
+ @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value
+
+ companion object {
+
+ @JvmField val LOW = of("low")
+
+ @JvmField val MEDIUM = of("medium")
+
+ @JvmField val HIGH = of("high")
+
+ @JvmStatic fun of(value: String) = Effort(JsonField.of(value))
+ }
+
+ /** An enum containing [Effort]'s known values. */
+ enum class Known {
+ LOW,
+ MEDIUM,
+ HIGH,
+ }
+
+ /**
+ * An enum containing [Effort]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [Effort] can contain an unknown value in a couple of cases:
+ * - It was deserialized from data that doesn't match any known member. For example, if the
+ * SDK is on an older version than the API, then the API may respond with new members that
+ * the SDK is unaware of.
+ * - It was constructed with an arbitrary value using the [of] method.
+ */
+ enum class Value {
+ LOW,
+ MEDIUM,
+ HIGH,
+ /** An enum member indicating that [Effort] was instantiated with an unknown value. */
+ _UNKNOWN,
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN]
+ * if the class was instantiated with an unknown value.
+ *
+ * Use the [known] method instead if you're certain the value is always known or if you want
+ * to throw for the unknown case.
+ */
+ fun value(): Value =
+ when (this) {
+ LOW -> Value.LOW
+ MEDIUM -> Value.MEDIUM
+ HIGH -> Value.HIGH
+ else -> Value._UNKNOWN
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value.
+ *
+ * Use the [value] method instead if you're uncertain the value is always known and don't
+ * want to throw for the unknown case.
+ *
+ * @throws AnthropicInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ LOW -> Known.LOW
+ MEDIUM -> Known.MEDIUM
+ HIGH -> Known.HIGH
+ else -> throw AnthropicInvalidDataException("Unknown Effort: $value")
+ }
+
+ /**
+ * Returns this class instance's primitive wire representation.
+ *
+ * This differs from the [toString] method because that method is primarily for debugging
+ * and generally doesn't throw.
+ *
+ * @throws AnthropicInvalidDataException if this class instance's value does not have the
+ * expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString().orElseThrow {
+ AnthropicInvalidDataException("Value is not a String")
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): Effort = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: AnthropicInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is Effort && value == other.value
+ }
+
+ override fun hashCode() = value.hashCode()
+
+ override fun toString() = value.toString()
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is BetaOutputConfig &&
+ effort == other.effort &&
+ format == other.format &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy { Objects.hash(effort, format, additionalProperties) }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "BetaOutputConfig{effort=$effort, format=$format, additionalProperties=$additionalProperties}"
+}
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaRawContentBlockStartEvent.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaRawContentBlockStartEvent.kt
index 6bd5c38e9..9e6db7582 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaRawContentBlockStartEvent.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaRawContentBlockStartEvent.kt
@@ -214,6 +214,13 @@ private constructor(
ContentBlock.ofTextEditorCodeExecutionToolResult(textEditorCodeExecutionToolResult)
)
+ /**
+ * Alias for calling [contentBlock] with
+ * `ContentBlock.ofToolSearchToolResult(toolSearchToolResult)`.
+ */
+ fun contentBlock(toolSearchToolResult: BetaToolSearchToolResultBlock) =
+ contentBlock(ContentBlock.ofToolSearchToolResult(toolSearchToolResult))
+
/** Alias for calling [contentBlock] with `ContentBlock.ofMcpToolUse(mcpToolUse)`. */
fun contentBlock(mcpToolUse: BetaMcpToolUseBlock) =
contentBlock(ContentBlock.ofMcpToolUse(mcpToolUse))
@@ -356,6 +363,7 @@ private constructor(
private val bashCodeExecutionToolResult: BetaBashCodeExecutionToolResultBlock? = null,
private val textEditorCodeExecutionToolResult: BetaTextEditorCodeExecutionToolResultBlock? =
null,
+ private val toolSearchToolResult: BetaToolSearchToolResultBlock? = null,
private val mcpToolUse: BetaMcpToolUseBlock? = null,
private val mcpToolResult: BetaMcpToolResultBlock? = null,
private val containerUpload: BetaContainerUploadBlock? = null,
@@ -389,6 +397,9 @@ private constructor(
Optional =
Optional.ofNullable(textEditorCodeExecutionToolResult)
+ fun toolSearchToolResult(): Optional =
+ Optional.ofNullable(toolSearchToolResult)
+
fun mcpToolUse(): Optional = Optional.ofNullable(mcpToolUse)
fun mcpToolResult(): Optional = Optional.ofNullable(mcpToolResult)
@@ -418,6 +429,8 @@ private constructor(
fun isTextEditorCodeExecutionToolResult(): Boolean =
textEditorCodeExecutionToolResult != null
+ fun isToolSearchToolResult(): Boolean = toolSearchToolResult != null
+
fun isMcpToolUse(): Boolean = mcpToolUse != null
fun isMcpToolResult(): Boolean = mcpToolResult != null
@@ -450,6 +463,9 @@ private constructor(
fun asTextEditorCodeExecutionToolResult(): BetaTextEditorCodeExecutionToolResultBlock =
textEditorCodeExecutionToolResult.getOrThrow("textEditorCodeExecutionToolResult")
+ fun asToolSearchToolResult(): BetaToolSearchToolResultBlock =
+ toolSearchToolResult.getOrThrow("toolSearchToolResult")
+
fun asMcpToolUse(): BetaMcpToolUseBlock = mcpToolUse.getOrThrow("mcpToolUse")
fun asMcpToolResult(): BetaMcpToolResultBlock = mcpToolResult.getOrThrow("mcpToolResult")
@@ -477,6 +493,8 @@ private constructor(
visitor.visitTextEditorCodeExecutionToolResult(
textEditorCodeExecutionToolResult
)
+ toolSearchToolResult != null ->
+ visitor.visitToolSearchToolResult(toolSearchToolResult)
mcpToolUse != null -> visitor.visitMcpToolUse(mcpToolUse)
mcpToolResult != null -> visitor.visitMcpToolResult(mcpToolResult)
containerUpload != null -> visitor.visitContainerUpload(containerUpload)
@@ -545,6 +563,12 @@ private constructor(
textEditorCodeExecutionToolResult.validate()
}
+ override fun visitToolSearchToolResult(
+ toolSearchToolResult: BetaToolSearchToolResultBlock
+ ) {
+ toolSearchToolResult.validate()
+ }
+
override fun visitMcpToolUse(mcpToolUse: BetaMcpToolUseBlock) {
mcpToolUse.validate()
}
@@ -613,6 +637,10 @@ private constructor(
BetaTextEditorCodeExecutionToolResultBlock
) = textEditorCodeExecutionToolResult.validity()
+ override fun visitToolSearchToolResult(
+ toolSearchToolResult: BetaToolSearchToolResultBlock
+ ) = toolSearchToolResult.validity()
+
override fun visitMcpToolUse(mcpToolUse: BetaMcpToolUseBlock) =
mcpToolUse.validity()
@@ -642,6 +670,7 @@ private constructor(
codeExecutionToolResult == other.codeExecutionToolResult &&
bashCodeExecutionToolResult == other.bashCodeExecutionToolResult &&
textEditorCodeExecutionToolResult == other.textEditorCodeExecutionToolResult &&
+ toolSearchToolResult == other.toolSearchToolResult &&
mcpToolUse == other.mcpToolUse &&
mcpToolResult == other.mcpToolResult &&
containerUpload == other.containerUpload
@@ -659,6 +688,7 @@ private constructor(
codeExecutionToolResult,
bashCodeExecutionToolResult,
textEditorCodeExecutionToolResult,
+ toolSearchToolResult,
mcpToolUse,
mcpToolResult,
containerUpload,
@@ -680,6 +710,8 @@ private constructor(
"ContentBlock{bashCodeExecutionToolResult=$bashCodeExecutionToolResult}"
textEditorCodeExecutionToolResult != null ->
"ContentBlock{textEditorCodeExecutionToolResult=$textEditorCodeExecutionToolResult}"
+ toolSearchToolResult != null ->
+ "ContentBlock{toolSearchToolResult=$toolSearchToolResult}"
mcpToolUse != null -> "ContentBlock{mcpToolUse=$mcpToolUse}"
mcpToolResult != null -> "ContentBlock{mcpToolResult=$mcpToolResult}"
containerUpload != null -> "ContentBlock{containerUpload=$containerUpload}"
@@ -727,6 +759,10 @@ private constructor(
textEditorCodeExecutionToolResult: BetaTextEditorCodeExecutionToolResultBlock
) = ContentBlock(textEditorCodeExecutionToolResult = textEditorCodeExecutionToolResult)
+ @JvmStatic
+ fun ofToolSearchToolResult(toolSearchToolResult: BetaToolSearchToolResultBlock) =
+ ContentBlock(toolSearchToolResult = toolSearchToolResult)
+
@JvmStatic
fun ofMcpToolUse(mcpToolUse: BetaMcpToolUseBlock) =
ContentBlock(mcpToolUse = mcpToolUse)
@@ -773,6 +809,8 @@ private constructor(
textEditorCodeExecutionToolResult: BetaTextEditorCodeExecutionToolResultBlock
): T
+ fun visitToolSearchToolResult(toolSearchToolResult: BetaToolSearchToolResultBlock): T
+
fun visitMcpToolUse(mcpToolUse: BetaMcpToolUseBlock): T
fun visitMcpToolResult(mcpToolResult: BetaMcpToolResultBlock): T
@@ -862,6 +900,11 @@ private constructor(
ContentBlock(textEditorCodeExecutionToolResult = it, _json = json)
} ?: ContentBlock(_json = json)
}
+ "tool_search_tool_result" -> {
+ return tryDeserialize(node, jacksonTypeRef())
+ ?.let { ContentBlock(toolSearchToolResult = it, _json = json) }
+ ?: ContentBlock(_json = json)
+ }
"mcp_tool_use" -> {
return tryDeserialize(node, jacksonTypeRef())?.let {
ContentBlock(mcpToolUse = it, _json = json)
@@ -906,6 +949,8 @@ private constructor(
generator.writeObject(value.bashCodeExecutionToolResult)
value.textEditorCodeExecutionToolResult != null ->
generator.writeObject(value.textEditorCodeExecutionToolResult)
+ value.toolSearchToolResult != null ->
+ generator.writeObject(value.toolSearchToolResult)
value.mcpToolUse != null -> generator.writeObject(value.mcpToolUse)
value.mcpToolResult != null -> generator.writeObject(value.mcpToolResult)
value.containerUpload != null -> generator.writeObject(value.containerUpload)
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaRequestMcpToolResultBlockParam.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaRequestMcpToolResultBlockParam.kt
index f816a0a84..ba839ebdc 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaRequestMcpToolResultBlockParam.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaRequestMcpToolResultBlockParam.kt
@@ -484,7 +484,7 @@ private constructor(
.toList()
return when (bestMatches.size) {
// This can happen if what we're deserializing is completely incompatible with
- // all the possible variants (e.g. deserializing from object).
+ // all the possible variants (e.g. deserializing from boolean).
0 -> Content(_json = json)
1 -> bestMatches.single()
// If there's more than one match with the highest validity, then use the first
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaServerToolCaller.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaServerToolCaller.kt
new file mode 100644
index 000000000..5add5faaf
--- /dev/null
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaServerToolCaller.kt
@@ -0,0 +1,210 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.anthropic.models.beta.messages
+
+import com.anthropic.core.ExcludeMissing
+import com.anthropic.core.JsonField
+import com.anthropic.core.JsonMissing
+import com.anthropic.core.JsonValue
+import com.anthropic.core.checkRequired
+import com.anthropic.errors.AnthropicInvalidDataException
+import com.fasterxml.jackson.annotation.JsonAnyGetter
+import com.fasterxml.jackson.annotation.JsonAnySetter
+import com.fasterxml.jackson.annotation.JsonCreator
+import com.fasterxml.jackson.annotation.JsonProperty
+import java.util.Collections
+import java.util.Objects
+
+/** Tool invocation generated by a server-side tool. */
+class BetaServerToolCaller
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
+private constructor(
+ private val toolId: JsonField,
+ private val type: JsonValue,
+ private val additionalProperties: MutableMap,
+) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("tool_id") @ExcludeMissing toolId: JsonField = JsonMissing.of(),
+ @JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(),
+ ) : this(toolId, type, mutableMapOf())
+
+ /**
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type or is
+ * unexpectedly missing or null (e.g. if the server responded with an unexpected value).
+ */
+ fun toolId(): String = toolId.getRequired("tool_id")
+
+ /**
+ * Expected to always return the following:
+ * ```java
+ * JsonValue.from("code_execution_20250825")
+ * ```
+ *
+ * However, this method can be useful for debugging and logging (e.g. if the server responded
+ * with an unexpected value).
+ */
+ @JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type
+
+ /**
+ * Returns the raw JSON value of [toolId].
+ *
+ * Unlike [toolId], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("tool_id") @ExcludeMissing fun _toolId(): JsonField = toolId
+
+ @JsonAnySetter
+ private fun putAdditionalProperty(key: String, value: JsonValue) {
+ additionalProperties.put(key, value)
+ }
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map =
+ Collections.unmodifiableMap(additionalProperties)
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /**
+ * Returns a mutable builder for constructing an instance of [BetaServerToolCaller].
+ *
+ * The following fields are required:
+ * ```java
+ * .toolId()
+ * ```
+ */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [BetaServerToolCaller]. */
+ class Builder internal constructor() {
+
+ private var toolId: JsonField? = null
+ private var type: JsonValue = JsonValue.from("code_execution_20250825")
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(betaServerToolCaller: BetaServerToolCaller) = apply {
+ toolId = betaServerToolCaller.toolId
+ type = betaServerToolCaller.type
+ additionalProperties = betaServerToolCaller.additionalProperties.toMutableMap()
+ }
+
+ fun toolId(toolId: String) = toolId(JsonField.of(toolId))
+
+ /**
+ * Sets [Builder.toolId] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.toolId] with a well-typed [String] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun toolId(toolId: JsonField) = apply { this.toolId = toolId }
+
+ /**
+ * Sets the field to an arbitrary JSON value.
+ *
+ * It is usually unnecessary to call this method because the field defaults to the
+ * following:
+ * ```java
+ * JsonValue.from("code_execution_20250825")
+ * ```
+ *
+ * This method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun type(type: JsonValue) = apply { this.type = type }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [BetaServerToolCaller].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ *
+ * The following fields are required:
+ * ```java
+ * .toolId()
+ * ```
+ *
+ * @throws IllegalStateException if any required field is unset.
+ */
+ fun build(): BetaServerToolCaller =
+ BetaServerToolCaller(
+ checkRequired("toolId", toolId),
+ type,
+ additionalProperties.toMutableMap(),
+ )
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): BetaServerToolCaller = apply {
+ if (validated) {
+ return@apply
+ }
+
+ toolId()
+ _type().let {
+ if (it != JsonValue.from("code_execution_20250825")) {
+ throw AnthropicInvalidDataException("'type' is invalid, received $it")
+ }
+ }
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: AnthropicInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int =
+ (if (toolId.asKnown().isPresent) 1 else 0) +
+ type.let { if (it == JsonValue.from("code_execution_20250825")) 1 else 0 }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is BetaServerToolCaller &&
+ toolId == other.toolId &&
+ type == other.type &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy { Objects.hash(toolId, type, additionalProperties) }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "BetaServerToolCaller{toolId=$toolId, type=$type, additionalProperties=$additionalProperties}"
+}
diff --git a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaServerToolUseBlock.kt b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaServerToolUseBlock.kt
index 8b703b152..f25bea0f1 100644
--- a/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaServerToolUseBlock.kt
+++ b/anthropic-java-core/src/main/kotlin/com/anthropic/models/beta/messages/BetaServerToolUseBlock.kt
@@ -2,19 +2,30 @@
package com.anthropic.models.beta.messages
+import com.anthropic.core.BaseDeserializer
+import com.anthropic.core.BaseSerializer
import com.anthropic.core.Enum
import com.anthropic.core.ExcludeMissing
import com.anthropic.core.JsonField
import com.anthropic.core.JsonMissing
import com.anthropic.core.JsonValue
import com.anthropic.core.checkRequired
+import com.anthropic.core.getOrThrow
import com.anthropic.errors.AnthropicInvalidDataException
import com.fasterxml.jackson.annotation.JsonAnyGetter
import com.fasterxml.jackson.annotation.JsonAnySetter
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
+import com.fasterxml.jackson.core.JsonGenerator
+import com.fasterxml.jackson.core.ObjectCodec
+import com.fasterxml.jackson.databind.JsonNode
+import com.fasterxml.jackson.databind.SerializerProvider
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize
+import com.fasterxml.jackson.databind.annotation.JsonSerialize
+import com.fasterxml.jackson.module.kotlin.jacksonTypeRef
import java.util.Collections
import java.util.Objects
+import java.util.Optional
import kotlin.jvm.optionals.getOrNull
class BetaServerToolUseBlock
@@ -24,6 +35,7 @@ private constructor(
private val input: JsonValue,
private val name: JsonField,
private val type: JsonValue,
+ private val caller: JsonField,
private val additionalProperties: MutableMap,
) {
@@ -33,13 +45,36 @@ private constructor(
@JsonProperty("input") @ExcludeMissing input: JsonValue = JsonMissing.of(),
@JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(),
@JsonProperty("type") @ExcludeMissing type: JsonValue = JsonMissing.of(),
- ) : this(id, input, name, type, mutableMapOf())
+ @JsonProperty("caller") @ExcludeMissing caller: JsonField = JsonMissing.of(),
+ ) : this(id, input, name, type, caller, mutableMapOf())
fun toParam(): BetaServerToolUseBlockParam =
BetaServerToolUseBlockParam.builder()
.id(_id())
.input(_input())
.name(_name().map { BetaServerToolUseBlockParam.Name.of(it.toString()) })
+ .caller(
+ _caller().map {
+ it.accept(
+ object :
+ BetaServerToolUseBlock.Caller.Visitor<
+ BetaServerToolUseBlockParam.Caller
+ > {
+ override fun visitDirect(
+ direct: BetaDirectCaller
+ ): BetaServerToolUseBlockParam.Caller =
+ BetaServerToolUseBlockParam.Caller.ofDirect(direct)
+
+ override fun visitCodeExecution20250825(
+ codeExecution20250825: BetaServerToolCaller
+ ): BetaServerToolUseBlockParam.Caller =
+ BetaServerToolUseBlockParam.Caller.ofDirect(
+ BetaDirectCaller.builder().build()
+ )
+ }
+ )
+ }
+ )
.build()
/**
@@ -67,6 +102,22 @@ private constructor(
*/
@JsonProperty("type") @ExcludeMissing fun _type(): JsonValue = type
+ /**
+ * Tool invocation directly from the model.
+ *
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun caller(): Optional = caller.getOptional("caller")
+
+ /**
+ * Returns the raw JSON value of [id].
+ *
+ * @throws AnthropicInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun caller(): Optional = caller.getOptional("caller")
+
/**
* Returns the raw JSON value of [id].
*
@@ -81,6 +132,20 @@ private constructor(
*/
@JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name
+ /**
+ * Returns the raw JSON value of [caller].
+ *
+ * Unlike [caller], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("caller") @ExcludeMissing fun _caller(): JsonField = caller
+
+ /**
+ * Returns the raw JSON value of [caller].
+ *
+ * Unlike [caller], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("caller") @ExcludeMissing fun _caller(): JsonField = caller
+
@JsonAnySetter
private fun putAdditionalProperty(key: String, value: JsonValue) {
additionalProperties.put(key, value)
@@ -112,9 +177,11 @@ private constructor(
class Builder internal constructor() {
private var id: JsonField? = null
+ private var caller: JsonField? = null
private var input: JsonValue? = null
private var name: JsonField? = null
private var type: JsonValue = JsonValue.from("server_tool_use")
+ private var caller: JsonField = JsonMissing.of()
private var additionalProperties: MutableMap = mutableMapOf()
@JvmSynthetic
@@ -123,6 +190,7 @@ private constructor(
input = betaServerToolUseBlock.input
name = betaServerToolUseBlock.name
type = betaServerToolUseBlock.type
+ caller = betaServerToolUseBlock.caller
additionalProperties = betaServerToolUseBlock.additionalProperties.toMutableMap()
}
@@ -138,6 +206,37 @@ private constructor(
fun input(input: JsonValue) = apply { this.input = input }
+ /** Tool invocation directly from the model. */
+ fun caller(caller: Caller) = caller(JsonField.of(caller))
+
+ /**
+ * Sets [Builder.caller] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.caller] with a well-typed [Caller] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun caller(caller: JsonField) = apply { this.caller = caller }
+
+ /** Alias for calling [caller] with `Caller.ofDirect(direct)`. */
+ fun caller(direct: BetaDirectCaller) = caller(Caller.ofDirect(direct))
+
+ /**
+ * Alias for calling [caller] with `Caller.ofCodeExecution20250825(codeExecution20250825)`.
+ */
+ fun caller(codeExecution20250825: BetaServerToolCaller) =
+ caller(Caller.ofCodeExecution20250825(codeExecution20250825))
+
+ /**
+ * Alias for calling [caller] with the following:
+ * ```java
+ * BetaServerToolCaller.builder()
+ * .toolId(toolId)
+ * .build()
+ * ```
+ */
+ fun codeExecution20250825Caller(toolId: String) =
+ caller(BetaServerToolCaller.builder().toolId(toolId).build())
+
fun name(name: Name) = name(JsonField.of(name))
/**
@@ -162,6 +261,37 @@ private constructor(
*/
fun type(type: JsonValue) = apply { this.type = type }
+ /** Tool invocation directly from the model. */
+ fun caller(caller: Caller) = caller(JsonField.of(caller))
+
+ /**
+ * Sets [Builder.caller] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.caller] with a well-typed [Caller] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun caller(caller: JsonField) = apply { this.caller = caller }
+
+ /** Alias for calling [caller] with `Caller.ofDirect(direct)`. */
+ fun caller(direct: BetaDirectCaller) = caller(Caller.ofDirect(direct))
+
+ /**
+ * Alias for calling [caller] with `Caller.ofCodeExecution20250825(codeExecution20250825)`.
+ */
+ fun caller(codeExecution20250825: BetaServerToolCaller) =
+ caller(Caller.ofCodeExecution20250825(codeExecution20250825))
+
+ /**
+ * Alias for calling [caller] with the following:
+ * ```java
+ * BetaServerToolCaller.builder()
+ * .toolId(toolId)
+ * .build()
+ * ```
+ */
+ fun codeExecution20250825Caller(toolId: String) =
+ caller(BetaServerToolCaller.builder().toolId(toolId).build())
+
fun additionalProperties(additionalProperties: Map