Getting Started with Spring Boot + Embabel: Build an AI Blog Assistant in Java
If you already know how to write Spring Boot applications and are exploring ways to integrate large language models into your business systems, you will quickly run into a practical problem: a single LLM call is simple, but orchestrating multiple LLM calls, database queries, rule checks, tool invocations, and business objects into a reliable workflow is anything but.
Spring AI acts as infrastructure for making model calls, vector stores, and tool invocations accessible from Spring applications. Embabel operates at a higher level. It is an agentic flow framework running on the JVM whose goal is to blend LLM prompt interactions, ordinary Java/Kotlin code, and strongly typed domain models using concepts like Agent, Action, Goal, and Plan to organize workflows.
Embabel’s official documentation describes an Agent as a self-contained component that combines domain logic, AI capabilities, and tool use to accomplish a specific goal on behalf of a user.
This guide uses a scenario close to real content production: we will build an AI Blog Assistant on top of Spring Boot + Embabel. The user submits a topic; the system understands the writing intent, generates an outline, writes a draft, reviews it, and returns a final Markdown article. The example is designed to be approachable while keeping the code complete enough to serve as a starting point for your own projects.
1. What Problem Does Embabel Solve?
Without an agent framework, a common approach to AI workflows looks like this: a Controller receives a request, and a Service calls parseTopic(), generateOutline(), writeDraft(), and reviewDraft() in sequence. This works, but it has a clear drawback: the workflow order is hardcoded. As soon as you need to add SEO optimization, fact checking, content moderation, database lookups, or external tool calls, that Service easily becomes a long, hard-to-maintain “process script.”
Embabel takes a different approach. Instead of writing a fixed pipeline upfront, you declare what actions an Agent can perform using @Action, and then tell the system what result constitutes success using @AchievesGoal or a Goal type. Embabel dynamically plans which steps to execute based on the objects currently available and the input/output types of each Action. The official documentation describes this as modeling around Actions, Goals, Conditions, a Domain Model, and a Plan, with the plan re-evaluated after each Action completes.
| Concept | Plain-language meaning | Typical code form |
|---|---|---|
| Agent | A “smart business component” with a set of capabilities | A Spring Bean annotated with @Agent |
| Action | A single step an Agent can perform | A Java method annotated with @Action |
| Goal | The final result the Agent needs to produce | @AchievesGoal or a target type |
| Domain Model | Strongly typed business objects flowing through the pipeline | Java records or classes |
| Plan | The sequence of steps generated to reach the goal | Dynamically planned by the Embabel platform |
This is the fundamental difference between Embabel and a plain LLM call: instead of treating AI as a text-generation endpoint, Embabel places AI inside an execution system jointly constrained by strongly typed objects and business code. This is very Java-developer-friendly because you still use Spring’s dependency injection, configuration management, testing infrastructure, transactions, database access, and ordinary business services.
2. What We Are Building
We will implement a simple but complete blog generation assistant. The user submits a topic through an HTTP endpoint, and the backend returns a reviewed Markdown blog post.
The overall flow looks like this:
flowchart LR
A[User submits topic] --> B[BlogIdea\nUnderstand topic and audience]
B --> C[BlogOutline\nGenerate article outline]
C --> D[BlogDraft\nWrite first draft]
D --> E[ReviewedBlogPost\nReview and produce final article]
None of these four nodes are plain Map or raw JSON strings — they are Java records. Embabel strongly encourages this strongly typed approach because it turns LLM output into objects that business code can understand, test, and refactor.
| Step | Input object | Output object | LLM call | Description |
|---|---|---|---|---|
| Understand topic | UserInput | BlogIdea | Yes | Extract topic, audience, and tone from natural language |
| Generate outline | BlogIdea | BlogOutline | Yes | Produce a structured section outline |
| Write draft | BlogOutline | BlogDraft | Yes | Write a Markdown first draft based on the outline |
| Review and finalize | BlogDraft | ReviewedBlogPost | Yes | Improve the draft and return the final result |
Note that the Embabel API continues to evolve across versions. The code in this guide follows conventions seen in the official documentation and 2026 community examples: @Agent, @Action, @AchievesGoal, OperationContext, and AgentInvocation.builder(agentPlatform). If your version differs slightly, always defer to the official documentation for that version.
3. Environment Setup and Version Selection
The Embabel official documentation states that the easiest way to get started is to add the Embabel Spring Boot starter to your project, with release versions published to Maven Central. The com.embabel.agent:embabel-agent-starter artifact has several Central versions available, with 0.4.0 released on 2026-05-19 and 0.3.5 being a recent 0.3.x release.
For a stable experience, this guide recommends starting with Spring Boot 3.5.x, Java 21+, and Embabel 0.4.0. If your project is still on Java 17, check the compatibility requirements for your target Embabel version. The official examples repository lists Java 21+, at least one LLM API key, and Maven 3.9+ as prerequisites.
| Software | Recommended version | Notes |
|---|---|---|
| JDK | 21+ | Java 21 is a widely accepted LTS version for enterprise projects |
| Spring Boot | 3.5.x | A solid choice for getting started; check docs for Boot 4 compatibility |
| Maven | 3.9+ | Required by the official examples repository |
| Embabel | 0.4.0 | One of the latest release versions on Maven Central |
| Model provider | OpenAI-compatible | The example uses the OPENAI_API_KEY environment variable |
4. Create the Spring Boot Project
Create a standard Maven project at Spring Initializr using these settings:
| Field | Example value |
|---|---|
| Group | com.example |
| Artifact | embabel-blog-demo |
| Package | com.example.embabelblog |
| Java | 21 |
| Dependencies | Only Spring Web for now |
After generating the project, manually edit pom.xml to add the Embabel dependencies.
5. Maven Configuration
Below is the complete pom.xml. We use embabel-agent-starter because we are building a web application driven by an HTTP Controller, plus embabel-agent-starter-openai to connect to OpenAI or an OpenAI-compatible model. The official documentation explains that the base starter registers the Agent Platform Bean in the Spring container; embabel-agent-starter-openai is also needed if you are not using a template project and want to work with OpenAI-compatible models.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.0</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>embabel-blog-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>embabel-blog-demo</name>
<description>Spring Boot + Embabel getting started demo</description>
<properties>
<java.version>21</java.version>
<embabel-agent.version>0.4.0</embabel-agent.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.embabel.agent</groupId>
<artifactId>embabel-agent-starter</artifactId>
<version>${embabel-agent.version}</version>
</dependency>
<dependency>
<groupId>com.embabel.agent</groupId>
<artifactId>embabel-agent-starter-openai</artifactId>
<version>${embabel-agent.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
If you are using a snapshot version rather than a Maven Central release, you will also need to configure Embabel’s release and snapshot repositories. For getting started, stick with release versions to avoid dependency resolution issues and unexpected API changes.
6. Configure application.yml
Create src/main/resources/application.yml to configure the application name, port, and default LLM. For OpenAI-compatible setups you need at minimum an OPENAI_API_KEY; you can also specify the API key and base URL directly in the configuration file.
spring:
application:
name: embabel-blog-demo
server:
port: 8080
embabel:
models:
default-llm: gpt-4.1-mini
agent:
platform:
models:
openai:
api-key: ${OPENAI_API_KEY}
base-url: ${OPENAI_BASE_URL:}
default-llm sets the default model. OPENAI_API_KEY is read from an environment variable — never hardcode real keys in your repository. Before starting the application, set the variable:
export OPENAI_API_KEY="your-api-key"
If you are using an OpenAI-compatible endpoint such as an enterprise gateway or another cloud provider, also set:
export OPENAI_BASE_URL="https://your-compatible-endpoint.example.com/v1"
7. Main Class: Enable Agent Scanning
Create src/main/java/com/example/embabelblog/EmbabelBlogApplication.java. The @EnableAgents annotation activates Embabel Agent scanning, which is how classes annotated with @Agent are registered with the platform.
package com.example.embabelblog;
import com.embabel.agent.config.annotation.EnableAgents;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableAgents
public class EmbabelBlogApplication {
public static void main(String[] args) {
SpringApplication.run(EmbabelBlogApplication.class, args);
}
}
Think of @EnableAgents as “tell Spring Boot to also discover Embabel Agents at startup.” Once discovered, Embabel knows which Agents, Actions, and Goals the application contains.
8. Define the Domain Model
Create a model package. Domain models are a crucial part of any Embabel application. Rather than rushing to write prompts or returning large JSON strings from the LLM, first ask yourself: what business objects does this workflow produce? What are the inputs and outputs at each step?
8.1 BlogIdea
BlogIdea represents the writing intent extracted from the user’s input.
package com.example.embabelblog.model;
public record BlogIdea(
String topic,
String targetAudience,
String tone,
String keyMessage
) {
}
| Field | Meaning | Example |
|---|---|---|
topic | Article topic | Global exception handling in Spring Boot |
targetAudience | Intended readers | Junior to mid-level Java developers |
tone | Writing style | Practical and approachable |
keyMessage | Core takeaway | Unified error handling improves API consistency |
8.2 BlogOutline
BlogOutline represents the article outline. We use a nested record to keep the code concise.
package com.example.embabelblog.model;
import java.util.List;
public record BlogOutline(
String title,
String summary,
List<Section> sections
) {
public record Section(
String heading,
String purpose,
List<String> keyPoints
) {
}
}
The sections list is a structured chapter breakdown. Compared to asking the model to return raw Markdown, an outline object is easier to validate and makes it simple to later add actions like “adjust the outline” or “inject SEO keywords.”
8.3 BlogDraft
BlogDraft holds the first draft written from the outline.
package com.example.embabelblog.model;
public record BlogDraft(
String title,
String markdown,
int estimatedReadingMinutes
) {
}
A draft is not the final goal — it is an intermediate artifact in the pipeline.
8.4 ReviewedBlogPost
ReviewedBlogPost is the reviewed final article and will be the return type of our HTTP endpoint.
package com.example.embabelblog.model;
import java.util.List;
public record ReviewedBlogPost(
String title,
String markdown,
List<String> improvements,
List<String> warnings
) {
}
improvements lists the changes made during the review stage. warnings flags anything that may still need a human check — for example, “this version number should be verified against the official documentation.”
8.5 GenerateBlogRequest
A simple request object for the Controller to accept a JSON body.
package com.example.embabelblog.model;
public record GenerateBlogRequest(
String topic,
String targetAudience,
String tone
) {
}
9. Write the BlogWritingAgent
Now we get to the heart of Embabel. Create an agent package and add BlogWritingAgent.java.
An Embabel Agent is a Spring Bean containing one or more @Action methods. Each Action method’s parameters declare which objects it needs, and the return type declares what it produces. Embabel infers the workflow path from these type relationships.
package com.example.embabelblog.agent;
import com.embabel.agent.api.annotation.AchievesGoal;
import com.embabel.agent.api.annotation.Action;
import com.embabel.agent.api.annotation.Agent;
import com.embabel.agent.api.common.OperationContext;
import com.embabel.agent.domain.io.UserInput;
import com.example.embabelblog.model.BlogDraft;
import com.example.embabelblog.model.BlogIdea;
import com.example.embabelblog.model.BlogOutline;
import com.example.embabelblog.model.ReviewedBlogPost;
@Agent(description = "Generates a beginner-friendly technical blog post from a user-supplied topic")
public class BlogWritingAgent {
@Action(description = "Extract the blog writing intent from user input")
public BlogIdea understandIdea(UserInput input, OperationContext context) {
String prompt = """
You are a senior technical editor. Extract the blog writing intent from the
user's input and return a structured object.
Requirements:
1. topic: the article subject.
2. targetAudience: the intended readers; default to "junior to mid-level Java developers"
if the user does not specify.
3. tone: the writing style; default to "practical and approachable" if not specified.
4. keyMessage: the single most important idea the article should convey.
User input:
%s
""".formatted(input.getContent());
return context.ai()
.withDefaultLlm()
.createObject(prompt, BlogIdea.class);
}
@Action(description = "Generate a blog outline from the writing intent")
public BlogOutline createOutline(BlogIdea idea, OperationContext context) {
String prompt = """
You are a Java technical blogger. Generate a clear outline based on the writing
intent below.
Topic: %s
Audience: %s
Tone: %s
Key message: %s
Outline requirements:
1. The title must be specific, not generic.
2. summary: 2–3 sentences describing the article content.
3. sections: 5–7 chapters recommended.
4. Each section must include a heading, purpose, and keyPoints.
5. keyPoints should be short phrases easy to expand later.
""".formatted(
idea.topic(),
idea.targetAudience(),
idea.tone(),
idea.keyMessage()
);
return context.ai()
.withDefaultLlm()
.createObject(prompt, BlogOutline.class);
}
@Action(description = "Write a Markdown first draft from the blog outline")
public BlogDraft writeDraft(BlogOutline outline, OperationContext context) {
String prompt = """
You are a technical writer specializing in Spring Boot and Java. Write a Markdown
first draft based on the outline below.
Title: %s
Summary: %s
Sections: %s
Writing requirements:
1. Write in English.
2. Target beginners — explanations should be clear and accessible.
3. Each section must contain full paragraphs, not just bullet points.
4. Include short but understandable Java code examples where relevant.
5. Estimate estimatedReadingMinutes based on the length of the body text.
""".formatted(
outline.title(),
outline.summary(),
outline.sections()
);
return context.ai()
.withDefaultLlm()
.createObject(prompt, BlogDraft.class);
}
@Action(description = "Review the first draft, correct phrasing and technical details, and produce the final article")
@AchievesGoal(description = "Produce a reviewed technical blog post")
public ReviewedBlogPost reviewDraft(BlogDraft draft, OperationContext context) {
String prompt = """
You are a rigorous but supportive technical reviewer. Review and improve the
blog draft below.
Original title: %s
Draft:
%s
Review requirements:
1. Correct obvious technical inaccuracies.
2. Make the language more accessible for beginners.
3. Preserve Markdown formatting.
4. improvements: list the main changes you made.
5. warnings: list anything that should still be verified by a human;
return an empty list if there are none.
""".formatted(draft.title(), draft.markdown());
return context.ai()
.withDefaultLlm()
.createObject(prompt, ReviewedBlogPost.class);
}
}
Several things are worth examining carefully.
First, BlogWritingAgent is annotated with @Agent. This marks it as an Embabel-recognized Agent rather than a plain Service. It is still a Spring-managed component, so you can freely inject your own Repositories, Services, configuration classes, or auditing components through the constructor.
Second, all four methods are annotated with @Action. understandIdea() takes UserInput and returns BlogIdea; createOutline() takes BlogIdea and returns BlogOutline; writeDraft() takes BlogOutline and returns BlogDraft; reviewDraft() takes BlogDraft and returns ReviewedBlogPost. These type relationships are exactly what Embabel uses to plan the execution path.
Third, reviewDraft() also carries @AchievesGoal. This tells Embabel: once the system successfully produces a ReviewedBlogPost, the blog generation task is complete.
10. Write the REST Controller
The official documentation shows how to inject AgentPlatform, build an invocation with AgentInvocation.builder(agentPlatform), and execute it with invoke(input). We embed this pattern in a Spring MVC Controller.
Create controller/BlogController.java:
package com.example.embabelblog.controller;
import com.embabel.agent.api.common.AgentInvocation;
import com.embabel.agent.api.common.AgentPlatform;
import com.embabel.agent.api.common.ProcessOptions;
import com.embabel.agent.domain.io.UserInput;
import com.example.embabelblog.model.GenerateBlogRequest;
import com.example.embabelblog.model.ReviewedBlogPost;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/blogs")
public class BlogController {
private final AgentPlatform agentPlatform;
public BlogController(AgentPlatform agentPlatform) {
this.agentPlatform = agentPlatform;
}
@PostMapping("/generate")
public ReviewedBlogPost generate(@RequestBody GenerateBlogRequest request) {
String userMessage = """
Please write a technical blog post for me.
Topic: %s
Target audience: %s
Writing style: %s
""".formatted(
request.topic(),
defaultIfBlank(request.targetAudience(), "junior to mid-level Java developers"),
defaultIfBlank(request.tone(), "practical and approachable")
);
UserInput input = new UserInput(userMessage);
AgentInvocation<ReviewedBlogPost> invocation = AgentInvocation
.builder(agentPlatform)
.options(ProcessOptions.builder()
.verbosity(v -> v.showPrompts(false))
.build())
.build(ReviewedBlogPost.class);
return invocation.invoke(input);
}
private static String defaultIfBlank(String value, String defaultValue) {
return value == null || value.isBlank() ? defaultValue : value;
}
}
The Controller only states: I have a UserInput and I want a ReviewedBlogPost. Which Actions to execute in between is determined by the Embabel platform based on the capabilities declared in the Agent. That is the key point — you do not write:
BlogIdea idea = agent.understandIdea(input);
BlogOutline outline = agent.createOutline(idea);
BlogDraft draft = agent.writeDraft(outline);
ReviewedBlogPost result = agent.reviewDraft(draft);
If the package names or constructors for AgentInvocation or UserInput differ in your version of Embabel, refer to the official documentation examples for that version. Embabel is evolving quickly and such API changes are not uncommon.
11. Run and Test
Set your API key before starting:
export OPENAI_API_KEY="your-api-key"
Then run the application:
mvn spring-boot:run
Call the endpoint with curl:
curl -X POST http://localhost:8080/api/blogs/generate \
-H "Content-Type: application/json" \
-d '{
"topic": "Elegant global exception handling in Spring Boot",
"targetAudience": "Java developers new to Spring Boot",
"tone": "clear and practical, with real-world tips"
}'
You will receive a response similar to the following (actual content varies by model output):
{
"title": "Global Exception Handling in Spring Boot: Consistent API Error Responses",
"markdown": "# Global Exception Handling in Spring Boot\n\nIn real projects...",
"improvements": [
"Added context explaining why unified exception handling matters",
"Renamed example code variables to better match Spring Boot conventions",
"Included explanations for pitfalls beginners commonly encounter"
],
"warnings": [
"Example code should be validated against the specific Spring Boot version in use"
]
}
If you inspect the application logs, you can typically see Embabel planning and executing Actions: first formulated plan, then executing action for each step, and finally goal achieved. These logs are invaluable for understanding why the Agent chose a particular execution path.
12. Why This Is Better Than Calling the LLM Directly
You might ask: every step in this example calls the LLM anyway, so why not just write four sequential method calls? Functionally, that works in the short term. But Embabel’s value shows up as the system evolves.
| Future requirement | Hardcoded pipeline | Embabel style |
|---|---|---|
| Add SEO optimization | Edit the Service flow | Add an Action that takes BlogDraft and returns SeoBlogDraft |
| Add content moderation | Insert a conditional branch | Add a moderation Action and make the goal depend on the moderated object |
| Pull reference material from a database | Query manually in the Service | Inject a Repository or Service directly into an Action |
| Mix multiple models | Manage different model clients manually | Select LLMs by config and role; the framework supports LLM mixing |
| Trace the execution path | Write your own logging | The platform can emit planning and execution details |
Embabel may feel like “an extra layer of abstraction” at first. But when a workflow grows from two steps to a dozen and starts mixing LLMs, databases, rules, tools, and external systems, that abstraction is what keeps the system maintainable.
13. Injecting Regular Spring Services into Actions
Embabel does not require every Action to call an LLM. In production systems, the recommended pattern is to use LLMs where they excel — understanding natural language, generating drafts, summarizing content — and leave deterministic logic to ordinary Java code. An Action can just as well be a database query, a scoring step, a validation check, or a call to a business service.
For example, define a reference lookup service:
package com.example.embabelblog.service;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class BlogReferenceService {
public List<String> findReferences(String topic) {
return List.of(
"Internal Java coding standards",
"Spring Boot official reference documentation",
"Historical incident post-mortems"
);
}
}
Then inject it into the Agent:
@Agent(description = "Generates a beginner-friendly technical blog post from a user-supplied topic")
public class BlogWritingAgent {
private final BlogReferenceService referenceService;
public BlogWritingAgent(BlogReferenceService referenceService) {
this.referenceService = referenceService;
}
@Action(description = "Find internal reference materials related to the topic")
public BlogReferences findReferences(BlogIdea idea) {
return new BlogReferences(referenceService.findReferences(idea.topic()));
}
}
The Agent can now use both LLMs and ordinary business code. For production systems this matters enormously: do not let the LLM take over all logic; let the LLM handle uncertain language tasks and let Java handle deterministic business rules.
14. Frequently Asked Questions
14.1 How does Embabel relate to Spring AI?
Spring AI provides foundational abstractions in the Spring ecosystem for model calls, vector stores, and tool invocations. Embabel is a higher-level Agent framework that can orchestrate goal-driven workflows on top of capabilities like Spring AI. In short: Spring AI helps you interact with models, tools, and vector stores; Embabel helps you build Agents that execute Actions to reach Goals.
14.2 Do I have to use the Shell starter?
No. The official documentation lists three common starters:
| Starter | Use case | Used in this guide |
|---|---|---|
embabel-agent-starter-shell | Learning, debugging, interactive CLI | No |
embabel-agent-starter-mcpserver | Exposing an Agent as an MCP Server | No |
embabel-agent-starter | Web API, microservice, custom startup mode | Yes |
14.3 Why use Java records for domain models?
Java records are ideal for immutable data transfer objects. Embabel emphasizes strongly typed domain models, and records make the input/output structure explicit, easier to test, and straightforward to refactor. Returning objects like BlogOutline, BlogDraft, and ReviewedBlogPost is far more suitable for a business pipeline than returning unstructured text from the model.
14.4 What if the model output does not match the expected structure?
Production systems need validation and fallback handling. You can use Bean Validation on record fields, or add a dedicated validation Action after the problematic step. If validation fails, another Action can attempt to repair the format, or you can return a descriptive error. Embabel’s value is not in preventing LLMs from ever producing bad output — it is in placing that uncertain output inside a more observable and controllable pipeline.
14.5 Can I use a model other than OpenAI?
Yes. The official documentation covers Anthropic, DeepSeek, Gemini, Mistral AI, LM Studio, Ollama, and other provider starters or configuration options. For local model execution try Ollama or LM Studio; for an enterprise-internal OpenAI-compatible gateway, configure the corresponding base URL.
15. Where to Go from Here
Once you have the example running, consider these enhancements:
| Enhancement | New domain objects | New Actions |
|---|---|---|
| SEO optimization | SeoSuggestion, SeoBlogPost | optimizeSeo() |
| Fact checking | FactList, FactCheckReport | extractFacts(), checkFacts() |
| Persist to database | SavedBlogPost | saveBlogPost() |
| Generate cover image prompt | ImagePrompt | createCoverImagePrompt() |
| Multi-language translation | TranslatedBlogPost | translatePost() |
This extension pattern highlights Embabel’s advantage: instead of continuously modifying a large pipeline, you add new types and Actions, giving the platform more composable capabilities.
16. Summary
This guide introduced the basics of Spring Boot + Embabel through an “AI Blog Assistant” example. A typical Embabel application includes a Maven starter, model configuration, @EnableAgents, domain models, @Agent, @Action, @AchievesGoal, and an invocation issued via AgentPlatform.
More importantly, Embabel brings not “fancier prompt writing” but an AI engineering mindset better suited to Java enterprise applications: use strongly typed objects to carry context, decompose capabilities into Actions, express intent as Goals, let the platform plan the execution path, and manage LLM calls and ordinary business code within the same Spring ecosystem.
If you are new to Embabel, start with a simple Agent like the one in this guide to understand how objects flow between Actions. Then gradually introduce databases, business services, tool calls, multi-model configuration, and tests. This keeps the learning curve manageable and makes it far easier to bring Embabel into a real project.
References
- Embabel Agent Framework User Guide
- Embabel Agent Framework — GitHub
- Embabel First Look: Building Agentic Flows on the JVM
- Build AI Agents in Java with Embabel: Step-by-Step Guide
- Creating an AI Agent in Java Using Embabel Agent Framework
- Embabel Agent Examples
- Maven Repository: Embabel Agent Starter