Sproutice
Todas las entradas

Agentes de IA en Spring Boot con Java — Sprout 1.5.0

AgentesIAJavaSpring bootInyección de dependenciasOpenAIAnthropicSproutRelease

Añade agentes de IA a tu app Spring Boot en Java puro, sin código pegamento

Si haces backends en Java, meter agentes de IA solía implicar un desvío: montar un servicio Python aparte, cablearlo por HTTP y mantener dos runtimes sincronizados. Sprout es un framework de IA para Java que, en cambio, corre dentro de Spring Boot — y Sprout 1.5.0 hace desaparecer la costura entre ambos. Lo mejor: tus controladores, tus @Service y tu application.yml se quedan tal cual están.

En resumen

  • Sprout corre dentro de tu proceso Spring Boot — inyecta un agente en un @RestController y respalda sus @Tool con los @Service de Spring que ya tienes.
  • 1.5.0 permite que los beans de Sprout y de Spring usen las anotaciones DI del otro en ambos sentidos, así que los @Autowired / @Value / @Qualifier con el mismo nombre ya no chocan.
  • Añade sprout-openai o sprout-anthropic y el ejecutor @Model se auto-descubre — sin sprout.scan.base-packages.
  • sprout-monitoring se activa solo, expuesto como bean de Spring.
  • Mismo JVM, misma configuración, mismos tests. Sin servicio Python.

Correr agentes de IA dentro de Spring Boot

Añade la dependencia sprout-spring-boot-starter y los dos contenedores empiezan a hablarse: cada bean de Sprout —agentes, modelos, herramientas, servicios— queda registrado en el ApplicationContext de Spring, y a su vez los componentes de Sprout pueden depender de tus beans de Spring. Así, un agente es un bean más que inyectas con @Autowired:

@RestController
class ChatController {

    private final AgentExecutor supportAgent;   // un @Agent de Sprout, expuesto como bean de Spring

    ChatController(@Qualifier("supportAgentExecutor") AgentExecutor supportAgent) {
        this.supportAgent = supportAgent;
    }

    @PostMapping("/chat")
    String chat(@RequestBody String prompt) {
        return supportAgent.execute("conversacion-1", prompt).response();
    }
}

Ese puente ya existía. 1.5.0 va de las últimas asperezas.

Mezclar anotaciones: Sprout y Spring, en ambos sentidos

Sprout y Spring traen cada uno su @Autowired, su @Value y su @Qualifier. Antes de 1.5.0, usar la "que no tocaba" dentro de una clase gestionada por el otro contenedor hacía que se ignorara en silencio: el clásico pinchazo de "¿por qué este campo es null?". En 1.5.0 los dos juegos se tratan como equivalentes, en ambas direcciones.

Un componente de Sprout funciona cableado con las anotaciones de Spring —o de JSR-330—:

@Service                                                          // estereotipo de Sprout
public class PricingService {

    @org.springframework.beans.factory.annotation.Autowired       // @Autowired de Spring
    private RateRepository rates;

    @org.springframework.beans.factory.annotation.Value("${pricing.currency}")  // @Value de Spring
    private String currency;

    @io.github.ivannavas.sprout.annotation.Value("${pricing.margin:0.15}")      // @Value de Sprout
    private double margin;
}

Y un bean de Spring funciona cableado con el @Autowired / @Value / @Qualifier / @PostConstruct de Sprout (inyección por campo y @PostConstruct; para inyección por constructor en un bean de Spring, usa el @Autowired de Spring):

@Component                                                        // estereotipo de Spring
public class ReportBuilder {

    @io.github.ivannavas.sprout.annotation.Autowired              // @Autowired de Sprout
    private SummaryAgentExecutor agent;                           // un bean @Agent de Sprout

    @io.github.ivannavas.sprout.annotation.Value("${report.title}")
    private String title;

    @io.github.ivannavas.sprout.annotation.PostConstruct
    void init() { /* se ejecuta tras cablear los campos de arriba */ }
}

Y lo importante: esto es una red de seguridad, no un estilo. Existe para que el código mezclado o en migración nunca se rompa en silencio, no para repartir ambos tipos por todas partes. La recomendación es simple: usa las anotaciones de Sprout en componentes de Sprout, y las del contenedor DI correspondiente en sus propios beans. Y nada de esto mete Spring en el núcleo de Sprout: sprout-core reconoce solo sus propias anotaciones; el starter aporta las equivalentes de Spring y JSR-330.

Cero configuración: añade OpenAI o Anthropic

Añadir un proveedor de modelos requería antes una línea extra —decirle a Sprout en qué paquete vivía el ejecutor, con sprout.scan.base-packages—. En 1.5.0 cada módulo aporta su propio paquete al escaneo, así que los ejecutores @Model de OpenAI y Anthropic se descubren en cuanto el jar está en el classpath.

<dependency>
    <groupId>io.github.ivannavas</groupId>
    <artifactId>sprout-spring-boot-starter</artifactId>
    <version>1.5.0</version>
</dependency>
<dependency>
    <groupId>io.github.ivannavas</groupId>
    <artifactId>sprout-openai</artifactId>   <!-- o sprout-anthropic -->
    <version>1.5.0</version>
</dependency>

Sin configurar escaneo. Inyecta el ejecutor en cualquier bean de Spring por nombre:

ChatController(@Qualifier("openai") ModelExecutor openai) { ... }   // un @Model de Sprout, inyectado por Spring

Monitorización, activada por defecto

sprout-monitoring sigue la misma regla: añade el módulo y el seguimiento de uso, tokens y coste se activa solo, expuesto como el bean usageStore de Spring. Declara tu propio @UsageStore y toma el relevo — nada que escanear, nada que configurar.

Una única fuente de verdad para la configuración

El Environment de Spring —application.yml / application.properties, propiedades de sistema, variables de entorno— alimenta la configuración de Sprout. Un @Value("${pricing.currency}") de Sprout lee la misma property que leería un @Value de Spring, desde el mismo sitio. Nada que duplicar.

Preguntas frecuentes

¿Puedo usar agentes de IA en Spring Boot con Java (sin Python)?

Sí. Sprout es un framework de IA para Java que corre dentro de tu proceso Spring Boot. Los agentes, los ejecutores de modelos LLM y las herramientas son beans normales inyectables por Spring, así que no hay servicio Python aparte ni salto de red.

¿Sprout reemplaza la inyección de dependencias de Spring?

No. Sprout mantiene su propio contenedor para sus componentes y los expone a Spring, y puede consumir beans de Spring. Sigues usando Spring igual que hoy; el starter hace de puente entre ambos.

¿Qué anotaciones debo usar, las de Sprout o las de Spring?

Las de Sprout en componentes de Sprout y las de Spring en beans de Spring. 1.5.0 las hace intercambiables para que el código mezclado o en migración no se rompa, pero lo recomendado es la coherencia.

¿Cómo llamo a OpenAI o Anthropic desde Spring Boot?

Añade sprout-openai o sprout-anthropic junto al starter. El ejecutor @Model (openai / anthropic) se auto-descubre y es inyectable por nombre; configura la API key como una property.

¿Sprout es de código abierto?

Sí — Sprout es open source en GitHub y está publicado en Maven Central.

Consíguelo

Sprout 1.5.0 está en Maven Central. Añade sprout-spring-boot-starter (y sprout-openai y/o sprout-anthropic) en 1.5.0, manteniendo todos los artefactos de Sprout en la misma versión, configura la API key del proveedor y escribe tu primer @Agent — sin sprout.scan.base-packages, sin un segundo proceso. Referencia completa: el README del starter y las notas de la release 1.5.0. Si te ahorra un servicio Python, una ⭐ en GitHub ayuda a que otros lo encuentren.

Hablemos