1.0.0-M1
Milestone 1 is available on Maven Central. It is a non-final, draft-status release published for
early community feedback, and has not undergone the release review required to ratify a final
specification.
Structure instead of spaghetti
A predictable shape for agent code — trigger, decision, action, outcome — that
still makes sense to whoever reads it next.
Adapts at runtime
Keep the building blocks of your domain logic simple and recompose them dynamically,
possibly in response to LLM interactions.
Pluggable LLM access
A minimal facade over the LLM libraries you already use, with automatic type conversion
and a way through to the underlying API.
Familiar Jakarta EE
An agent is a CDI bean. Injection, validation, persistence, and the rest of the platform
work exactly as you expect.
About
Artificial Intelligence agents are one of the most prominent developments in enterprise and cloud
native computing in decades. They detect events, gather data, generate self-correcting plans,
execute actions, process results, and evolve subsequent decisions.
Jakarta Agentic AI aims to do for developing AI agents what Jakarta Servlet did for HTTP
processing, Jakarta REST did for RESTful web services, or perhaps most appropriately, Jakarta
Batch did for batch processing.
Why would I want this?
It is certainly possible to write script-like agent code that invokes LLMs directly. The problem is
that for any reasonably complex agent, you will probably end up with code that is hard to maintain,
especially for someone who did not write it. This API gives your agents a long-term, predictable
structure that fits the general patterns of agentic systems.
The API shines when agents must adapt their behaviour at runtime. Keep the building blocks of your
domain logic simple, and change how they are composed dynamically, possibly in response to LLM
interactions. Think of those blocks as the elements of a flow chart that can update itself.
Is this an LLM API like Spring AI or LangChain4j?
No. It is an API that helps you write better AI agents using Jakarta EE. In your agent code you very
likely will be using LLMs, so we provide a very simple facade. Implementations will likely use Spring
AI or LangChain4j under the hood, and the facade also lets you reach those directly when you need to.
The agent workflow
An agent is a CDI bean. Its workflow is a sequence of annotated methods, and domain objects flow
between them through the workflow context.
@TriggerA CDI event starts the workflow
@DecisionDecide whether and how to proceed
@ActionCarry out a step
@OutcomeMark the end of the workflow
@HandleException handles failures arising in any phase.
| Type | Purpose |
@Agent | Declares an agent class. Scope defaults to the workflow. |
@Trigger | Workflow entry point, invoked by CDI events. |
@Decision | Decides whether and how the workflow proceeds. |
@Action | A step within the workflow. |
@Outcome | Terminal step; marks the end of the workflow. |
@HandleException | Exception handler within the workflow. |
@WorkflowScoped | CDI normal scope, one context per workflow execution. |
LargeLanguageModel | Injectable LLM facade with automatic type conversion. |
Result | Built-in record returning a boolean plus detail from a decision. |
An agent, annotated
A fraud detection agent. It does not block a transaction — it marks it suspect and sends
notifications.
/*
* Simple agent for bank fraud detection.
* Doesn't actually block a transaction but marks it suspect and sends notifications.
*/
// Infers agent type and name by default.
// Default scope is agent workflow, but agents can have application scope.
// Just a CDI bean annotated with @Agent.
@Agent
public class FraudDetectionAgent {
// Injects default LLM in the implementation, but can be configured to inject specific ones.
@Inject private LargeLanguageModel model;
// Regular CDI features just work.
@Inject private EntityManager entityManager;
// Initiates the agent workflow. For this initial release, the workflow can only be triggered by
// CDI events.
// In the future, there could be many other types of triggers such as Jakarta Messaging,
// REST POST, or direct invocation from a programmatic life cycle API.
@Trigger
// Return type can be void or a domain object stored in the workflow and accessible in
// the context.
// Parameters are automatically added to the workflow context.
private void handleTransaction(@Valid BankTransaction transaction) {
// Simple check to see if this is a type of transaction that makes sense to check for
// fraud detection.
// Could add a bit more data, likely looked up from a database, and return an enhanced
// version of the transaction or return another domain object entirely.
}
// Can return boolean, a built-in Result record type, or any domain object.
// In this initial release, workflows will automatically end with a negative result.
// In subsequent releases, more robust decision flows should be possible, either with
// annotations/EL and/or the programmatic workflow API.
@Decision
private Result checkFraud(BankTransaction transaction) {
/*
* One of the value propositions of the LLM facade is automatic type conversion in Java,
* both for parameters and return types.
*
* If nothing is specified, it's all strings.
* Probably only JSON and string are supported initially for conversion.
* Queries can be parameterized similar to Jakarta Persistence.
*/
String output = model.query(
"Is this a fraudulent transaction? If so, how serious is it?", transaction);
boolean fraud = isFraud(output); // Does some simple custom text parsing.
Fraud details = null;
if (fraud) {
details = getFraudDetails(output); // Does some simple custom text parsing,
// possibly involving database queries.
}
return new Result(fraud, details);
}
// Only one action here, but there could be multiple actions and/or decisions in sequence.
// In the initial version, it's just one linear flow.
// In subsequent releases, the workflow API can define complex flows, including
// pre-conditions for actions defined via annotation/EL.
@Action
// Notice that we are automatically injecting domain objects from the workflow context.
private void handleFraud(Fraud fraud, BankTransaction transaction) {
/*
* IMPORTANT FUNDAMENTAL CONCEPT:
* This is an example of hard-coded logic, which would still be possible if desired.
*
* The power of a programmatic/structured workflow, instead, is that this could change
* entirely at runtime, driven by further LLM queries.
* Even for simple, static workflows, the API helps developers think through how agents
* operate fundamentally - introducing a common vocabulary/patterns.
*
* Dynamically altered workflows could possibly be serialized into persistent storage.
*/
if (fraud.isSerious()) {
alertBankSecurity(fraud);
}
Customer customer = getCustomer(transaction);
alertCustomer(fraud, transaction, customer);
}
// In this initial release, outcomes are essentially the same as actions, but specifically
// mark the end of the workflow.
// In subsequent releases, outcomes can do more powerful things such as pass a domain
// object to a subsequent workflow or agent.
// This is probably also where it best makes sense to dynamically alter a workflow using
// a programmatic API.
@Outcome
private void markTransaction(BankTransaction transaction) {
// Mark a transaction suspect, probably in the database.
}
}
Get it
<dependency>
<groupId>jakarta.agentic-ai</groupId>
<artifactId>jakarta.agentic-ai-api</artifactId>
<version>1.0.0-M1</version>
<scope>provided</scope>
</dependency>
Requirements
- Java SE 17 or higher
- Jakarta EE 10 or higher
The project aims for the broadest industry consensus possible, engaging subject matter experts and
API consumers from within the Java and Jakarta EE ecosystem as well as outside it. Version 1.0 is
intentionally minimal, and we aim to iterate quickly based on evolving industry knowledge and user
feedback.
Standalone specification
The project does not initially seek inclusion into the Jakarta EE Platform or any profile. Rather, it
provides a usable standalone API under the Jakarta EE umbrella that vendors may choose to adopt. In
the future it may make sense to define a Jakarta EE profile for AI in general, to which this project
could be added.