Return to site

๐Ÿค–โ˜• EMBABEL 1.0.0 GA: 5 STEPS TO YOUR FIRST JAVA AGENT APP

ยท spring

Embabel 1.0.0 is now generally available! ๐ŸŽ‰

Special thanks to Igor Dayen, Alex Hein-Heifetz and the many open-source contributors who helped bring the framework to this milestone.

Embabel, created by Spring Framework founder Rod Johnson, provides a strongly typed way to build agentic applications on the JVM.

Instead of hard-coding a fixed workflow, you define:

โ–ช๏ธ Domain objects

โ–ช๏ธ Actions the system can perform

โ–ช๏ธ The goal it must achieve

Embabel can then use its planner to determine (and reconsider) the sequence of actions needed to reach that goal.

Here is a simplified five-step Java walkthrough.

๐Ÿ”ธ TL;DR

Embabel 1.0.0 brings agentic development closer to idiomatic Java and Kotlin.

You define typed domain objects, focused actions and an achievable goal. Embabel handles planning, execution and replanning while still allowing normal application code to remain in control.

๐Ÿ”ธ 1. ADD EMBABEL TO YOUR APPLICATION

<properties>
    <java.version>21</java.version>
    <embabel.version>1.0.0</embabel.version>
</properties>

<dependencies>
    <dependency>
        <groupId>com.embabel.agent</groupId>
        <artifactId>embabel-agent-starter-openai</artifactId>
        <version>${embabel.version}</version>
    </dependency>

    <dependency>
        <groupId>com.embabel.agent</groupId>
        <artifactId>embabel-agent-starter-shell</artifactId>
        <version>${embabel.version}</version>
    </dependency>
</dependencies>

The OpenAI starter configures the model integration, while the shell starter gives us an interactive environment for testing the agent.

Before starting the application, provide an OPENAI_API_KEY.

Embabel also supports Anthropic, Gemini, Mistral, DeepSeek, Ollama, LM Studio and other providers.

๐Ÿ”ธ 2. CREATE THE SPRING BOOT APPLICATION

@SpringBootApplication
public class ResearchAgentApplication {

    public static void main(String[] args) {
        SpringApplication.run(
            ResearchAgentApplication.class,
            args
        );
    }
}

Embabel builds on Spring, so agents can benefit from dependency injection, configuration, persistence, security, transactions and the wider JVM ecosystem.

Your agent is still a Spring-managed component; not an isolated Python script beside your application.

๐Ÿ”ธ 3. DEFINE A STRONGLY TYPED DOMAIN MODEL

public record ResearchRequest(
    String topic,
    String audience
) {}

public record ResearchFindings(
    List<String> facts,
    List<String> sources
) {}

public record ResearchBrief(
    String title,
    String summary,
    List<String> takeaways
) {}

These types are more than DTOs.

They describe the data flowing through the agent:

UserInput
   โ†“
ResearchRequest
   โ†“
ResearchFindings
   โ†“
ResearchBrief

Embabel uses these input and output types to infer action preconditions and postconditions.

No giant untyped map. No manually maintained workflow state machine.

๐Ÿ”ธ 4. EXTRACT THE REQUEST AND CALL TOOLS

@Agent(
    description =
        "Research a topic and produce a technical brief"
)
public class ResearchBriefAgent {

    @Action
    public ResearchRequest understandRequest(
            UserInput input,
            OperationContext context) {

        return context.promptRunner()
            .createObjectIfPossible(
                """
                Extract a research topic and its intended
                audience from this request:

                %s
                """.formatted(input.getContent()),
                ResearchRequest.class
            );
    }

    @Action
    public ResearchFindings research(
            ResearchRequest request,
            OperationContext context) {

        return context.ai()
            .withDefaultLlm()
            .withToolGroup(CoreToolGroups.WEB)
            .createObject(
                """
                Research the following topic:

                Topic: %s
                Audience: %s

                Return verified facts and their sources.
                """.formatted(
                    request.topic(),
                    request.audience()
                ),
                ResearchFindings.class
            );
    }
}

Two representative Embabel capabilities appear here.

createObjectIfPossible() provides best-effort structured output. When the model cannot create the requested object, it can return null rather than immediately terminating the process.

The second action gives the LLM access to web tools. The model can decide which searches or tool calls are required instead of relying only on its training data.

๐Ÿ”ธ 5. DECLARE THE GOAL

@AchievesGoal(
    description =
        "Produce a sourced technical research brief",
    export = @Export(
        remote = true,
        name = "researchBrief",
        startingInputTypes = {UserInput.class}
    )
)
@Action
public ResearchBrief writeBrief(
        ResearchRequest request,
        ResearchFindings findings,
        OperationContext context) {

    return context.ai()
        .withDefaultLlm()
        .createObject(
            """
            Create a concise technical brief.

            Topic: %s
            Audience: %s
            Facts: %s
            Sources: %s

            Include a title, summary and takeaways.
            Do not invent information.
            """.formatted(
                request.topic(),
                request.audience(),
                findings.facts(),
                findings.sources()
            ),
            ResearchBrief.class
        );
}

// From the Embabel shell:
//
// x "Create a Java developer brief about virtual threads"

@AchievesGoal identifies the action that completes the agentโ€™s objective.

The developer has not explicitly written:

First call A, then B, then C.

Instead, Embabel can infer the route from the available types and actions:

UserInput
โ†’ understandRequest()
โ†’ research()
โ†’ writeBrief()
โ†’ ResearchBrief

Instead, Embabel can infer the route from the available types and actions:That is the key difference between a manually scripted LLM pipeline and a goal-oriented agent.

๐Ÿ”ธ TAKEAWAYS

โ–ช๏ธ Embabel is built for Java, Kotlin, Spring and existing JVM assets

โ–ช๏ธ Strong typing connects LLM interactions with real domain models

โ–ช๏ธ GOAP planning replaces many rigid, manually scripted workflows

โ–ช๏ธ Actions can combine deterministic Java code, LLM calls and external tools

โ–ช๏ธ Structured output makes AI results easier to validate and integrate

โ–ช๏ธ Version 1.0.0 also expands areas such as ToolishRag, streaming, guardrails, budget enforcement, conversation storage, ONNX embeddings, BYOK, skills and secured MCP tools

โ–ช๏ธ GA does not mean every optional module has the same maturity: check whether a module is marked Stable, Incubating or Experimental before using it in production

Embabel is not trying to replace Spring AI.

A useful analogy is that Spring AI provides lower-level AI integration capabilities, while Embabel offers a higher-level model for composing them into goal-driven agents.

AI on the JVM just became much more interesting. ๐Ÿš€

#Java #Kotlin #Spring #SpringBoot #Embabel #AgenticAI #GenerativeAI #JVM #ArtificialIntelligence #OpenSource #SoftwareDevelopment #JavaDeveloper

Go further with Java certification:

Java๐Ÿ‘‡

Spring๐Ÿ‘‡

SpringBook๐Ÿ‘‡

JavaBook๐Ÿ‘‡