Java is Coming for Python’s Lunch - The Rise of JVM AI Agents
The full text and code of the slides, one page per section.
- Java is Coming for Python’s Lunch - The Rise of JVM AI Agents
- Agents in production need what Java has delivered for decades
- Why Python was first
- Why Python was first
- AI started in the lab, and the lab spoke Python
- Researchers joined companies and brought Python with them
- Python was the glue, the heavy lifting always ran in C and C++
- LLMs moved the heavy lifting into the datacenter
- What travels over the wire is JSON and JSON Schema
- An agent is mostly concurrent network IO, and the JVM is built for it
- Jackson turns a record into the schema and the answer back into a record
- The context an agent needs already lives in JVM systems
- Put the agent inside the system, not next to it
- A production agent needs the same safety net as any other service
- The big JVM vendors are building best-in-class agent frameworks
- Most AI projects fail because they automate the wrong thing
- The demo
- The demo
- A trip is a plain JPA aggregate with its bookings
- The rules are sentences written for people, not for code
- Every agent reads the same facts through one read-only service
- Three agents, one contract
- Choosing the framework is one request parameter
- Every reviewer drafts, a judge audits, a rejection goes back
- Spring AI
- Spring AI
- One builder call configures the reviewer once
- A tool is a Spring bean method with a description
- The request reads like the question and returns a Kotlin type
- Every call passes through a chain of advisors before it reaches the model
- An advisor wraps every call like a servlet filter
- Every review shows up as a trace without extra code
- Chat memory is one more advisor, the history lives in a table
- Spring AI already ships a judge: the `FactCheckingEvaluator`
- The judge implements Spring AI's own `Evaluator` contract
- The whole agent loop is a Kotlin `repeat`
- Embabel
- Embabel
- Embabel plans like a game AI: actions, conditions, goals
- A* walks the cheapest chain of actions to the goal and replans when the world changes
- The caller names an input and a goal type, never the steps
- An `@Action` can be plain code that never calls a model
- A model-backed action asks for an object, not a string
- Tools are granted per model call, not per agent
- A domain object can bring its own tools
- A side effect waits for a type only a human can produce
- The memory is the typed blackboard, not a growing chat transcript
- Spring AI traces the model calls, Embabel adds the plan around them
- The judge declares both outcomes, conditions decide which one is true
- Two goals finish the review, the true condition picks one
- Nobody wrote this order down, the planner derived it from the types
- Shared actions live in a component, not inside one agent
- A whole agent becomes one step of the next agent
- Every new agent needs fewer new actions
- Koog
- Koog
- The same review becomes a graph of nodes and edges
- Tools live in a `ToolRegistry` the agent is built with
- Every node is a typed value declared up front
- Four edges are the whole tool loop
- Koog ships the whole tool loop as one `subgraphWithTask`
- The judge is a `subgraphWithVerification` that never sees the reviewer's chat
- The revision loop stays a plain node and two edges
- Two library subgraphs and one node of mine are the whole agent
- Koog runs on the same Spring AI `ChatModel`
- Spring AI traces the model calls, Koog adds the graph around them
- One `install` sends the whole graph to Langfuse
- Chat memory is a feature I install, compression is a node I place
- Every tool can register its undo, a rollback runs them backwards
- The graph is one strategy, Koog lets every agent pick its own