AI Agents in Spring Boot with Java — Sprout 1.5.0
Add AI agents to your Spring Boot app in pure Java, with no glue code
If you build backends in Java, adding AI agents has usually meant a detour: stand up a separate Python
service, wire it over HTTP, and keep two runtimes in sync. Sprout
is a Java AI framework that runs inside Spring Boot instead — and Sprout 1.5.0 makes the seam
between the two disappear. The best part: your controllers, your @Services and your application.yml
stay exactly as they are.
TL;DR
- Sprout runs inside your Spring Boot process — inject an agent into a
@RestController, back its@Tools with the Spring@Services you already have. - 1.5.0 lets Sprout and Spring beans use each other's DI annotations both ways, so same-named
@Autowired/@Value/@Qualifiernever clash again. - Drop in
sprout-openaiorsprout-anthropicand the@Modelexecutor is auto-discovered — nosprout.scan.base-packages. sprout-monitoringactivates on its own, exposed as a Spring bean.- Same JVM, same configuration, same tests. No Python service.
Running AI agents inside Spring Boot
Add the sprout-spring-boot-starter dependency and the two containers start talking: every Sprout bean —
agents, models, tools, services — is registered in the Spring ApplicationContext, and Sprout components
can depend on your Spring beans in return. So an agent is just another bean you @Autowired:
@RestController
class ChatController {
private final AgentExecutor supportAgent; // a Sprout @Agent, exposed as a Spring bean
ChatController(@Qualifier("supportAgentExecutor") AgentExecutor supportAgent) {
this.supportAgent = supportAgent;
}
@PostMapping("/chat")
String chat(@RequestBody String prompt) {
return supportAgent.execute("conversation-1", prompt).response();
}
}
That bridge has existed for a while. 1.5.0 is about the last rough edges.
Mixing annotations: Sprout and Spring, both ways
Sprout and Spring each ship an @Autowired, a @Value and a @Qualifier. Before 1.5.0, using the
"wrong" one inside a class managed by the other container meant it was silently ignored — the classic
"why is this field null?" papercut. In 1.5.0 the two sets are treated as equivalents, in both
directions.
A Sprout component works when wired with Spring's — or JSR-330's — annotations:
@Service // Sprout's stereotype
public class PricingService {
@org.springframework.beans.factory.annotation.Autowired // Spring's @Autowired
private RateRepository rates;
@org.springframework.beans.factory.annotation.Value("${pricing.currency}") // Spring's @Value
private String currency;
@io.github.ivannavas.sprout.annotation.Value("${pricing.margin:0.15}") // Sprout's @Value
private double margin;
}
And a Spring bean works when wired with Sprout's @Autowired / @Value / @Qualifier /
@PostConstruct (field injection and @PostConstruct; for constructor injection on a Spring bean, use
Spring's own @Autowired):
@Component // Spring's stereotype
public class ReportBuilder {
@io.github.ivannavas.sprout.annotation.Autowired // Sprout's @Autowired
private SummaryAgentExecutor agent; // a Sprout @Agent bean
@io.github.ivannavas.sprout.annotation.Value("${report.title}")
private String title;
@io.github.ivannavas.sprout.annotation.PostConstruct
void init() { /* runs after the fields above are wired */ }
}
Here's the important part: this is a compatibility net, not a style. It exists so mixed or migrating
code never breaks silently — not as an invitation to scatter both flavours everywhere. The
recommendation stays simple: use Sprout's annotations in Sprout components, and each DI container's own
annotations in its own beans. And none of it leaks Spring into Sprout's core — sprout-core recognises
only its own annotations; the starter contributes the Spring and JSR-330 equivalents.
Zero config: drop in OpenAI or Anthropic
Adding a model provider used to need one extra line — telling Sprout which package the executor lived in,
via sprout.scan.base-packages. In 1.5.0 each module contributes its own package to the scan, so the
OpenAI and Anthropic @Model executors are discovered the moment the jar is on the 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> <!-- or sprout-anthropic -->
<version>1.5.0</version>
</dependency>
No scan configuration. Inject the executor into any Spring bean by name:
ChatController(@Qualifier("openai") ModelExecutor openai) { ... } // a Sprout @Model, injected by Spring
Monitoring, on by default
sprout-monitoring follows the same rule: add the module and usage, token and cost tracking activates
on its own, exposed as the Spring usageStore bean. Declare your own @UsageStore and it takes over —
nothing to scan, nothing to configure.
One source of truth for configuration
Spring's Environment — application.yml / application.properties, system properties, environment
variables — feeds Sprout's configuration. A Sprout @Value("${pricing.currency}") reads the same
property a Spring @Value would, from the same place. Nothing to duplicate.
FAQ
Can I use AI agents in Spring Boot with Java (no Python)?
Yes. Sprout is a Java AI framework that runs inside your Spring Boot process. Agents, LLM model executors and tools are ordinary Spring-injectable beans, so there's no separate Python service and no network hop.
Does Sprout replace Spring's dependency injection?
No. Sprout keeps its own container for its components and exposes them to Spring, and it can consume Spring beans. You keep using Spring exactly as you do today; the starter bridges the two.
Which annotations should I use — Sprout's or Spring's?
Use Sprout's in Sprout components and Spring's in Spring beans. 1.5.0 makes them interchangeable so mixed or migrating code doesn't break, but consistency is the recommended style.
How do I call OpenAI or Anthropic from Spring Boot?
Add sprout-openai or sprout-anthropic alongside the starter. The @Model executor (openai /
anthropic) is auto-discovered and injectable by name — configure the API key as a property.
Is Sprout open source?
Yes — Sprout is open source on GitHub and published to Maven Central.
Get it
Sprout 1.5.0 is on Maven Central. Add sprout-spring-boot-starter (plus sprout-openai and/or
sprout-anthropic) at 1.5.0, keeping every Sprout artifact on the same version, set your provider API
key, and write your first @Agent — no sprout.scan.base-packages, no second process. Full reference:
the starter README
and the 1.5.0 release notes. If it
saves you a Python service, a ⭐ on GitHub helps others
find it.