惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Securelist
L
LangChain Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
腾讯CDC
月光博客
月光博客
S
Schneier on Security
Simon Willison's Weblog
Simon Willison's Weblog
WordPress大学
WordPress大学
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Cisco Blogs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
美团技术团队
S
Security @ Cisco Blogs
人人都是产品经理
人人都是产品经理
L
LINUX DO - 热门话题
S
SegmentFault 最新的问题
D
DataBreaches.Net
C
CXSECURITY Database RSS Feed - CXSecurity.com
Microsoft Security Blog
Microsoft Security Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
N
News | PayPal Newsroom
W
WeLiveSecurity
F
Fortinet All Blogs
The Hacker News
The Hacker News
The Register - Security
The Register - Security
P
Palo Alto Networks Blog
Engineering at Meta
Engineering at Meta
T
The Exploit Database - CXSecurity.com
Vercel News
Vercel News
G
GRAHAM CLULEY
博客园 - 聂微东
P
Privacy International News Feed
P
Privacy & Cybersecurity Law Blog
Hacker News: Ask HN
Hacker News: Ask HN
Webroot Blog
Webroot Blog
G
Google Developers Blog
T
Tailwind CSS Blog
V
Vulnerabilities – Threatpost
L
Lohrmann on Cybersecurity
T
Tenable Blog
Cisco Talos Blog
Cisco Talos Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
S
Security Affairs
云风的 BLOG
云风的 BLOG
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
B
Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Hugging Face - Blog
Hugging Face - Blog
T
Threatpost

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Sprout: a Spring-style, Spring-compatible framework for building AI tooling in Java
ivannavas · 2026-06-22 · via DEV Community

ivannavas

Your backend already exists. It runs on the JVM, it has services, configuration and tests, and increasingly it needs to do AI things — call a model, expose some tools, run an agent loop. Sprout lets you add those capabilities right where your code already lives, as ordinary beans that drop into the dependency injection, configuration and tests you already use.

Sprout is a foundation for building AI tooling in Java — a simple, modular, Spring-style and Spring-compatible IoC container with a provider-agnostic model layer, automatic tool/JSON-schema plumbing and Model Context Protocol support, all behind one open extension SPI. A cohesive base like this is still uncommon in the Java ecosystem, where most options are thin API clients. Sprout is meant to be the cornerstone you keep building AI tooling on — and, with the Spring Boot starter, to fit straight into the backend you already maintain.

It's 1.1.0 on Maven Central and Apache-2.0 on GitHub. Here's the tour.

An agent is just an annotated class

The flagship capability today is agents. An agent is an annotated class that extends AgentExecutor — declare a model, write @Tool methods, and Sprout runs the model/tool loop for you:

@Agent(model = AnthropicModelExecutor.class, systemPrompt = "You are a helpful assistant.")
public class WeatherAgent extends AgentExecutor {

    @Tool(description = "Look up the weather forecast for a city")
    public String lookup(String city) {
        return "Sunny, 25°C in " + city;
    }
}

SproutContainer container = SproutApplication.run(MyApp.class);
AgentExecutor agent = container.getSingleton("weatherAgentExecutor");
System.out.println(agent.execute("session-1", "What's the weather in Madrid?").response());

Notice the symmetry: a @Model class extends ModelExecutor, and a @Agent class extends AgentExecutor — the agent is its own executor. The executor loops: it sends the conversation to the model, dispatches any tool calls, feeds the results back, and repeats until the model produces a final answer or maxIterations is reached.

The @Tool parameter JSON-Schema is generated automatically from the method signature (compile with -parameters) — primitives, enums and collections map across, and every parameter is required by default. Add @ToolParam to describe a parameter or mark it optional; a good description noticeably improves how reliably the model fills the argument in. Tools are ordinary methods backed by the services you already have.

Conversation history is persisted through an AbstractConversationStore — a thread-safe in-memory one by default; swap in your own to persist it. And to stream a run instead of blocking, call executeStream(conversationId, prompt, listener): assistant tokens, tool calls and the final response arrive through a StreamListener as they happen.

A real IoC container, not a bag of clients

Everything above sits on a Spring-style container. You annotate classes and let it discover, instantiate and wire them:

  • @Component / @Service mark managed singletons.
  • @Autowired injects by type into fields or through a constructor; @Qualifier selects a specific bean by name.
  • @PostConstruct runs initialisation once dependencies are injected.
  • @Value and @Configuration/@ConfigurationProperty bind configuration, with Spring-style ${key:default} placeholders resolved against sprout.properties, system properties and environment variables.

The richer stereotypes — @Service, @Model, @Agent, @ConversationStore, @Mcp — are all meta-annotated with @Component. So a model and an agent are ordinary managed singletons too: the container builds and wires them, and you inject them anywhere exactly like any other bean. They are not a separate kind of object.

Provider-agnostic models

A model is a ModelExecutor subclass annotated with @Model. sprout-anthropic and sprout-openai ship implementations; you can add your own — including offline, deterministic stubs for tests — by extending ModelExecutor and implementing chat(ModelRequest). Swapping providers doesn't touch your agent code: the agent depends on a ModelExecutor, not on a vendor SDK.

MCP, both sides

With sprout-mcp on the classpath, an @Mcp bean's @Tool methods are published over the Model Context Protocol — no agent required. And an @Agent can connect to remote MCP servers with @UseMcp and use their tools as if they were its own. The same @Tool methods that power an agent can be exposed as a server.

Multi-agent orchestration

sprout-orchestration adds three patterns that compose around plain AgentExecutor beans.

Concurrent runs. An AgentOrchestrator wraps an agent to run several prompts at once. Each execute is scheduled on a worker thread and returns immediately, so calls fan out concurrently; a failing run is isolated and never tears down the others:

try (AgentOrchestrator orchestrator = AgentOrchestrator.of(agent)) {
    orchestrator.execute("Tell me about Mars", "mars", "mars-session")
                .execute("Tell me about Venus", "venus", "venus-session")
                .waitForExecutions();

    System.out.println(orchestrator.getResult("mars").block().response());
}

Delegation. One agent delegates to specialists. An AgentDelegation exposes a set of specialist agents to a supervisor as tools — one per specialist — through the very same ToolProvider SPI the agent already uses for its @Tool methods and MCP servers, so the executor needs no special-casing:

AgentDelegation.builder()
        .specialist("math", "Solves arithmetic and number problems.", mathAgent)
        .specialist("history", "Answers history and general-knowledge questions.", historyAgent)
        .attachTo(supervisor);

System.out.println(supervisor.execute("session", "What is 6 times 7?").response());

Hand-off. Instead of calling a specialist as an isolated sub-task, an agent transfers control. An AgentHandoff gives each team member a handoff_to_<member> tool; the conversation passes to that agent, which continues the same shared transcript and produces the final answer — while still applying its own system prompt to its turns:

AgentHandoff team = AgentHandoff.builder()
        .member("triage", "First point of contact; routes the user.", triageAgent)
        .member("billing", "Handles invoices, payments and refunds.", billingAgent)
        .member("tech", "Handles login, passwords and technical errors.", techAgent)
        .build();

AgentHandoff.HandoffResult result = team.run("I have a question about my invoice.");
System.out.println(result.path());     // [triage, billing]
System.out.println(result.response()); // the billing agent's answer

The three compose: because delegation happens inside an agent's own run, a delegating supervisor is just an AgentExecutor — so you can orchestrate it concurrently and make it the target of a hand-off, all around one hub.

Fully Spring-compatible — in both directions

Add sprout-spring-boot-starter and the container is bootstrapped during context startup, with no glue code:

  • Sprout → Spring: every Sprout bean (agents' executors, models, services...) is registered in the ApplicationContext, so you can @Autowired it into any @Controller/@Service.
  • Spring → Sprout: a Sprout component can depend on a Spring bean; it is resolved from the BeanFactory as a lazy proxy, preserving AOP/@Transactional.

So an agent can be backed by an existing Spring @Service and called straight from a controller:

@Agent(model = AnthropicModelExecutor.class, systemPrompt = "You are a weather assistant.")
public class WeatherAgent extends AgentExecutor {

    private final WeatherService weather;          // an existing Spring @Service

    @Autowired
    public WeatherAgent(WeatherService weather) {  // Spring bean injected into the agent
        this.weather = weather;
    }

    @Tool(description = "Look up the forecast for a city")
    public String forecast(String city) {
        return weather.forecast(city);
    }
}

The runnable Spring example pushes this all the way: a /weather/batch endpoint is a plain @RestController that fans a forecast-per-city out concurrently with AgentOrchestrator, over a Spring-managed @Agent whose tool is a Spring @Service and whose conversations persist to a database via JPA. One HTTP call drives concurrent multi-agent work with Spring DI and JPA persistence — all inside the same application, using the framework and the beans you already run.

Customizable to the core

Here's the part I'm most proud of: the processing pipeline is fully open, and it is the same mechanism the built-in features use — there is no privileged core. To teach Sprout a new annotation, subclass ComponentProcessor and register it with @Processor(MyAnnotation.class); it's discovered automatically and applied to every component carrying that annotation. A whole custom stereotype is only a few lines:

@Retention(RUNTIME) @Target(TYPE) @Component   // a custom stereotype, discovered by scanning
public @interface Plugin {}

@Processor(Plugin.class)                        // applied to every @Plugin component
public class PluginProcessor extends ComponentProcessor {

    public PluginProcessor(Class<?> component, SproutContainer container) {
        super(component, container);
    }

    @Override
    public Set<String> beanNames() {            // standard wiring still runs; here we add an alias
        Set<String> names = new HashSet<>(super.beanNames());
        names.add("plugin:" + component.getSimpleName());
        return names;
    }
}

This is exactly how @Agent, @Model, @Configuration and @Mcp are implemented — each lives in its own module and plugs in without the core knowing about it. The same door is open to your code and to third-party modules, so the framework can grow a module for anything: a new model provider, a transport, a persistence-backed conversation store, custom stereotypes.

The modules

Module What it provides
sprout-core IoC container, component scanning, DI, configuration, and the agent/model/tool abstractions.
sprout-anthropic ModelExecutor for Anthropic's Messages API (@Model("anthropic")).
sprout-openai ModelExecutor for OpenAI's Chat Completions API (@Model("openai")).
sprout-mcp Expose @Tool methods as an MCP server, and consume remote MCP servers from an agent.
sprout-orchestration Concurrent runs, supervisor delegation and conversation hand-off.
sprout-spring-boot-starter Runs Sprout inside Spring Boot, bridging beans and configuration both ways.

Requirements: Java 21, Maven 3.9+.

Where it's headed

This is an early release, so the surface is deliberately focused — expect gaps and rough edges. On the roadmap: nested-object tool parameters, built-in JDBC/Redis conversation stores, real SSE provider streaming, more providers (Gemini, Azure OpenAI, Ollama), memory & RAG, observability/token accounting, structured output, human-in-the-loop guardrails, and GraalVM native image.

Try it

<dependency>
    <groupId>io.github.ivannavas</groupId>
    <artifactId>sprout-core</artifactId>
    <version>1.1.0</version>
</dependency>

If you build AI features on the JVM — or wish you could without leaving it — I'd love your feedback, issues and stars. What would you want a Java-native agent framework to do next?