English ← MyDocs

Java SDK

安装和配置 Anthropic Java SDK,支持构建器模式和异步操作


Anthropic Java SDK 为使用 Java 编写的应用程序提供对 Anthropic REST API 的便捷访问。它使用构建器模式创建请求,并支持同步和异步操作。

Info

有关带有代码示例的 API 功能文档,请参阅 API 参考。本页面介绍 Java 特定的 SDK 功能和配置。

安装

implementation("com.anthropic:anthropic-java:2.33.0")
<dependency>
    <groupId>com.anthropic</groupId>
    <artifactId>anthropic-java</artifactId>
    <version>2.33.0</version>
</dependency>

要求

此库需要 Java 8 或更高版本。

Note

SDK 支持 Java 8 及更高版本。本文档中的代码示例以 JDK 25 紧凑源文件 格式编写,使用裸 void main() 入口点和 IO.println() 进行输出。API 调用本身在每个支持的 JDK 上都相同;要在较早版本上编译示例,请将 IO.println(...) 替换为 System.out.println(...),并将主体放在类中的 public static void main(String[] args) 内。

快速开始

import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;

// 使用 `anthropic.apiKey`、`anthropic.authToken` 和 `anthropic.baseUrl` 系统属性配置
// 或使用 `ANTHROPIC_API_KEY`、`ANTHROPIC_AUTH_TOKEN` 和 `ANTHROPIC_BASE_URL` 环境变量配置
AnthropicClient client = AnthropicOkHttpClient.fromEnv();

MessageCreateParams params = MessageCreateParams.builder()
  .maxTokens(1024L)
  .addUserMessage("Hello, Claude")
  .model(Model.CLAUDE_OPUS_4_7)
  .build();

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

客户端配置

API 密钥设置

使用系统属性或环境变量配置客户端:

import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

// 使用 `anthropic.apiKey`、`anthropic.authToken` 和 `anthropic.baseUrl` 系统属性配置
// 或使用 `ANTHROPIC_API_KEY`、`ANTHROPIC_AUTH_TOKEN` 和 `ANTHROPIC_BASE_URL` 环境变量配置
AnthropicClient client = AnthropicOkHttpClient.fromEnv();

或手动配置:

import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

AnthropicClient client = AnthropicOkHttpClient.builder()
  .apiKey("my-anthropic-api-key")
  .build();

或使用两种方式的组合:

import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

AnthropicClient client = AnthropicOkHttpClient.builder()
  // 使用系统属性或环境变量配置
  .fromEnv()
  .apiKey("my-anthropic-api-key")
  .build();

有关认证选项(包括 Workload Identity Federation),请参阅认证

配置选项

设置器系统属性环境变量必填默认值
apiKeyanthropic.apiKeyANTHROPIC_API_KEYfalse-
authTokenanthropic.authTokenANTHROPIC_AUTH_TOKENfalse-
baseUrlanthropic.baseUrlANTHROPIC_BASE_URLtrue"https://api.anthropic.com"

系统属性优先于环境变量。

Tip

不要在同一个应用程序中创建多个客户端。每个客户端都有连接池和线程池,在请求之间共享更高效。

修改配置

要临时使用修改后的客户端配置,同时复用相同的连接和线程池,请在任何客户端或服务上调用 withOptions()

import com.anthropic.client.AnthropicClient;

AnthropicClient clientWithOptions = client.withOptions(optionsBuilder -> {
  optionsBuilder.baseUrl("https://example.com");
  optionsBuilder.maxRetries(42);
});

withOptions() 方法不会影响原始客户端或服务。

异步用法

默认客户端是同步的。要切换到异步执行,请调用 async() 方法:

import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;

AnthropicClient client = AnthropicOkHttpClient.fromEnv();

MessageCreateParams params = MessageCreateParams.builder()
  .maxTokens(1024L)
  .addUserMessage("Hello, Claude")
  .model(Model.CLAUDE_OPUS_4_7)
  .build();

CompletableFuture<Message> message = client.async().messages().create(params);

或从一开始就创建异步客户端:

import com.anthropic.client.AnthropicClientAsync;
import com.anthropic.client.okhttp.AnthropicOkHttpClientAsync;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;

AnthropicClientAsync client = AnthropicOkHttpClientAsync.fromEnv();

MessageCreateParams params = MessageCreateParams.builder()
  .maxTokens(1024L)
  .addUserMessage("Hello, Claude")
  .model(Model.CLAUDE_OPUS_4_7)
  .build();

CompletableFuture<Message> message = client.messages().create(params);

异步客户端支持与同步客户端相同的选项,但大多数方法返回 CompletableFuture

流式传输

SDK 定义了返回响应"分块"流的方法,每个分块在到达时即可单独处理,而无需等待完整响应。

同步流式传输

这些流式传输方法为同步客户端返回 StreamResponse

import com.anthropic.core.http.StreamResponse;
import com.anthropic.models.messages.RawMessageStreamEvent;

try (StreamResponse<RawMessageStreamEvent> streamResponse = client.messages().createStreaming(params)) {
    streamResponse.stream().forEach(chunk -> {
        IO.println(chunk);
    });
    IO.println("No more chunks!");
}

异步流式传输

对于异步客户端,该方法返回 AsyncStreamResponse

import com.anthropic.core.http.AsyncStreamResponse;
import com.anthropic.models.messages.RawMessageStreamEvent;

client.async().messages().createStreaming(params).subscribe(chunk -> {
    IO.println(chunk);
});

// 如果你需要处理流的错误或完成
client.async().messages().createStreaming(params).subscribe(new AsyncStreamResponse.Handler<>() {
    @Override
    public void onNext(RawMessageStreamEvent chunk) {
        IO.println(chunk);
    }

    @Override
    public void onComplete(Optional<Throwable> error) {
        if (error.isPresent()) {
            IO.println("Something went wrong!");
            throw new RuntimeException(error.get());
        } else {
            IO.println("No more chunks!");
        }
    }
});

// 或使用 futures
client.async().messages().createStreaming(params)
    .subscribe(chunk -> {
        IO.println(chunk);
    })
    .onCompleteFuture()
    .whenComplete((unused, error) -> {
        if (error != null) {
            IO.println("Something went wrong!");
            throw new RuntimeException(error);
        } else {
            IO.println("No more chunks!");
        }
    });

异步流式传输使用每个客户端专用的缓存线程池 Executor 进行流式传输,不会阻塞当前线程。要使用不同的 Executor

Executor executor = Executors.newFixedThreadPool(4);
client.async().messages().createStreaming(params).subscribe(
    chunk -> IO.println(chunk), executor
);

或使用 streamHandlerExecutor 方法全局配置客户端:

import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

AnthropicClient client = AnthropicOkHttpClient.builder()
  .fromEnv()
  .streamHandlerExecutor(Executors.newFixedThreadPool(4))
  .build();

使用消息累加器进行流式传输

MessageAccumulator 可以在处理响应时记录事件流,并累积一个类似于非流式 API 返回的 Message 对象。

对于同步响应,在流管道中添加 Stream.peek() 调用以累积每个事件:

import com.anthropic.core.http.StreamResponse;
import com.anthropic.helpers.MessageAccumulator;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.RawMessageStreamEvent;

MessageAccumulator messageAccumulator = MessageAccumulator.create();

try (StreamResponse<RawMessageStreamEvent> streamResponse =
         client.messages().createStreaming(createParams)) {
    streamResponse.stream()
            .peek(messageAccumulator::accumulate)
            .flatMap(event -> event.contentBlockDelta().stream())
            .flatMap(deltaEvent -> deltaEvent.delta().text().stream())
            .forEach(textDelta -> IO.print(textDelta.text()));
}

Message message = messageAccumulator.message();

对于异步响应,将 MessageAccumulator 添加到 subscribe() 调用中:

import com.anthropic.helpers.MessageAccumulator;
import com.anthropic.models.messages.Message;

MessageAccumulator messageAccumulator = MessageAccumulator.create();

client.async().messages()
        .createStreaming(createParams)
        .subscribe(event -> messageAccumulator.accumulate(event).contentBlockDelta().stream()
                .flatMap(deltaEvent -> deltaEvent.delta().text().stream())
                .forEach(textDelta -> IO.print(textDelta.text())))
        .onCompleteFuture()
        .join();

Message message = messageAccumulator.message();

BetaMessageAccumulator 也可用于累积 BetaMessage 对象。它的使用方式与 MessageAccumulator 相同。

结构化输出

有关包含 Java 示例的完整结构化输出文档,请参阅结构化输出

工具使用

与 Claude 的工具使用 允许你将外部工具和函数直接集成到 AI 模型的响应中。模型不是生成纯文本,而是在适当时输出调用工具或函数的指令(带参数)。你为工具定义 JSON 模式,模型使用这些模式来决定何时以及如何使用这些工具。

工具使用功能支持"严格"模式,保证 AI 模型的 JSON 输出符合你在输入参数中提供的 JSON 模式。

SDK 可以从任意 Java 类的结构自动推导工具及其参数:类的名称(转换为蛇形命名)提供工具名称,类的字段定义工具的参数。

Note

将你的工具类声明为顶级类或 static 嵌套类。此要求来自 Jackson Databind 库(com.fasterxml.jackson.databind),SDK 使用它将工具输入反序列化为你的类实例,无法实例化非静态内部类。

使用注解定义工具

import com.fasterxml.jackson.annotation.JsonClassDescription;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;

enum Unit {
  CELSIUS,
  FAHRENHEIT;

  public String toString() {
    switch (this) {
      case CELSIUS:
        return "C";
      case FAHRENHEIT:
      default:
        return "F";
    }
  }

  public double fromKelvin(double temperatureK) {
    switch (this) {
      case CELSIUS:
        return temperatureK - 273.15;
      case FAHRENHEIT:
      default:
        return (temperatureK - 273.15) * 1.8 + 32.0;
    }
  }
}

@JsonClassDescription("Get the weather in a given location")
static class GetWeather {

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

  @JsonPropertyDescription("The unit of temperature")
  public Unit unit;

  public Weather execute() {
    double temperatureK;
    switch (location) {
      case "San Francisco, CA":
        temperatureK = 300.0;
        break;
      case "New York, NY":
        temperatureK = 310.0;
        break;
      case "Dallas, TX":
        temperatureK = 305.0;
        break;
      default:
        temperatureK = 295;
        break;
    }
    return new Weather(String.format("%.0f%s", unit.fromKelvin(temperatureK), unit));
  }
}

static class Weather {

  public String temperature;

  public Weather(String temperature) {
    this.temperature = temperature;
  }
}

调用工具

定义工具类后,使用 MessageCreateParams.Builder.addTool(Class<T>) 将它们添加到消息参数中,然后在 AI 模型的响应中请求时调用它们。BetaToolUseBlock.input(Class<T>) 可用于将工具的 JSON 格式参数解析为工具定义类的实例。

调用工具后,使用 BetaToolResultBlockParam.Builder.contentAsJson(Object) 将工具的结果传递回 AI 模型:

import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.beta.messages.*;
import com.anthropic.models.messages.Model;

AnthropicClient client = AnthropicOkHttpClient.fromEnv();

MessageCreateParams.Builder createParamsBuilder = MessageCreateParams.builder()
        .model(Model.CLAUDE_OPUS_4_7)
        .maxTokens(2048)
        .addTool(GetWeather.class)
        .addUserMessage("What's the temperature in New York?");

client.beta().messages().create(createParamsBuilder.build()).content().stream()
        .flatMap(contentBlock -> contentBlock.toolUse().stream())
        .forEach(toolUseBlock -> createParamsBuilder
              // 添加一条消息,指示请求了工具使用。
              .addAssistantMessageOfBetaContentBlockParams(
                      List.of(BetaContentBlockParam.ofToolUse(BetaToolUseBlockParam.builder()
                              .name(toolUseBlock.name())
                              .id(toolUseBlock.id())
                              .input(toolUseBlock._input())
                              .build())))
              // 添加一条消息,包含请求的工具使用的结果。
              .addUserMessageOfBetaContentBlockParams(
                      List.of(BetaContentBlockParam.ofToolResult(BetaToolResultBlockParam.builder()
                              .toolUseId(toolUseBlock.id())
                              .contentAsJson(callTool(toolUseBlock))
                              .build()))));

client.beta().messages().create(createParamsBuilder.build()).content().stream()
        .flatMap(contentBlock -> contentBlock.text().stream())
        .forEach(textBlock -> IO.println(textBlock.text()));

private static Object callTool(BetaToolUseBlock toolUseBlock) {
  if (!"get_weather".equals(toolUseBlock.name())) {
    throw new IllegalArgumentException("Unknown tool: " + toolUseBlock.name());
  }

  GetWeather tool = toolUseBlock.input(GetWeather.class);
  return tool != null ? tool.execute() : new Weather("unknown");
}

工具名称转换

工具名称从驼峰命名的工具类名(如 GetWeather)派生并转换为蛇形命名(如 get_weather)。单词边界开始于当前字符不是第一个字符、是大写字母,且前一个字符是小写字母或后一个字符是小写字母的位置。例如,MyJSONParser 变为 my_json_parserParseJSON 变为 parse_json。可以使用 @JsonTypeName 注解覆盖此转换。

本地工具 JSON 模式验证

你可以执行本地验证来检查从工具类推导的 JSON 模式是否符合 Anthropic 的限制。本地验证默认启用,但可以禁用:

MessageCreateParams.Builder createParamsBuilder = MessageCreateParams.builder()
  .model(Model.CLAUDE_OPUS_4_7)
  .maxTokens(2048)
  .addTool(GetWeather.class, JsonSchemaLocalValidation.NO)
  .addUserMessage("What's the temperature in New York?");

注解工具类

你可以使用注解向 JSON 模式添加有关工具的更多信息:

  • @JsonClassDescription - 向工具类添加描述,详细说明何时以及如何使用该工具。
  • @JsonTypeName - 将工具名称设置为类名转换为蛇形命名以外的值。
  • @JsonPropertyDescription - 向工具参数添加详细描述。
  • @JsonIgnore - 从生成的工具参数 JSON 模式中排除 public 字段或 getter 方法。
  • @JsonProperty - 将非 public 字段或 getter 方法包含在生成的工具参数 JSON 模式中。

消息批处理

SDK 在 client.messages().batches() 命名空间下提供批处理支持。有关如何列出和分页批处理,请参阅分页

文件上传

SDK 定义了通过 MultipartField 类接受文件的方法:

import com.anthropic.core.MultipartField;
import com.anthropic.models.beta.files.FileMetadata;
import com.anthropic.models.beta.files.FileUploadParams;

FileUploadParams params = FileUploadParams.builder()
  .file(
    MultipartField.<InputStream>builder()
      .value(Files.newInputStream(Paths.get("/path/to/file.pdf")))
      .contentType("application/pdf")
      .build()
  )
  .build();

FileMetadata fileMetadata = client.beta().files().upload(params);

或从 InputStream

import com.anthropic.core.MultipartField;
import com.anthropic.models.beta.files.FileMetadata;
import com.anthropic.models.beta.files.FileUploadParams;

FileUploadParams params = FileUploadParams.builder()
  .file(
    MultipartField.<InputStream>builder()
      .value(new URL("https://example.com/path/to/file").openStream())
      .filename("document.pdf")
      .contentType("application/pdf")
      .build()
  )
  .build();

FileMetadata fileMetadata = client.beta().files().upload(params);

或从内存中的字节:

import com.anthropic.core.MultipartField;
import com.anthropic.models.beta.files.FileMetadata;
import com.anthropic.models.beta.files.FileUploadParams;

FileUploadParams params = FileUploadParams.builder()
  .file(
    MultipartField.<InputStream>builder()
      .value(new ByteArrayInputStream("content".getBytes()))
      .filename("document.txt")
      .contentType("text/plain")
      .build()
  )
  .build();

FileMetadata fileMetadata = client.beta().files().upload(params);

二进制响应

SDK 定义了返回二进制响应的方法,用于不一定要作为 JSON 解析的 API 响应:

import com.anthropic.core.http.HttpResponse;

HttpResponse response = client.beta().files().download("file_id");

要将响应内容保存到文件:

import com.anthropic.core.http.HttpResponse;

try (HttpResponse response = client.beta().files().download(params)) {
    Files.copy(
        response.body(),
        Paths.get(path),
        StandardCopyOption.REPLACE_EXISTING
    );
} catch (Exception e) {
    IO.println("Something went wrong!");
    throw new RuntimeException(e);
}

或将响应内容传输到任何 OutputStream

import com.anthropic.core.http.HttpResponse;

try (HttpResponse response = client.beta().files().download(params)) {
    response.body().transferTo(Files.newOutputStream(Paths.get(path)));
} catch (Exception e) {
    IO.println("Something went wrong!");
    throw new RuntimeException(e);
}

错误处理

SDK 抛出自定义的非受检异常类型:

  • AnthropicServiceException - HTTP 错误的基类。
  • AnthropicIoException - I/O 网络错误。
  • AnthropicRetryableException - 指示可能可重试的失败的通用错误。
  • AnthropicInvalidDataException - 解释已成功解析的数据失败(例如,当访问应该必需但 API 意外省略的属性时)。
  • AnthropicException - 所有异常的基类。

状态码映射

状态码异常
400BadRequestException
401UnauthorizedException
403PermissionDeniedException
404NotFoundException
422UnprocessableEntityException
429RateLimitException
5xxInternalServerException
其他UnexpectedStatusCodeException

在初始 HTTP 响应成功后,SSE 流式传输过程中遇到错误时会抛出 SseException

import com.anthropic.errors.*;

try {
    Message message = client.messages().create(params);
} catch (RateLimitException e) {
    IO.println("Rate limited, retry after: " + e.headers());
} catch (UnauthorizedException e) {
    IO.println("Invalid API key");
} catch (AnthropicServiceException e) {
    IO.println("API error: " + e.statusCode());
} catch (AnthropicIoException e) {
    IO.println("Network error: " + e.getMessage());
}

请求 ID

使用原始响应时,你可以使用 requestId() 方法访问 request-id 响应头:

import com.anthropic.core.http.HttpResponseFor;
import com.anthropic.models.messages.Message;

HttpResponseFor<Message> message = client.messages().withRawResponse().create(params);

Optional<String> requestId = message.requestId();

这可用于快速记录失败的请求并向 Anthropic 报告。有关调试请求的更多信息,请参阅请求 ID

重试

SDK 默认自动重试 2 次,请求之间有短暂的指数退避。

仅重试以下错误类型:

  • 连接错误(例如,由于网络连接问题)
  • 408 请求超时
  • 409 冲突
  • 429 速率限制
  • 5xx 内部错误

API 也可能明确指示 SDK 重试或不重试请求。

要设置自定义重试次数,请使用 maxRetries 方法配置客户端:

import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

AnthropicClient client = AnthropicOkHttpClient.builder().fromEnv().maxRetries(4).build();

超时

请求默认在 10 分钟后超时。

但是,对于接受 maxTokens 的方法,如果你指定了较大的 maxTokens 值并且正在使用流式传输,则默认超时将使用以下公式动态计算:

Duration.ofSeconds(
    Math.min(
        60 * 60, // 最大 1 小时
        Math.max(
            10 * 60, // 最小 10 分钟
            60 * 60 * maxTokens / 128_000
        )
    )
)

这将导致最多 60 分钟的超时,按 maxTokens 参数缩放,除非被覆盖。

对于非流式请求,动态超时从 30 秒最小值到 10 分钟最大值,基于 maxTokens 缩放。

要为每个请求设置自定义超时:

import com.anthropic.models.messages.Message;

Message message = client
  .messages()
  .create(params, RequestOptions.builder().timeout(Duration.ofSeconds(30)).build());

或在客户端级别为所有方法调用配置默认值:

import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

AnthropicClient client = AnthropicOkHttpClient.builder()
  .fromEnv()
  .timeout(Duration.ofSeconds(30))
  .build();

长请求

Warning

对于较长时间运行的请求,请考虑使用流式传输

避免在不使用流式传输的情况下设置较大的 maxTokens 值。某些网络可能会在一段时间后断开空闲连接,这可能导致请求失败或超时而无法收到来自 Anthropic 的响应。SDK 会定期向 API 发送 ping 以保持连接活动,减少这些网络的影响。

如果非流式请求预计超过 10 分钟,SDK 会抛出错误。使用流式传输方法或在客户端或请求级别覆盖超时会禁用此错误。

分页

SDK 提供了便捷的方式逐页或逐项访问分页结果。

自动分页

要遍历所有页面的结果,请使用 autoPager() 方法,它会根据需要自动获取更多页面。

import com.anthropic.models.messages.batches.BatchListPage;
import com.anthropic.models.messages.batches.MessageBatch;

BatchListPage page = client.messages().batches().list();

// 作为 Iterable 处理
for (MessageBatch batch : page.autoPager()) {
    IO.println(batch);
}

// 作为 Stream 处理
page.autoPager()
    .stream()
    .limit(50)
    .forEach(batch -> IO.println(batch));

使用异步客户端时,该方法返回 AsyncStreamResponse

import com.anthropic.core.http.AsyncStreamResponse;
import com.anthropic.models.messages.batches.BatchListPageAsync;
import com.anthropic.models.messages.batches.MessageBatch;

CompletableFuture<BatchListPageAsync> pageFuture = client.async().messages().batches().list();

pageFuture.thenAccept(page -> page.autoPager().subscribe(batch -> {
    IO.println(batch);
}));

// 如果你需要处理流的错误或完成
pageFuture.thenAccept(page -> page.autoPager().subscribe(new AsyncStreamResponse.Handler<>() {
    @Override
    public void onNext(MessageBatch batch) {
        IO.println(batch);
    }

    @Override
    public void onComplete(Optional<Throwable> error) {
        if (error.isPresent()) {
            IO.println("Something went wrong!");
            throw new RuntimeException(error.get());
        } else {
            IO.println("No more!");
        }
    }
}));

// 或使用 futures
pageFuture.thenAccept(page -> page.autoPager()
    .subscribe(batch -> {
        IO.println(batch);
    })
    .onCompleteFuture()
    .whenComplete((unused, error) -> {
        if (error != null) {
            IO.println("Something went wrong!");
            throw new RuntimeException(error);
        } else {
            IO.println("No more!");
        }
    }));

手动分页

要访问单个页面项目并手动请求下一页:

import com.anthropic.models.messages.batches.BatchListPage;
import com.anthropic.models.messages.batches.MessageBatch;

BatchListPage page = client.messages().batches().list();
while (true) {
    for (MessageBatch batch : page.items()) {
        IO.println(batch);
    }

    if (!page.hasNextPage()) {
        break;
    }

    page = page.nextPage();
}

类型系统

不可变性和构建器

SDK 中的每个类都有一个关联的构建器用于构造。每个类一旦构造就是不可变的。如果类有关联的构建器,则它有 toBuilder() 方法,可用于将其转换回构建器以制作修改后的副本。

MessageCreateParams params = MessageCreateParams.builder()
  .maxTokens(1024L)
  .addUserMessage("Hello, Claude")
  .model(Model.CLAUDE_OPUS_4_7)
  .build();

// 使用 toBuilder() 创建修改后的副本
MessageCreateParams modified = params.toBuilder().maxTokens(2048L).build();

因为每个类都是不可变的,构建器修改永远不会影响已构建的类实例。

请求和响应

要向 Claude API 发送请求,请构建某个 Params 类的实例并将其传递给相应的客户端方法。收到响应后,它会被反序列化为 Java 类的实例。

例如,client.messages().create(...) 应该使用 MessageCreateParams 的实例调用,并返回 Message 的实例。

未文档化的参数

要设置未文档化的参数,请在任何 Params 类上调用 putAdditionalHeaderputAdditionalQueryParamputAdditionalBodyProperty 方法:

import com.anthropic.core.JsonValue;
import com.anthropic.models.messages.MessageCreateParams;

MessageCreateParams params = MessageCreateParams.builder()
  .putAdditionalHeader("Secret-Header", "42")
  .putAdditionalQueryParam("secret_query_param", "42")
  .putAdditionalBodyProperty("secretProperty", JsonValue.from("42"))
  .build();

这些可以在稍后使用 _additionalHeaders()_additionalQueryParams()_additionalBodyProperties() 方法在构建的对象上访问。

Warning

传递给这些方法的值会覆盖传递给早期方法的值。出于安全原因,确保这些方法仅用于受信任的输入数据。

要设置嵌套头、查询参数或主体类上的未文档化参数:

import com.anthropic.core.JsonValue;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Metadata;

MessageCreateParams params = MessageCreateParams.builder()
  .metadata(
    Metadata.builder().putAdditionalProperty("secretProperty", JsonValue.from("42")).build()
  )
  .build();

这些属性可以在稍后使用 _additionalProperties() 方法在嵌套构建的对象上访问。

要将已文档化的参数或属性设置为未文档化或尚不支持的值,请向其设置器传递 JsonValue 对象:

import com.anthropic.core.JsonValue;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;

MessageCreateParams params = MessageCreateParams.builder()
  .maxTokens(JsonValue.from(3.14))
  .addUserMessage("Hello, Claude")
  .model(Model.CLAUDE_OPUS_4_7)
  .build();

JsonValue 创建

创建 JsonValue 最直接的方式是使用其 from(...) 方法:

import com.anthropic.core.JsonValue;

// 创建原始 JSON 值
JsonValue nullValue = JsonValue.from(null);

JsonValue booleanValue = JsonValue.from(true);

JsonValue numberValue = JsonValue.from(42);

JsonValue stringValue = JsonValue.from("Hello World!");

// 创建等同于 `["Hello", "World"]` 的 JSON 数组值
JsonValue arrayValue = JsonValue.from(List.of("Hello", "World"));

// 创建等同于 `{ "a": 1, "b": 2 }` 的 JSON 对象值
JsonValue objectValue = JsonValue.from(Map.of("a", 1, "b", 2));

// 创建任意嵌套的 JSON,等同于:
// { "a": [1, 2], "b": [3, 4] }
JsonValue complexValue = JsonValue.from(Map.of("a", List.of(1, 2), "b", List.of(3, 4)));

强制省略必需参数

通常,Builder 类的 build 方法会在任何必需参数或属性未设置时抛出 IllegalStateException。要强制省略必需参数或属性,请传递 JsonMissing

import com.anthropic.core.JsonMissing;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;

MessageCreateParams params = MessageCreateParams.builder()
  .addUserMessage("Hello, world")
  .model(Model.CLAUDE_OPUS_4_7)
  .maxTokens(JsonMissing.of())
  .build();

响应属性

要访问未文档化的响应属性,请调用 _additionalProperties() 方法:

import com.anthropic.core.JsonValue;

Map<String, JsonValue> additionalProperties = client
  .messages()
  .create(params)
  ._additionalProperties();

JsonValue secretPropertyValue = additionalProperties.get("secretProperty");

String result = secretPropertyValue.accept(new JsonValue.Visitor<>() {
    @Override
    public String visitNull() {
        return "It's null!";
    }

    @Override
    public String visitBoolean(boolean value) {
        return "It's a boolean!";
    }

    @Override
    public String visitNumber(Number value) {
        return "It's a number!";
    }

    // 其他方法包括 `visitMissing`、`visitString`、`visitArray` 和 `visitObject`
    // 每个未实现方法的默认实现委托给 `visitDefault`,
    // 默认抛出异常,但也可以被覆盖
});

要访问属性的原始 JSON 值,请调用其 _ 前缀方法:

import com.anthropic.core.JsonField;
import com.anthropic.models.messages.StopReason;

JsonField<StopReason> stopReason = client.messages().create(params)._stopReason();

if (stopReason.isMissing()) {
  // 属性在 JSON 响应中不存在
} else if (stopReason.isNull()) {
  // 属性被设置为字面量 null
} else {
  // 检查值是否作为字符串提供
  // 其他方法包括 `asNumber()`、`asBoolean()` 等。
  Optional<String> jsonString = stopReason.asString();

  // 尝试反序列化为自定义类型
  MyClass myObject = stopReason.asUnknown().orElseThrow().convert(MyClass.class);
}

响应验证

默认情况下,当 API 返回与预期类型不匹配的响应时,SDK 不会抛出异常。只有在你直接访问属性时才会抛出 AnthropicInvalidDataException

要预先检查响应是否完全类型正确,请调用 validate()

import com.anthropic.models.messages.Message;

Message message = client.messages().create(params).validate();

或按请求配置:

import com.anthropic.models.messages.Message;

Message message = client
  .messages()
  .create(params, RequestOptions.builder().responseValidation(true).build());

或在客户端级别为所有方法调用配置默认值:

import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

AnthropicClient client = AnthropicOkHttpClient.builder()
  .fromEnv()
  .responseValidation(true)
  .build();

HTTP 客户端自定义

代理配置

import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import java.net.Proxy;

AnthropicClient client = AnthropicOkHttpClient.builder()
  .fromEnv()
  .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("https://example.com", 8080)))
  .build();

HTTPS / SSL 配置

Note

大多数应用程序不应调用这些方法,而应使用系统默认值。默认值包含特殊优化,如果修改了实现可能会丢失。

import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;

AnthropicClient client = AnthropicOkHttpClient.builder()
  .fromEnv()
  .sslSocketFactory(yourSSLSocketFactory)
  .trustManager(yourTrustManager)
  .hostnameVerifier(yourHostnameVerifier)
  .build();

自定义 HTTP 客户端

SDK 由三个制品组成:

  • anthropic-java-core - 包含核心 SDK 逻辑,不依赖 OkHttp。暴露 AnthropicClientAnthropicClientAsync 及其实现类,它们都可以与任何 HTTP 客户端一起工作。
  • anthropic-java-client-okhttp - 依赖 OkHttp。暴露 AnthropicOkHttpClientAnthropicOkHttpClientAsync
  • anthropic-java - 依赖并暴露 anthropic-java-coreanthropic-java-client-okhttp 的 API。没有自己的逻辑。

此结构允许替换 SDK 的默认 HTTP 客户端而不引入不必要的依赖。

自定义 OkHttpClient

Tip

在替换默认客户端之前,请先尝试可用的网络选项

要使用自定义的 OkHttpClient

  1. 将你的 anthropic-java 依赖替换为 anthropic-java-core
  2. anthropic-java-client-okhttpOkHttpClient 类复制到你的代码中并进行自定义。
  3. 使用你的自定义客户端构建 AnthropicClientImplAnthropicClientAsyncImpl

完全自定义 HTTP 客户端

要使用完全自定义的 HTTP 客户端:

  1. 将你的 anthropic-java 依赖替换为 anthropic-java-core
  2. 编写一个实现 HttpClient 接口的类。
  3. 使用你的新客户端类构建 AnthropicClientImplAnthropicClientAsyncImpl

平台集成

Note

有关带有代码示例的详细平台设置指南,请参阅:

Java SDK 通过单独的依赖支持以下平台,这些依赖提供平台特定的 Backend 实现:

  • Bedrock: com.anthropic:anthropic-java-bedrock。使用 BedrockMantleBackend.fromEnv()BedrockMantleBackend.builder() 访问 Messages-API Bedrock 端点,或使用 BedrockBackend.fromEnv() / BedrockBackend.builder()bedrock-runtime 路径)。
  • Vertex AI: com.anthropic:anthropic-java-vertex。使用 VertexBackend.fromEnv()VertexBackend.builder()
  • Foundry: com.anthropic:anthropic-java-foundry。使用 FoundryBackend.fromEnv()FoundryBackend.builder()
  • Claude Platform on AWS: com.anthropic:anthropic-java-aws。使用 AwsBackend.fromEnv()(读取 ANTHROPIC_AWS_WORKSPACE_ID 和 AWS 默认区域/凭据链)或 AwsBackend.builder()。目前处于测试阶段。

新项目请使用 BedrockMantleBackendBedrockBackend 保留给使用 Bedrock InvokeModel API 的现有应用程序。

每个 Backend 实现通过 AnthropicOkHttpClient.builder() 上的 .backend() 传递给客户端。每个云后端将其各自的云平台 SDK 类作为传递依赖引入。

高级用法

原始响应访问

要访问 HTTP 头、状态码和原始响应体,请在任何 HTTP 方法调用前加上 withRawResponse()

import com.anthropic.core.http.Headers;
import com.anthropic.core.http.HttpResponseFor;
import com.anthropic.models.messages.Message;
import com.anthropic.models.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;

MessageCreateParams params = MessageCreateParams.builder()
  .maxTokens(1024L)
  .addUserMessage("Hello, Claude")
  .model(Model.CLAUDE_OPUS_4_7)
  .build();

HttpResponseFor<Message> message = client.messages().withRawResponse().create(params);

int statusCode = message.statusCode();

Headers headers = message.headers();

如果需要,你仍然可以将响应反序列化为 Java 类的实例:

import com.anthropic.models.messages.Message;

Message parsedMessage = message.parse();

日志记录

SDK 使用标准的 OkHttp 日志拦截器。

通过将 ANTHROPIC_LOG 环境变量设置为 info 来启用日志记录:

export ANTHROPIC_LOG=info

或设置为 debug 以获取更详细的日志:

export ANTHROPIC_LOG=debug

Jackson 兼容性

SDK 依赖 Jackson 进行 JSON 序列化/反序列化。它与版本 2.13.4 或更高版本兼容,但默认依赖版本 2.18.2。

如果 SDK 在运行时检测到不兼容的 Jackson 版本(例如如果默认版本在你的 Maven 或 Gradle 配置中被覆盖),则会抛出异常。

如果 SDK 抛出了异常,但你确定版本是兼容的,请使用 AnthropicOkHttpClientAnthropicOkHttpClientAsync 上的 checkJacksonVersionCompatibility 禁用版本检查。

Warning

无法保证在禁用 Jackson 版本检查时 SDK 能正常工作。

旧版 Jackson 中也存在可能影响 SDK 的 bug。SDK 不会解决所有 Jackson bug,期望用户升级 Jackson 来修复这些问题。

ProGuard/R8 配置

虽然 SDK 使用了反射,但它仍然可以与 ProGuard 和 R8 一起使用,因为 anthropic-java-core 发布时附带了包含 keep 规则的配置文件。

ProGuard 和 R8 应该会自动检测并使用发布的规则,但你也可以在必要时手动复制 keep 规则。

未文档化的 API 功能

SDK 针对已文档化 API 的便捷使用进行了类型化。但是,它也支持使用 API 的未文档化或尚不支持的部分。

未文档化的请求参数

要设置未文档化的请求参数,请使用未文档化参数中描述的 putAdditionalHeaderputAdditionalQueryParamputAdditionalBodyProperty 方法。

未文档化的响应属性

要访问未文档化的响应属性,请使用响应属性中描述的 _additionalProperties() 方法。

测试功能

测试功能在正式发布前可用,以获取早期反馈和测试新功能。你可以在构建 Claude 概述中查看 Claude 所有功能和工具的可用性。

你可以通过客户端的 beta() 方法访问大多数测试 API 功能。要启用特定的测试功能,请在构建消息参数时使用 .addBeta() 添加适当的测试头

例如,要使用 Files API

import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.beta.AnthropicBeta;
import com.anthropic.models.beta.messages.BetaContentBlockParam;
import com.anthropic.models.beta.messages.BetaMessage;
import com.anthropic.models.beta.messages.BetaRequestDocumentBlock;
import com.anthropic.models.beta.messages.BetaTextBlockParam;
import com.anthropic.models.beta.messages.MessageCreateParams;
import com.anthropic.models.messages.Model;

void main() {
    AnthropicClient client = AnthropicOkHttpClient.fromEnv();

    BetaMessage message = client.beta().messages().create(
        MessageCreateParams.builder()
            .model(Model.CLAUDE_OPUS_4_7)
            .maxTokens(1024L)
            .addBeta(AnthropicBeta.FILES_API_2025_04_14)
            .addUserMessageOfBetaContentBlockParams(List.of(
                BetaContentBlockParam.ofText(
                    BetaTextBlockParam.builder()
                        .text("Please summarize this document for me.")
                        .build()),
                BetaContentBlockParam.ofDocument(
                    BetaRequestDocumentBlock.builder()
                        .fileSource("file_abc123")
                        .build())))
            .build());
}

常见问题

为什么 SDK 不使用普通枚举类?

Java enum 类不容易向前兼容。在 SDK 中使用它们如果 API 更新为响应新的枚举值,可能会导致运行时异常。

为什么字段使用 JsonField<T> 而不是普通的 T?

使用 JsonField<T> 可以实现几个功能:

  • 允许使用未文档化的 API 功能
  • 延迟验证 API 响应是否符合预期形状
  • 表示不存在的值与显式 null 值

为什么 SDK 不使用数据类?

向数据类添加新字段不是向后兼容的,SDK 避免每次向类添加字段时引入破坏性变更。

为什么 SDK 不使用受检异常?

受检异常在 Java 编程语言中被广泛认为是一个错误。事实上,它们因此被 Kotlin 省略。

受检异常:

  • 处理起来很冗长
  • 鼓励在错误的抽象级别进行错误处理,在那里无法对错误做任何事情
  • 由于函数着色问题,传播起来很繁琐
  • 与 lambda 不兼容(同样因为函数着色问题)

语义化版本控制

此包通常遵循 SemVer 约定,但某些不向后兼容的更改可能作为次要版本发布:

  1. 对库内部的更改,这些更改在技术上是公开的,但不打算或不对外部使用进行文档化。
  2. 在实践中预计不会影响绝大多数用户的更改。

附加资源