1. Visión general
Los Modelos de Lenguaje Grande (LLM) han avanzado hasta convertirse en sistemas de agentes capaces de ejecutar tareas más complejas que simplemente generar texto. Una de las áreas emergentes son las habilidades de agente introducidas por Anthropic.
Las habilidades de agente permiten que el LLM produzca archivos de documentos sin una API adicional, como Apache POI. Invocan las capacidades incorporadas que generan documentos en el servidor del proveedor y los devuelven mediante identificadores de archivo. Spring AI admite habilidades con los modelos de Anthropic, lo que facilita la integración con aplicaciones Java.
En este tutorial, exploraremos lo que Anthropic ofrece en términos de habilidades de agente y cómo las integramos con Spring AI.
2. Habilidades preconstruidas de Anthropic
Anthropic ofrece un conjunto de habilidades de agente preconstruidas que pueden generar un documento y llenarlo con contenido. Así, el modelo puede devolver un archivo de documento en lugar de texto plano.
Por supuesto, hay algunos formatos de documento que Anthropic admite actualmente:
- DOCX: documentos Word con formato
- PDF: informes PDF formateados
- PPTX: diapositivas de PowerPoint
- XLSX: hojas de cálculo de Excel
En Spring AI, podemos usar estas habilidades preconstruidas de Anthropic aplicándolas a través de las opciones de chat.
3. Configuración
Para comenzar con las habilidades de Anthropic, agreguemos la dependencia requerida (dependencia) a pom.xml:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-anthropic</artifactId>
</dependency>
A continuación, configuramos la clave de API de Anthropic en application.yml para usar los modelos de Anthropic:
spring:
ai:
anthropic:
api-key: "${ANTHROPIC_API_KEY}"
De esta forma, no necesitamos proporcionar la clave por separado.
4. Implementación de ejemplo
Para demostrar las características, construyamos una aplicación web simple que genere un informe de ventas. Además, la implementación nos permite generar un formato de documento específico soportado por las habilidades preconstruidas a través del mensaje de solicitud.
4.1. Servicio de datos
Para comenzar, necesitamos proporcionar un modelo que represente los datos enviados al modelo de chat:
public record MonthlySale(String product, int year, Month month, BigDecimal amount) {
}
Para fines de demostración, creamos una capa de servicio de datos simple que devuelve datos codificados de forma estática. En este caso, el servicio devuelve una List de MonthlySale que contiene 12 meses de ventas para el producto A y el producto B:
@Service
public class MonthlySalesService {
public List<MonthlySale> getMonthlySalesForYear(int year) {
return List.of(
// Product A monthly sales
new MonthlySale("Product A", year, Month.JANUARY, new BigDecimal("1200")),
new MonthlySale("Product A", year, Month.FEBRUARY, new BigDecimal("1325")),
...
// Product B monthly sales
...
new MonthlySale("Product B", year, Month.NOVEMBER, new BigDecimal("1330")),
new MonthlySale("Product B", year, Month.DECEMBER, new BigDecimal("1395"))
);
}
}
En la práctica, podríamos reemplazarlo con una herramienta MCP para recuperar los datos de ventas de la base de datos e integrarlos con el modelo de chat.
4.2. Controlador
A continuación, exponemos un punto final HTTP para aceptar un mensaje de solicitud que defina el contenido y el formato del documento.
Dado que el formato del documento no se conoce de antemano, devolvemos el tipo MIME, que se determina a partir del modelo de chat, al cliente:
@RestController
@RequestMapping("/agent-skills")
@Validated
public class AgentSkillsController {
private final AgentSkillsService agentSkillsService;
public AgentSkillsController(AgentSkillsService agentSkillsService) {
this.agentSkillsService = agentSkillsService;
}
@GetMapping("/report")
public ResponseEntity<byte[]> genReport(@RequestBody @Valid ReportRequest reportRequest) {
AnthropicDocument document = agentSkillsService.genReport(reportRequest);
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(document.mimeType()))
.header(HttpHeaders.CONTENT_DISPOSITION,
ContentDisposition.attachment()
.filename(document.fileName())
.build()
.toString())
.body(document.content());
}
}
Introducamos un registro de marcador de posición sencillo:
public record ReportRequest(@NotNull String prompt) {
}
Esto contiene el mensaje de solicitud introducido por el usuario, que se pasa al AgentSkillService.
4.3. Servicio de Habilidad de Agente
Ahora, creamos un servicio para generar un documento usando el modelo de chat de Anthropic con las habilidades preconstruidas. Las opciones de chat de Anthropic pueden soportar múltiples habilidades.
En este ejemplo, colocamos todas las habilidades preconstruidas disponibles en el modelo de chat y utilizamos el mensaje del usuario para controlar el formato de documento que deseamos generar. Esto tiene como objetivo demostrar que el modelo de chat puede seleccionar la habilidad adecuada en función del mensaje.
Sin embargo, suele ser mejor habilitar solo las habilidades requeridas para reducir la posibilidad de producir un formato impredecible:
@Service
public class AgentSkillsService {
private final AnthropicChatModel chatModel;
private final AnthropicApi anthropicApi;
private final MonthlySalesService monthlySalesService;
public AgentSkillsService(
AnthropicChatModel chatModel,
AnthropicApi anthropicApi,
MonthlySalesService monthlySalesService) {
this.chatModel = chatModel;
this.anthropicApi = anthropicApi;
this.monthlySalesService = monthlySalesService;
}
public AnthropicDocument genReport(ReportRequest reportRequest) {
ChatResponse response = ChatClient.create(chatModel)
.prompt()
.system( "Given the dataset of monthly sales for our product: "
+ monthlySalesService.getMonthlySalesForYear(2025))
.user(reportRequest.prompt())
.options(AnthropicChatOptions.builder()
.model("claude-sonnet-4-5")
.skill(AnthropicApi.AnthropicSkill.DOCX)
.skill(AnthropicApi.AnthropicSkill.PDF)
.skill(AnthropicApi.AnthropicSkill.PPTX)
.skill(AnthropicApi.AnthropicSkill.XLSX)
maxTokens(4096)
.build())
.call()
.chatResponse();
List fileIds = AnthropicSkillsResponseHelper.extractFileIds(response);
if (fileIds.isEmpty()) {
throw new IllegalStateException("No document was generated by the skill");
}
return downloadReport(fileIds.get(0));
}
public AnthropicDocument downloadReport(String fileId) {
AnthropicApi.FileMetadata metadata = anthropicApi.getFileMetadata(fileId);
byte[] content = anthropicApi.downloadFile(fileId);
return new AnthropicDocument(metadata.filename(), metadata.mimeType(), content);
}
}
Notablemente, configuramos maxTokens en 4096 para controlar la cantidad máxima de contenido que podría generarse en una respuesta. Como regla empírica, un (1) token equivale aproximadamente a cuatro (4) caracteres. En este caso, 4096 debería ser más que suficiente. Sin embargo, podríamos ampliarlo a un tamaño mayor si esperamos un informe extenso.
Una vez que recibimos la respuesta del modelo de chat, podemos usar AnthropicSkillsResponseHelper para extraer el ID del archivo de esa respuesta. Este ID de archivo identifica de forma única el archivo generado almacenado en el servidor de Anthropic.
Revisemos los archivos en la consola de Claude:

Así, utilizamos AnthropicAPI proporcionado por Spring AI para obtener la información del archivo basada en el ID de archivo. Por supuesto, AnthropicApi.FileMetadata contiene detalles sobre el archivo:
- nombre del archivo
- tamaño del archivo
- fecha de creación
- tipo MIME
Mientras que AnthropicDocument es un registro Java simple para almacenar el nombre del archivo, el tipo MIME y el contenido del archivo, los devuelve al cliente a través del controlador:
public record AnthropicDocument(String fileName, String, mimeType, byte[] content) {
}
Así, tenemos la aplicación básica lista para probar.
5. Ejecución de prueba
Todo está configurado, y podemos comenzar a probar. Con ese fin, llamemos al punto final usando Postman para disparar la solicitud.
5.1. Informe PDF
Para comenzar, creamos una solicitud de ejemplo para generar un informe de ventas con un resumen y una tabla en formato PDF:

En este momento, vemos el contenido, que incluye la tabla de ventas mensuales y un resumen en el archivo generado:

Así, toda la información está allí y en un formato estructurado.
5.2. Hoja de cálculo de Excel
Cambiemos el mensaje para generar una hoja de cálculo de Excel en su lugar, con un gráfico de barras en lugar de un resumen:
{
"prompt": "Create a Excel spreadsheet for our product monthly sales. Include a monthly sales table, and a monthly bar chart next to the table."
}
Ahora, el informe refleja el cambio de formato:

Así, vemos la hoja de cálculo con los datos correctos y el formato adecuado.
6. Conclusión
En este artículo, exploramos cómo integrar las habilidades de agente preconstruidas de Anthropic con un modelo de chat para generar diversos documentos utilizando Spring AI.
Además, demostramos cómo usar un mensaje para controlar el formato real del documento de salida. En particular, esto brinda flexibilidad para generar diferentes formatos de documento sin cambiar la lógica de la aplicación.
Como de costumbre, los ejemplos de código completos están disponibles en GitHub.
Newsletter Semanal de Java
Cada viernes recibe lo más nuevo del ecosistema Java: frameworks, herramientas y mejores prácticas.
Sin spam. Cancela cuando quieras.