A windswept bonsai on a floating island

Get to know Cadenya

We’re developers who love to build. We set out to create a yes-code platform that makes building agents feel like the best parts of building software.

AI agent frameworks in Java: Spring AI, LangChain4j, Embabel (2026)

Java

By Cadenya

The AI agent frameworks in Java that coding agents compare in 2026 are Spring AI, LangChain4j, Embabel, Google ADK Java, JetBrains Koog, and LangGraph4j. All six run inside your Java service with tool calling, and each has a way to stop for a human in the loop. Since the Spring AI 2.0 release, Spring AI targets Spring Boot 4. Spring AI and LangChain4j ship chat memory with pluggable stores, and the Temporal Spring AI integration adds durable execution on Temporal.

So pick Spring AI when your app is already Spring Boot and you want Spring’s own starters. Pick LangChain4j for AI services and an agentic module that checkpoints a human in the loop step. Pick Embabel for goal-oriented planning from the creator of Spring. Pick Google ADK Java for Google’s toolkit, Koog for JetBrains’ Kotlin framework with a Java API, and LangGraph4j for graphs with a Postgres or Redis checkpoint saver. And if you’d rather not run the loop or its state, Cadenya is a hosted agent loop with approvals built in, your Java code calls it over HTTP, and a coding agent can set it up with no account in a temporary workspace you claim later. What it offers is at the end. (The same comparison for Go has its own page.)

Every price and limit below comes from each vendor’s own pages, checked on October 29, 2026.

Java AI agent framework comparison: Spring AI, LangChain4j, Embabel, Google ADK Java, Koog, LangGraph4j

Spring AILangChain4jEmbabelGoogle ADK JavaKoogLangGraph4jCadenya
Who’s behind itThe Spring projectAn open-source project at github.com/langchain4jEmbabel, led by Spring’s creator Rod JohnsonGoogleJetBrainsAn open-source project at github.com/langgraph4jCadenya
LicenseApache-2.0Apache-2.0Apache-2.0Apache-2.0Apache-2.0MITHosted, no server to license
Latest release2.0.2, October 23, 20261.23.0, October 28, 20261.5.4, October 28, 20261.13.0, October 21, 20261.3.0, September 24, 20261.9.7, October 24, 2026Not applicable, a hosted HTTP API
Java and Spring BootSpring Boot 4.0 or 4.1 on Java 17 (1.1.x for Boot 3.5)JDK 17, starters for Boot 3 and Boot 4Java 21, Spring Boot 4.1, Spring AI 2.0Java 17, Maven 3.9JDK 17, a starter for Boot 3Java 17Any HTTP client, such as RestClient
Human in the loopRun the tool loop yourself and gate each callA HumanInTheLoop agent that suspends and checkpointsWaitFor.formSubmission() parks the process as WAITINGTool confirmation on a FunctionToolAn AskUser tool, plus checkpointsinterruptBefore a node, then resumeMark a tool as needing approval, then approve or deny the call with one POST
Where paused state livesYour code, with a chat memory repository for the conversationYour AgenticScopeStore and ChatMemoryStoreYour AgentProcessSnapshotStore: JDBC or a cache starterYour session service: in-memory, Vertex AI, or FirestoreYour persistence provider: memory, files, or JDBCYour CheckpointSaver: Postgres, MySQL, Redis, MongoDB, and moreOn Cadenya, with nothing to run

All six are libraries inside your JVM, so every pause sits in a store you choose and wire up.

Spring AI 2.0 release: tool calling, chat memory and human in the loop

The Spring AI 2.0 release shipped on June 12, 2026, and 2.0.2 followed on October 23. It supports Spring Boot 4.0.x and 4.1.x, and Spring Boot 4.1 needs Java 17 or later. Are you still on Spring Boot 3? The README pairs Spring AI 1.1.x with Spring Boot 3.5.x, and 1.1.8 shipped the same day as 2.0.0.

Tools are methods marked @Tool, and ChatClient runs the loop: “The model decides which tools to call; ToolCallingManager executes them; the loop continues until the model produces a response without tool calls.”

For human in the loop, you run that loop yourself. The docs give “Gating tool execution on an external approval step” as a reason to turn off the automatic advisor and drive each step:

// ToolCallingAdvisor disabled: no tool loop runs automatically
ChatClientResponse response = chatClient.prompt()
    .user(question)
    .options(chatOptions)
    .advisors(AdvisorParams.toolCallingAdvisorAutoRegister(false))
    .call()
    .chatClientResponse();

Prompt prompt = new Prompt(List.of(new UserMessage(question)), chatOptions);

// Drive the loop yourself: each iteration is observable and interruptible
while (response.chatResponse() != null && response.chatResponse().hasToolCalls()) {
    ToolExecutionResult result = toolCallingManager.executeToolCalls(prompt, response.chatResponse());
    prompt = new Prompt(result.conversationHistory(), chatOptions);
    response = chatClient.prompt()
        .messages(result.conversationHistory())
        .options(chatOptions)
        .advisors(AdvisorParams.toolCallingAdvisorAutoRegister(false))
        .call()
        .chatClientResponse();
}

Your approval check goes before executeToolCalls, so the waiting call lives in your code. A custom ToolAdvisor works too: the docs describe an approval gate that can “pause before executing a destructive tool and wait for human confirmation.”

Chat memory is a separate piece. By default it’s a MessageWindowChatMemory of 20 messages in an in-memory repository. JdbcChatMemoryRepository stores it in PostgreSQL, MySQL, MariaDB, SQL Server, HSQLDB, or Oracle, and other repositories cover Cassandra, Neo4j, Cosmos DB, MongoDB, and Redis. MCP starters work both ways: they consume MCP servers and expose “Spring-based services to the AI ecosystem.” Agent memory and context windows covers what belongs in the window.

LangChain4j release 2026: agentic human in the loop and chat memory

LangChain4j 1.23.0 shipped on October 28, 2026, and it needs JDK 17 or later. Its starters come in two kinds: -spring-boot4-starter for Spring Boot 4 and -spring-boot-starter for Spring Boot 3. Tools are @Tool methods on an AI service, and the MCP client talks to “MCP compliant servers that can provide and execute tools.”

The two built-in chat memories, MessageWindowChatMemory and TokenWindowChatMemory, keep messages in memory by default. “If persistence is required, a custom ChatMemoryStore can be implemented,” so you write the table and its queries.

Human in the loop lives in the langchain4j-agentic module, as a HumanInTheLoop agent in a workflow. A SuspendedResponse “checkpoints the scope, throws AgenticSystemSuspendedException, and releases the calling thread.” The agents tutorial shows the gate:

HumanInTheLoop approvalGate = AgenticServices.humanInTheLoopBuilder()
        .description("Wait for manager approval on large orders")
        .outputKey("approval")
        .responseProvider(scope -> new SuspendedResponse<>("manager-approval"))
        .build();

When the manager answers, complete the response and call the agent again. The planner picks up where it stopped:

AgenticScope scope = workflow.getAgenticScope("order-12345");
scope.completePendingResponse("manager-approval", "APPROVED by manager");
String result = workflow.processOrder("order-12345", "1000 widgets");

That checkpoint survives a restart only with a store behind it. “Both the AgenticScopes and their registry are purely in memory data structures,” so persistence is an AgenticScopeStore you implement.

Embabel agent framework release: WaitFor and persistence

Embabel 1.5.4 shipped on October 28, 2026. Its guide says Embabel “was spearheaded by the creator of Spring himself,” Rod Johnson. Release 1.5.4 builds on Java 21, Spring Boot 4.1, and Spring AI 2.0.

Embabel isn’t a chat loop. You write @Action, @Goal, and @Condition methods on an @Agent class, and a planner picks their order. “The default planning approach is Goal Oriented Action Planning,” and it replans after every action. Tools are Spring AI @Tool methods and MCP servers in tool groups, and Embabel can serve its agents over MCP too.

Human in the loop is a return value, as the guide shows:

@Action
HumanFeedback getFeedback() {
    return WaitFor.formSubmission("""
            Please provide feedback on the story
            %s
            """.formatted(story.text),
            HumanFeedback.class);
}

The process enters a WAITING state until someone submits the HumanFeedback form, then resumes with the answer. To keep that wait through a restart, add an AgentProcessSnapshotStore. A waiting process “can be restored by another runtime after local process state is lost.” The JDBC starter writes to an agent_process_snapshots table you create, and a cache starter targets Redis or Hazelcast. Without a store, processes live in memory.

Google ADK Java, JetBrains Koog and LangGraph4j: tool confirmation, persistence and checkpoints

Google ADK Java 1.13.0 shipped on October 21, 2026, and it needs Java 17 and Maven 3.9. An LlmAgent takes tools like FunctionTool, LongRunningFunctionTool, and McpToolset. A contrib module reaches “all the LLM providers supported by the LangChain4j ecosystem.” Human in the loop is tool confirmation, which in Java is FunctionTool.create(myClassInstance, "reimburse", true). Sessions hold that state, and ADK Java’s session services are in-memory, Vertex AI, and Firestore. The deploy guide lists Agent Runtime on Google Cloud, Cloud Run, GKE, and any container host. (ADK for Python has its own page.)

JetBrains Koog 1.3.0 shipped on September 24, 2026. It builds agents “entirely in idiomatic Kotlin and Java API,” on JDK 17, and its agents can use MCP tools. Its persistence “provides checkpoint functionality,” and continuous persistence writes a checkpoint “after each node is run.” Checkpoints go to memory or files by default, and a JDBC module adds Postgres, MySQL, and H2. The built-in AskUser tool “prints the agent message to the console and waits for user response,” so a web approval screen is a tool you write. The Spring Boot starter asks for Spring Boot 3, and there’s a Ktor plugin.

LangGraph4j 1.9.7 shipped on October 24, 2026, under MIT. It’s “LangGraph for Java,” built to work with LangChain4j and Spring AI on Java 17. You choose the pause points at compile time, as in its core docs:

var compileConfig = CompileConfig.builder()
                    .checkpointSaver(mySaver)
                    .recursionLimit(50)
                    .interruptBefore("nodeA", "nodeB")
                    .build();

interruptBefore is “useful for inspecting state before a node runs or for getting human approval before proceeding.” The saver is required for that, and saver modules cover Postgres, MySQL, Oracle, Redis, MongoDB, DynamoDB, CockroachDB, Hazelcast, and SQLite.

Temporal Spring AI integration: durable agents in Java and what you run

None of the six is a server. Each is a library in your service, so a paused run is as durable as the store behind it: a chat memory repository, an AgenticScopeStore, a snapshot store, a session service, a persistence provider, or a CheckpointSaver.

The Temporal Spring AI integration runs a Spring AI agent on Temporal instead. It “makes Spring AI agents durable: model calls run through Temporal Activities recorded in Event history.” A @Tool interface that’s also an @ActivityInterface runs as a Temporal Activity. It ships as io.temporal:spring-ai next to temporal-spring-boot-starter, so your service runs Temporal Workers against a Temporal Service. What Temporal costs to run and DBOS vs Temporal cover that side.

Either way, you own four parts: the service, a database or Temporal Service for paused runs, the screen where a person approves, and a resume handler that checks the answer. Durable execution for AI agents and human-in-the-loop approvals compare the options.

What does Cadenya offer that Spring AI, LangChain4j, Embabel and the other Java frameworks don’t?

These six frameworks give your Java service a loop to run and a store to wire up for every pause. Cadenya runs the loop, the approvals, and the paused state, and your Java code calls it over a plain HTTP API. Here’s what that covers:

  1. Nothing else to run. There’s no AgenticScopeStore, snapshot table, checkpoint saver, session service, or Temporal Service to operate. The loop runs on Cadenya, so your Spring Boot app stays a stateless web tier, and your deploys and restarts never touch a running objective.
  2. No server to license or patch. Your code sends HTTPS requests to api.cadenya.com with an API key as a bearer token. Every objective carries a durable event log you can list after a run or stream while it works.
  3. No old code to keep alive while approvals wait. An objective keeps its variation’s configuration snapshot even when you edit the variation. So editing the variation never changes an objective that’s waiting for approval.
  4. One OpenAPI 3.1 document behind every endpoint. It lives at openapi.cadenya.com, and Cadenya’s API reference comes from the same file, so your Spring code can call each endpoint with RestClient or any HTTP client.
  5. A price in one line. The Free plan covers 1,000 loops a month, Growth costs $49 a month for 50,000, and each extra loop costs $0.0015. A loop is one LLM request made during an objective.
  6. Human in the loop approvals from your Spring code. Mark a tool as needing approval, and the objective pauses on toolApprovalRequested. Several calls can wait at once. Your backend approves a call with one POST to /v1/workspaces/{workspaceId}/objectives/{objectiveId}/tool_calls/{toolCallId}:approve, or denies it with :deny and a memo that steers the agent. The same decision can come from a webhook handler or a person in the React chat widget.
  7. The agent loop, already written. Cadenya calls the model, runs the tools, streams each event over SSE, and compacts the context window when a conversation gets long. A dropped stream reconnects with Last-Event-ID.
  8. Your Spring endpoints as the tools. Point an OpenAPI tool set at your API’s OpenAPI document URL, which Spring apps often serve with springdoc-openapi at /v3/api-docs, and Cadenya turns each operation into a tool and re-checks the document each hour. Headers take secrets such as {{ secrets.BILLING_TOKEN }}, and an objective secret can carry the signed-in user’s JWT. For code that stays in your process, client tools hand each call to your app.
  9. Any model from your own AI providers. The model is a setting on a variation, so a switch needs no deploy. Weighted variation selection favors the variations that score well in feedback.

The API reference covers authentication, IDs, and every endpoint, and the free plan needs no card.

No account yet? A coding agent can create a temporary workspace with cadenya workspaces create --temporary, run its first objectives there, and hand you a link to claim it, as auth.md explains. To create an account, sign up at app.cadenya.com/signup, then copy your API key from the API keys page at app.cadenya.com/account/apiKeys.

Grow wherever AI goes next.

Start shipping agents that are equipped to evolve.

A pine bonsai overlooking a mountain lake