• Mensajes
  • Agentes gestionados
  • Administración
Search...
⌘K
CLI, SDKs y bibliotecas
Descripción general
CLI ant
Inicio rápidoOpciones de autenticaciónUso de la CLIScripting y automatización
SDKs de cliente
MiddlewarePythonTypeScriptC#GoJavaPHPRuby
Bibliotecas e integraciones
Compatibilidad con el SDK de OpenAI
Log in
Java
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...

Solutions

  • AI agents
  • Code modernization
  • Coding
  • Customer support
  • Education
  • Financial services
  • Government
  • Life sciences

Partners

  • Amazon Bedrock
  • Google Cloud's Vertex AI

Learn

  • Blog
  • Courses
  • Use cases
  • Connectors
  • Customer stories
  • Engineering at Anthropic
  • Events
  • Powered by Claude
  • Service partners
  • Startups program

Company

  • Anthropic
  • Careers
  • Economic Futures
  • Research
  • News
  • Responsible Scaling Policy
  • Security and compliance
  • Transparency

Learn

  • Blog
  • Courses
  • Use cases
  • Connectors
  • Customer stories
  • Engineering at Anthropic
  • Events
  • Powered by Claude
  • Service partners
  • Startups program

Help and security

  • Availability
  • Status
  • Support
  • Discord

Terms and policies

  • Privacy policy
  • Responsible disclosure policy
  • Terms of service: Commercial
  • Terms of service: Consumer
  • Usage policy
CLI, SDKs y bibliotecas/SDKs de cliente

SDK de Java

Instala y configura el SDK de Java de Anthropic con patrones builder y soporte asíncrono

El SDK de Java de Anthropic proporciona acceso conveniente a la API REST de Anthropic desde aplicaciones escritas en Java. Utiliza el patrón "builder" (constructor) para crear solicitudes y admite operaciones tanto síncronas como asíncronas.

Para la documentación de las funcionalidades de la API con ejemplos de código, consulta la referencia de la API. Esta página cubre las funcionalidades y la configuración del SDK específicas de Java.

Instalación

Requisitos

Esta biblioteca requiere Java 8 o posterior.

El SDK es compatible con Java 8 y versiones posteriores. Los ejemplos de código en esta documentación están escritos como archivos fuente compactos de JDK 25, usando un punto de entrada void main() simple e IO.println() para la salida. Las llamadas a la API en sí son idénticas en todos los JDK compatibles; para compilar un ejemplo en una versión anterior, reemplaza IO.println(...) por System.out.println(...) y coloca el cuerpo dentro de public static void main(String[] args) en una clase.

Inicio rápido

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;

// Se configura usando las propiedades del sistema `anthropic.apiKey`, `anthropic.authToken` y `anthropic.baseUrl`
// O se configura usando las variables de entorno `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN` y `ANTHROPIC_BASE_URL`
AnthropicClient client = AnthropicOkHttpClient.fromEnv();

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

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

Configuración del cliente

Configuración de la clave de API

Configura el cliente usando propiedades del sistema o variables de entorno:

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

// Se configura usando las propiedades del sistema `anthropic.apiKey`, `anthropic.authToken` y `anthropic.baseUrl`
// O se configura usando las variables de entorno `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN` y `ANTHROPIC_BASE_URL`
AnthropicClient client = AnthropicOkHttpClient.fromEnv();

O configúralo manualmente:

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

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

O usa una combinación de ambos enfoques:

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

AnthropicClient client = AnthropicOkHttpClient.builder()
  // Se configura usando propiedades del sistema o variables de entorno
  .fromEnv()
  .apiKey("my-anthropic-api-key")
  .build();

Para conocer las opciones de autenticación, incluida Workload Identity Federation, consulta Autenticación.

Opciones de configuración

SetterPropiedad del sistemaVariable de entornoRequeridoValor predeterminado
apiKeyanthropic.apiKeyANTHROPIC_API_KEYfalse-
authTokenanthropic.authTokenANTHROPIC_AUTH_TOKENfalse-
baseUrlanthropic.baseUrlANTHROPIC_BASE_URLtrue"https://api.anthropic.com"

Las propiedades del sistema tienen prioridad sobre las variables de entorno.

No crees más de un cliente en la misma aplicación. Cada cliente tiene un pool de conexiones y pools de hilos, que son más eficientes cuando se comparten entre solicitudes.

Modificar la configuración

Para usar temporalmente una configuración de cliente modificada mientras reutilizas los mismos pools de conexiones e hilos, llama a withOptions() en cualquier cliente o servicio:

import com.anthropic.client.AnthropicClient;

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

El método withOptions() no afecta al cliente o servicio original.

Uso asíncrono

El cliente predeterminado es síncrono. Para cambiar a ejecución asíncrona, llama al método 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_8)
  .build();

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

O crea un cliente asíncrono desde el principio:

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_8)
  .build();

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

El cliente asíncrono admite las mismas opciones que el síncrono, excepto que la mayoría de los métodos devuelven CompletableFutures.

Streaming

El SDK define métodos que devuelven flujos de "chunks" (fragmentos) de respuesta, donde cada fragmento puede procesarse individualmente tan pronto como llega, en lugar de esperar la respuesta completa.

Streaming síncrono

Estos métodos de streaming devuelven StreamResponse para clientes síncronos:

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!");
}

Streaming asíncrono

Para clientes asíncronos, el método devuelve AsyncStreamResponse:

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

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

// Si necesitas manejar errores o la finalización del stream
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!");
        }
    }
});

// O usa 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!");
        }
    });

El streaming asíncrono usa un Executor dedicado de pool de hilos en caché por cliente para hacer streaming sin bloquear el hilo actual. Para usar un Executor diferente:

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

O configura el cliente globalmente usando el método streamHandlerExecutor:

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

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

Streaming con acumulador de mensajes

Un MessageAccumulator puede registrar el flujo de eventos en la respuesta a medida que se procesan y acumular un objeto Message similar al que habría devuelto la API sin streaming.

Para una respuesta síncrona, agrega una llamada a Stream.peek() en el pipeline del flujo para acumular cada evento:

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();

Para una respuesta asíncrona, agrega el MessageAccumulator a la llamada 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();

También está disponible un BetaMessageAccumulator para la acumulación de un objeto BetaMessage. Se usa de la misma manera que el MessageAccumulator.

Salidas estructuradas

Para la documentación completa de salidas estructuradas, incluidos ejemplos en Java, consulta Salidas estructuradas.

Uso de herramientas

El uso de herramientas con Claude te permite integrar herramientas y funciones externas directamente en las respuestas del modelo de IA. En lugar de producir texto plano, el modelo puede generar instrucciones (con parámetros) para llamar a una herramienta o función cuando sea apropiado. Tú defines esquemas JSON para las herramientas, y el modelo usa los esquemas para determinar cuándo y cómo usar estas herramientas.

La funcionalidad de uso de herramientas admite un modo "strict" (estricto) que garantiza que la salida JSON del modelo de IA se ajustará al esquema JSON que proporciones en los parámetros de entrada.

El SDK puede derivar una herramienta y sus parámetros automáticamente a partir de la estructura de una clase Java arbitraria: el nombre de la clase (convertido a snake case) proporciona el nombre de la herramienta, y los campos de la clase definen los parámetros de la herramienta.

Declara tus clases de herramientas como clases de nivel superior o clases anidadas static. Este requisito proviene de la biblioteca Jackson Databind (com.fasterxml.jackson.databind), que el SDK usa para deserializar las entradas de herramientas en instancias de tus clases y no puede instanciar clases internas no estáticas.

Definir herramientas con anotaciones

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;
  }
}

Llamar a herramientas

Cuando tus clases de herramientas estén definidas, agrégalas a los parámetros del mensaje usando MessageCreateParams.Builder.addTool(Class<T>) y luego llámalas si así se solicita en la respuesta del modelo de IA. BetaToolUseBlock.input(Class<T>) puede usarse para analizar los parámetros de una herramienta en formato JSON y convertirlos en una instancia de tu clase que define la herramienta.

Después de llamar a la herramienta, usa BetaToolResultBlockParam.Builder.contentAsJson(Object) para pasar el resultado de la herramienta de vuelta al modelo de IA:

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_8)
        .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
              // Agrega un mensaje que indique que se solicitó el uso de herramientas.
              .addAssistantMessageOfBetaContentBlockParams(
                      List.of(BetaContentBlockParam.ofToolUse(BetaToolUseBlockParam.builder()
                              .name(toolUseBlock.name())
                              .id(toolUseBlock.id())
                              .input(toolUseBlock._input())
                              .build())))
              // Agrega un mensaje con el resultado del uso de herramientas solicitado.
              .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");
}

Conversión de nombres de herramientas

Los nombres de las herramientas se derivan de los nombres de las clases de herramientas en camel case (p. ej., GetWeather) y se convierten a snake case (p. ej., get_weather). Los límites de palabra comienzan donde el carácter actual no es el primer carácter, está en mayúscula, y el carácter anterior está en minúscula o el carácter siguiente está en minúscula. Por ejemplo, MyJSONParser se convierte en my_json_parser y ParseJSON se convierte en parse_json. Esta conversión puede anularse usando la anotación @JsonTypeName.

Validación local del esquema JSON de herramientas

Puedes realizar una validación local para verificar que el esquema JSON derivado de tu clase de herramienta respete las restricciones de Anthropic. La validación local está habilitada de forma predeterminada, pero puede deshabilitarse:

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

Anotar clases de herramientas

Puedes usar anotaciones para agregar más información sobre las herramientas a los esquemas JSON:

  • @JsonClassDescription - Agrega una descripción a una clase de herramienta que detalla cuándo y cómo usar esa herramienta.
  • @JsonTypeName - Establece el nombre de la herramienta en algo distinto al nombre simple de la clase convertido a snake case.
  • @JsonPropertyDescription - Agrega una descripción detallada a un parámetro de herramienta.
  • @JsonIgnore - Excluye un campo public o método getter del esquema JSON generado para los parámetros de una herramienta.
  • @JsonProperty - Incluye un campo no public o método getter en el esquema JSON generado para los parámetros de una herramienta.

Lotes de mensajes

El SDK proporciona soporte para el procesamiento por lotes bajo el espacio de nombres client.messages().batches(). Consulta Paginación para saber cómo listar y paginar a través de los lotes.

Carga de archivos

El SDK define métodos que aceptan archivos a través de la clase 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);

O desde un 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);

O desde bytes en memoria:

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);

Respuestas binarias

El SDK define métodos que devuelven respuestas binarias para respuestas de la API que no necesariamente se analizan como JSON:

import com.anthropic.core.http.HttpResponse;

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

Para guardar el contenido de la respuesta en un archivo:

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);
}

O transferir el contenido de la respuesta a cualquier 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);
}

Manejo de errores

El SDK lanza tipos de excepciones no comprobadas personalizadas:

  • AnthropicServiceException - Clase base para errores HTTP.
  • AnthropicIoException - Errores de red de E/S.
  • AnthropicRetryableException - Error genérico que indica un fallo que podría reintentarse.
  • AnthropicInvalidDataException - Fallo al interpretar datos analizados correctamente (p. ej., al acceder a una propiedad que se supone que es requerida, pero la API la omitió inesperadamente).
  • AnthropicException - Clase base para todas las excepciones.

Mapeo de códigos de estado

EstadoExcepción
400BadRequestException
401UnauthorizedException
403PermissionDeniedException
404NotFoundException
422UnprocessableEntityException
429RateLimitException
5xxInternalServerException
otrosUnexpectedStatusCodeException

SseException se lanza para errores encontrados durante el streaming SSE después de una respuesta HTTP inicial exitosa.

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());
}

IDs de solicitud

Al usar respuestas sin procesar, puedes acceder al encabezado de respuesta request-id usando el método requestId():

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();

Esto puede usarse para registrar rápidamente las solicitudes fallidas y reportarlas a Anthropic. Para obtener más información sobre la depuración de solicitudes, consulta ID de solicitud.

Reintentos

El SDK reintenta automáticamente 2 veces de forma predeterminada, con un breve retroceso exponencial entre solicitudes.

Solo se reintentan los siguientes tipos de errores:

  • Errores de conexión (por ejemplo, debido a un problema de conectividad de red)
  • 408 Request Timeout
  • 409 Conflict
  • 429 Rate Limit
  • 5xx Internal

La API también puede indicar explícitamente al SDK que reintente o no una solicitud.

Para establecer un número personalizado de reintentos, configura el cliente usando el método maxRetries:

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

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

Tiempos de espera

Las solicitudes agotan el tiempo de espera después de 10 minutos de forma predeterminada.

Sin embargo, para los métodos que aceptan maxTokens, si especificas un valor grande de maxTokens y estás usando streaming, el tiempo de espera predeterminado se calculará dinámicamente usando esta fórmula:

Duration.ofSeconds(
    Math.min(
        60 * 60, // 1 hour max
        Math.max(
            10 * 60, // 10 minute minimum
            60 * 60 * maxTokens / 128_000
        )
    )
)

Esto resulta en un tiempo de espera de hasta 60 minutos, escalado por el parámetro maxTokens, a menos que se anule.

Para solicitudes sin streaming, el tiempo de espera dinámico escala desde un mínimo de 30 segundos hasta un máximo de 10 minutos según maxTokens.

Para establecer un tiempo de espera personalizado por solicitud:

import com.anthropic.models.messages.Message;

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

O configura el valor predeterminado para todas las llamadas a métodos a nivel de cliente:

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

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

Solicitudes largas

Considera usar streaming para solicitudes de larga duración.

Evita establecer un valor grande de maxTokens sin usar streaming. Algunas redes pueden cerrar conexiones inactivas después de cierto período de tiempo, lo que puede hacer que la solicitud falle o agote el tiempo de espera sin recibir una respuesta de Anthropic. El SDK hace ping periódicamente a la API para mantener la conexión activa y reducir el impacto de estas redes.

El SDK lanza un error si se espera que una solicitud sin streaming tarde más de 10 minutos. Usar un método de streaming o anular el tiempo de espera a nivel de cliente o de solicitud deshabilita el error.

Paginación

El SDK proporciona formas convenientes de acceder a resultados paginados, ya sea una página a la vez o elemento por elemento a través de todas las páginas.

Paginación automática

Para iterar a través de todos los resultados en todas las páginas, usa el método autoPager(), que obtiene automáticamente más páginas según sea necesario.

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

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

// Procesar como un Iterable
for (MessageBatch batch : page.autoPager()) {
    IO.println(batch);
}

// Procesar como un Stream
page.autoPager()
    .stream()
    .limit(50)
    .forEach(batch -> IO.println(batch));

Al usar el cliente asíncrono, el método devuelve un 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);
}));

// Si necesitas manejar errores o la finalización del stream
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!");
        }
    }
}));

// O usa 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!");
        }
    }));

Paginación manual

Para acceder a elementos de páginas individuales y solicitar manualmente la siguiente página:

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();
}

Sistema de tipos

Inmutabilidad y builders

Cada clase en el SDK tiene un builder asociado para construirla. Cada clase es inmutable una vez construida. Si la clase tiene un builder asociado, entonces tiene un método toBuilder(), que puede usarse para convertirla de nuevo en un builder y hacer una copia modificada.

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

// Crea una copia modificada usando toBuilder()
MessageCreateParams modified = params.toBuilder().maxTokens(2048L).build();

Debido a que cada clase es inmutable, la modificación del builder nunca afectará a las instancias de clase ya construidas.

Solicitudes y respuestas

Para enviar una solicitud a la API de Claude, construye una instancia de alguna clase Params y pásala al método de cliente correspondiente. Cuando se recibe la respuesta, se deserializa en una instancia de una clase Java.

Por ejemplo, client.messages().create(...) debe llamarse con una instancia de MessageCreateParams, y devolverá una instancia de Message.

Parámetros no documentados

Para establecer parámetros no documentados, llama a los métodos putAdditionalHeader, putAdditionalQueryParam o putAdditionalBodyProperty en cualquier clase Params:

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();

Estos pueden accederse en el objeto construido más tarde usando los métodos _additionalHeaders(), _additionalQueryParams() y _additionalBodyProperties().

Los valores pasados a estos métodos sobrescriben los valores pasados a métodos anteriores. Por razones de seguridad, asegúrate de que estos métodos solo se usen con datos de entrada confiables.

Para establecer parámetros no documentados en encabezados anidados, parámetros de consulta o clases de cuerpo:

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();

Estas propiedades pueden accederse en el objeto anidado construido más tarde usando el método _additionalProperties().

Para establecer un parámetro o propiedad documentado en un valor no documentado o aún no compatible, pasa un objeto JsonValue a su setter:

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_8)
  .build();

Creación de JsonValue

La forma más sencilla de crear un JsonValue es usando su método from(...):

import com.anthropic.core.JsonValue;

// Crea valores JSON primitivos
JsonValue nullValue = JsonValue.from(null);

JsonValue booleanValue = JsonValue.from(true);

JsonValue numberValue = JsonValue.from(42);

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

// Crea un valor de arreglo JSON equivalente a `["Hello", "World"]`
JsonValue arrayValue = JsonValue.from(List.of("Hello", "World"));

// Crea un valor de objeto JSON equivalente a `{ "a": 1, "b": 2 }`
JsonValue objectValue = JsonValue.from(Map.of("a", 1, "b", 2));

// Crea un JSON anidado arbitrariamente equivalente a:
// { "a": [1, 2], "b": [3, 4] }
JsonValue complexValue = JsonValue.from(Map.of("a", List.of(1, 2), "b", List.of(3, 4)));

Omitir forzosamente parámetros requeridos

Normalmente, el método build de una clase Builder lanzará IllegalStateException si algún parámetro o propiedad requerido no está establecido. Para omitir forzosamente un parámetro o propiedad requerido, pasa 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_8)
  .maxTokens(JsonMissing.of())
  .build();

Propiedades de respuesta

Para acceder a propiedades de respuesta no documentadas, llama al método _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!";
    }

    // Otros métodos incluyen `visitMissing`, `visitString`, `visitArray` y `visitObject`
    // La implementación predeterminada de cada método no implementado delega en `visitDefault`,
    // que lanza una excepción por defecto, pero también puede sobrescribirse
});

Para acceder al valor JSON sin procesar de una propiedad, llama a su método con prefijo _:

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

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

if (stopReason.isMissing()) {
  // La propiedad está ausente en la respuesta JSON
} else if (stopReason.isNull()) {
  // La propiedad se estableció como null literal
} else {
  // Verifica si el valor se proporcionó como una cadena
  // Otros métodos incluyen `asNumber()`, `asBoolean()`, etc.
  Optional<String> jsonString = stopReason.asString();

  // Intenta deserializar en un tipo personalizado
  MyClass myObject = stopReason.asUnknown().orElseThrow().convert(MyClass.class);
}

Validación de respuestas

De forma predeterminada, el SDK no lanza una excepción cuando la API devuelve una respuesta que no coincide con el tipo esperado. Lanza AnthropicInvalidDataException solo si accedes directamente a la propiedad.

Para verificar que la respuesta esté completamente bien tipada de antemano, llama a validate():

import com.anthropic.models.messages.Message;

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

O configúralo por solicitud:

import com.anthropic.models.messages.Message;

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

O configura el valor predeterminado para todas las llamadas a métodos a nivel de cliente:

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

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

Personalización del cliente HTTP

Configuración de proxy

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();

Configuración de HTTPS / SSL

La mayoría de las aplicaciones no deberían llamar a estos métodos y, en su lugar, deberían usar los valores predeterminados del sistema. Los valores predeterminados incluyen optimizaciones especiales que pueden perderse si se modifican las implementaciones.

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

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

Cliente HTTP personalizado

El SDK consta de tres artefactos:

  • anthropic-java-core - Contiene la lógica central del SDK, no depende de OkHttp. Expone AnthropicClient, AnthropicClientAsync y sus clases de implementación, todas las cuales pueden funcionar con cualquier cliente HTTP.
  • anthropic-java-client-okhttp - Depende de OkHttp. Expone AnthropicOkHttpClient y AnthropicOkHttpClientAsync.
  • anthropic-java - Depende de y expone las APIs tanto de anthropic-java-core como de anthropic-java-client-okhttp. No tiene lógica propia.

Esta estructura permite reemplazar el cliente HTTP predeterminado del SDK sin incorporar dependencias innecesarias.

OkHttpClient personalizado

Prueba las opciones de red disponibles antes de reemplazar el cliente predeterminado.

Para usar un OkHttpClient personalizado:

  1. Reemplaza tu dependencia anthropic-java por anthropic-java-core.
  2. Copia la clase OkHttpClient de anthropic-java-client-okhttp en tu código y personalízala.
  3. Construye AnthropicClientImpl o AnthropicClientAsyncImpl usando tu cliente personalizado.

Cliente HTTP completamente personalizado

Para usar un cliente HTTP completamente personalizado:

  1. Reemplaza tu dependencia anthropic-java por anthropic-java-core.
  2. Escribe una clase que implemente la interfaz HttpClient.
  3. Construye AnthropicClientImpl o AnthropicClientAsyncImpl usando tu nueva clase de cliente.

Integraciones de plataforma

Para guías detalladas de configuración de plataforma con ejemplos de código, consulta:

  • Amazon Bedrock
  • Amazon Bedrock (legacy)
  • Vertex AI
  • Microsoft Foundry
  • Claude Platform en AWS

El SDK de Java admite las siguientes plataformas a través de dependencias separadas que proporcionan implementaciones de Backend específicas de cada plataforma:

  • Bedrock: com.anthropic:anthropic-java-bedrock: Usa BedrockMantleBackend.fromEnv() o BedrockMantleBackend.builder() para el endpoint de Bedrock de la API de Messages, o BedrockBackend.fromEnv() / BedrockBackend.builder() (ruta bedrock-runtime).
  • Vertex AI: com.anthropic:anthropic-java-vertex: Usa VertexBackend.fromEnv() o VertexBackend.builder().
  • Foundry: com.anthropic:anthropic-java-foundry: Usa FoundryBackend.fromEnv() o FoundryBackend.builder().
  • Claude Platform en AWS: com.anthropic:anthropic-java-aws: Usa AwsBackend.fromEnv() (lee ANTHROPIC_AWS_WORKSPACE_ID y la cadena predeterminada de región/credenciales de AWS) o AwsBackend.builder(). Disponible en beta.

Usa BedrockMantleBackend para proyectos nuevos; BedrockBackend se mantiene para aplicaciones existentes que usan la API InvokeModel de Bedrock.

Cada implementación de Backend se pasa al cliente con .backend() en AnthropicOkHttpClient.builder(). Cada backend de nube incorpora sus respectivas clases del SDK de la plataforma en la nube como dependencias transitivas.

Uso avanzado

Acceso a la respuesta sin procesar

Para acceder a los encabezados HTTP, códigos de estado y el cuerpo de la respuesta sin procesar, antepón withRawResponse() a cualquier llamada a método HTTP:

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_8)
  .build();

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

int statusCode = message.statusCode();

Headers headers = message.headers();

Aún puedes deserializar la respuesta en una instancia de una clase Java si es necesario:

import com.anthropic.models.messages.Message;

Message parsedMessage = message.parse();

Registro de logs

El SDK usa el interceptor de logging estándar de OkHttp.

Habilita el registro de logs estableciendo la variable de entorno ANTHROPIC_LOG en info:

export ANTHROPIC_LOG=info

O en debug para un registro más detallado:

export ANTHROPIC_LOG=debug

Funcionalidad de API no documentada

El SDK está tipado para un uso conveniente de la API documentada. Sin embargo, también admite trabajar con partes no documentadas o aún no compatibles de la API.

Parámetros de solicitud no documentados

Para establecer parámetros de solicitud no documentados, usa los métodos putAdditionalHeader, putAdditionalQueryParam o putAdditionalBodyProperty como se describe en Parámetros no documentados.

Propiedades de respuesta no documentadas

Para acceder a propiedades de respuesta no documentadas, usa el método _additionalProperties() como se describe en Propiedades de respuesta.

Valores de enum nuevos o no publicados

Las clases similares a enum en el SDK, como Model y AnthropicBeta, no son tipos enum cerrados de Java. Cada una proporciona un método de fábrica of(String) que acepta cualquier cadena, por lo que puedes usar valores que aún no se han agregado al SDK, como un modelo o encabezado beta publicado después de tu versión del SDK:

import com.anthropic.models.beta.AnthropicBeta;
import com.anthropic.models.messages.Model;

Model model = Model.of("some-new-model");
AnthropicBeta beta = AnthropicBeta.of("some-new-beta-2026-01-01");

Los métodos de builder que toman estos tipos a menudo también proporcionan una sobrecarga de String que llama a of(...) por ti:

import com.anthropic.models.messages.MessageCreateParams;

MessageCreateParams params = MessageCreateParams.builder()
  .model("some-new-model") // same as .model(Model.of("some-new-model"))
  .maxTokens(1024L)
  .addUserMessage("Hello, Claude")
  .build();

Prefiere las constantes bien tipadas (por ejemplo, Model.CLAUDE_OPUS_4_7) para obtener autocompletado y advertencias de obsolescencia. Las sobrecargas de String y of(...) son principalmente para establecer el campo en un valor no documentado o aún no compatible mientras esperas una versión del SDK que lo incluya.

Funcionalidades beta

Las funcionalidades beta están disponibles antes del lanzamiento general para obtener retroalimentación temprana y probar nuevas funcionalidades. Puedes verificar la disponibilidad de todas las capacidades y herramientas de Claude en la descripción general de construir con Claude.

Puedes acceder a la mayoría de las funcionalidades beta de la API a través del método beta() en el cliente. Para habilitar una funcionalidad beta en particular, agrega el encabezado beta apropiado con .addBeta() al construir los parámetros del mensaje.

Por ejemplo, para usar la API de Files:

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;
// ...
void main() {
    AnthropicClient client = AnthropicOkHttpClient.fromEnv();

    BetaMessage message = client.beta().messages().create(
        MessageCreateParams.builder()
            .model(Model.CLAUDE_OPUS_4_8)
            .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());
}

Preguntas frecuentes

Versionado semántico

Este paquete generalmente sigue las convenciones de SemVer, aunque ciertos cambios incompatibles hacia atrás pueden publicarse como versiones menores:

  1. Cambios en los componentes internos de la biblioteca que son técnicamente públicos pero no están destinados ni documentados para uso externo.
  2. Cambios que no se espera que afecten a la gran mayoría de los usuarios en la práctica.

Recursos adicionales

  • Repositorio de GitHub
  • Javadocs
  • Referencia de la API
  • Streaming de mensajes
  • Uso de herramientas con Claude

Was this page helpful?

  • Instalación
  • Requisitos
  • Inicio rápido
  • Configuración del cliente
  • Configuración de la clave de API
  • Opciones de configuración
  • Modificar la configuración
  • Uso asíncrono
  • Streaming
  • Streaming síncrono
  • Streaming asíncrono
  • Streaming con acumulador de mensajes
  • Salidas estructuradas
  • Uso de herramientas
  • Definir herramientas con anotaciones
  • Llamar a herramientas
  • Conversión de nombres de herramientas
  • Validación local del esquema JSON de herramientas
  • Anotar clases de herramientas
  • Lotes de mensajes
  • Carga de archivos
  • Respuestas binarias
  • Manejo de errores
  • Mapeo de códigos de estado
  • IDs de solicitud
  • Reintentos
  • Tiempos de espera
  • Solicitudes largas
  • Paginación
  • Paginación automática
  • Paginación manual
  • Sistema de tipos
  • Inmutabilidad y builders
  • Solicitudes y respuestas
  • Parámetros no documentados
  • Creación de JsonValue
  • Omitir forzosamente parámetros requeridos
  • Propiedades de respuesta
  • Validación de respuestas
  • Personalización del cliente HTTP
  • Configuración de proxy
  • Configuración de HTTPS / SSL
  • Cliente HTTP personalizado
  • Integraciones de plataforma
  • Uso avanzado
  • Acceso a la respuesta sin procesar
  • Registro de logs
  • Funcionalidad de API no documentada
  • Funcionalidades beta
  • Preguntas frecuentes
  • Versionado semántico
  • Recursos adicionales