Skip to content
Skip to content
All posts
Language
ENDE

Jakarta Agentic AI: Four Annotations, and Even Copilot Gets It

with Luís Neto

Luís Neto, committer on Jakarta Agentic AI and author of its Payara Micro integration, guided me while GitHub Copilot added a reviewer agent to a small CFP app. The spec boils down to four annotations. It's so compact that Copilot built a clean agent from the spec URL alone. And it isn't another LLM client: it's a workflow layer, closer to Embabel and LangGraph4j than to Spring AI or LangChain4j.

Published: October 28, 2026Reading time: 6 min read
Jakarta Agentic AI: Four Annotations, and Even Copilot Gets It

YouTube

Jakarta Agentic AI: Four Annotations, and Even Copilot Gets It

Load YouTube video

This video is embedded from YouTube and will only be loaded after your consent. When loading it, personal data may be transmitted to YouTube or Google and cookies may be set.

Open on YouTube

More details are available in the privacy policy.

Project Source

Working Repository

Explore prompts, instructions, and examples used in the live modernization workflow.

Open repository
Session Timeline

Jakarta Agentic AI fits on one index card. Four annotations, a few rules about order, done. I handed the spec URL to GitHub Copilot, and it built a working reviewer agent that Luís Neto, one of the spec's committers, barely had to correct.

Luís Neto

Co-Speaker

Luís Neto

Java Software Engineer at Azul

Luís lives in Brazil and has written Java since 2004. He came to Azul with Payara, is a committer on Jakarta Agentic AI and wrote the integration that ships the spec in Payara Micro.

Not another LLM client

If you're shopping for a Java AI framework, put this one on the right shelf. I asked Luís whether it compares to the annotations in Spring AI or LangChain4j, at 11:23. He said it works on another level and is closer to Embabel.

In the Jakarta Agentic AI, you are creating agents that are going to run in a workflow, in our case, based in CDI events.

— Luís Neto, Committer, Jakarta Agentic AI

Spring AI and LangChain4j sit close to the LLM call. Jakarta Agentic AI bundles calls into steps and chains them. That's what I know from LangGraph4j. The model itself is just a LargeLanguageModel facade you inject into whichever step needs it.

It's a specification, not a framework. Reza Rahman came up with the idea and invited Luís and other Payara people he knew from MicroProfile. The spec sits outside the Jakarta umbrella and doesn't follow its release schedule. Milestone 1 is out. Luís expects the first official version maybe next month. Payara Micro is the first implementation; Luís wrote that integration himself in payara/Payara#8386.

Four strokes

Think of an agent as a four-stroke engine. Every run goes through the same strokes in the same order, and there are no hidden parts. Luís walked through them from 18:07, one branch per step in his fork.

100%
false / null: skip straight to the outcomeStroke 1@TriggerCDI event fired, exactly oneStroke 2@Decisionchecks, can stop the runStroke 3@Actiondoes work, result passed onStroke 4@Outcomereceives the last resulttrue / object@OnExceptionany step fails: the most specific handler winszero or many decisions and actions,run by order() or source order
  • @Trigger starts the run. Your code fires a CDI event, Payara catches it. In version 1 there is exactly one trigger, and it's required.
  • @Decision checks something. Returning true or an object continues. Returning false or null skips straight to the outcome.
  • @Action does the work. Each action gets the previous action's result.
  • @Outcome receives the last result. In the demo it stored the review so the REST resource could return it.

There can be zero or many decisions and actions. They run by an order attribute, or in source order without one. Failures go to @OnException methods, and the handler for the most specific exception type wins.

That's the whole spec you need to read code. I called it not complicated at all on stream. I still think so.

Copilot read the manual

The demo app was a call for papers for a made-up "JCON Brazil 2030", running Payara Micro and Ollama in Docker Compose. Requesting a review only said the reviewer agent didn't exist yet. Luís suggested the prompt at 08:21: give Copilot the spec and ask for an agent that checks the scope, then reviews. I pasted the spec URL he dropped in the chat.

It worked. Copilot produced a clean agent for a brand-new standard from the spec alone. Luís's own version, written with Claude Code, looked much the same. Both passed the LLM in as a method parameter, where Luís would inject it as a field. It still works.

The interesting difference was the shape. Copilot built two decisions and no action: one for scope, one for quality, accepting at 7 out of 10. Luís, at 36:57, called it possible, not wrong. For him, though, the review is an action.

The action is something you do, but it's not the verification. The decision is a verification.

— Luís Neto, Committer, Jakarta Agentic AI

I didn't get the difference at first. We boiled it down to one rule: a decision can end the workflow, an action can't. If your agent should always produce a score, that's an action. If a bad score should stop everything, Copilot's version is fine.

A cake for JCON Brazil

After a rebuild the review ran, and the logs showed both decisions. Then we tested the scope check at 40:25. "Baking a cake" live on stage got accepted, explained as a process that illustrates principles. "How to properly play soccer" got rejected. Luís joked that baking a cake might be closer to programming than soccer.

That's the local model, not the spec. Swapping in a paid model is a few lines in the MicroProfile config: provider, model, API key. Luís put it plainly: then you spend your money.

The exception handling held up under a real failure. At 44:26 we stopped the Ollama container. The general handler Copilot had written returned a readable error. I added a second handler for the spec's LLMException, stopped Ollama again, and the more specific handler fired.

Where version 1 stops

Simple has a price. A decision returning false quietly skips every action. I'm not calling that bad, but I prefer handling such things in code over an invisible workflow you just have to know. Luís said the team kept version 1 simple on purpose and welcomes new contributors.

There's no way around the annotations for now; the implementation finds the methods by reflection. Reza took inspiration from Jakarta Batch, and Embabel uses similar annotations. My problem with annotations is that you have to know them. Here that's four, so it's a small problem.

Each fired event gets its own thread, so one endpoint serves many users. Agents are fully independent today. To chain two, you fire the next event in your own code. Luís named a more flexible workflow for version 2, and MCP and agent-to-agent communication maybe in version 3 or 4.

Final thought

The spec is small enough to learn from four annotations. It's small enough that a coding agent learns it from the spec URL. Luís had an explanation:

The agents are very good to read the specifications because the specifications are written in a well-formatted way.

— Luís Neto, Committer, Jakarta Agentic AI

If you're choosing a Java AI stack, compare Jakarta Agentic AI with LangGraph4j and Embabel, not with Spring AI or LangChain4j. It's a workflow layer on CDI. If you're already on a Jakarta EE runtime, that may be the deciding point. Our example was too simple to push it. Version 2 deserves a harder one, and Luís offered to come back for it.

Comments

Load comments from GitHub optionally

The comment section is provided via Giscus and GitHub Discussions. It will only be loaded after your explicit consent. When loading it, personal data such as your IP address and technical metadata may be transmitted to GitHub, and cookies or similar technologies may be set.

Please confirm first before loading the comment section.

More details are available in the privacy policy.