How to Run Cyclic AI Agents in Java
Most tutorials on multi-agent systems with LLMs are written in Python. If you're writing a backend in Java and want to build something more complex than a linear chain of calls, you previously had to invent your own finite state machines or hack together branching on top of LangChain4j.
In the Python ecosystem, LangGraph from the LangChain team has become the standard for such tasks. It solves a simple problem: real conversational agents almost never work in a straight line (DAG). An agent needs to call a tool, look at an error, ask the user for clarification, or restart a subtask. These are cycles.
The LangGraph4j project brings this concept to the Java world. The library works well with Spring AI and LangChain4j, supports state persistence to real databases, and provides the ability to build complex execution graphs.
What's Inside and How It Works
At the core of the library is the StateGraph class. You describe a graph as a set of nodes, edges, and shared state that is passed between steps.
Each node receives the current state, executes a piece of logic (for example, calls an LLM or accesses a database) and returns a dictionary with updates. These updates are merged with the shared state through so-called reducers. For example, new messages can be appended to the end of a list, while a status flag can simply be overwritten.
Basic Example
You need Java 17 or newer to work with this. Add the dependency:
<dependency>
<groupId>org.bsc.langgraph4j</groupId>
<artifactId>langgraph4j-core</artifactId>
<version>1.8.24</version>
</dependency>
Let's describe the simplest graph with two nodes and shared state for messages:
import org.bsc.langgraph4j.StateGraph;
import org.bsc.langgraph4j.state.AgentState;
import org.bsc.langgraph4j.state.Channels;
import org.bsc.langgraph4j.state.Channel;
import static org.bsc.langgraph4j.action.AsyncNodeAction.node_async;
import static org.bsc.langgraph4j.StateGraph.START;
import static org.bsc.langgraph4j.StateGraph.END;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
// 1. Описываем структуру состояния
class SimpleState extends AgentState {
public static final String MESSAGES_KEY = "messages";
public static final Map<String, Channel<?>> SCHEMA = Map.of(
MESSAGES_KEY, Channels.appender(ArrayList::new)
);
public SimpleState(Map<String, Object> initData) {
super(initData);
}
public List<String> messages() {
return this.<List<String>>value("messages").orElse(List.of());
}
}
public class SimpleApp {
public static void main(String[] args) throws Exception {
// 2. Собираем граф
var graph = new StateGraph<>(SimpleState.SCHEMA, SimpleState::new)
.addNode("greeter", node_async(state ->
Map.of(SimpleState.MESSAGES_KEY, "Привет от первого узла!")))
.addNode("responder", node_async(state ->
Map.of(SimpleState.MESSAGES_KEY, "Ответ получен.")))
.addEdge(START, "greeter")
.addEdge("greeter", "responder")
.addEdge("responder", END)
.compile();
// 3. Запускаем стриминг шагов
for (var step : graph.stream(Map.of(SimpleState.MESSAGES_KEY, "Старт"))) {
System.out.println("Шаг выполнен: " + step);
}
}
}
Here, the graph returns an async generator. You get the graph state after each node executes, which is convenient for streaming progress updates to the client in real time.
What Makes This Project Interesting in Practice
1. Conditional Transitions and Cycles
Linear chains are easy to build with regular code. The power of graphs reveals itself when you add conditional edges. You attach a function to an edge that looks at the result of the LLM's work and decides where to go next: to a tool-calling node, to regeneration, or to completing the dialogue.
2. State Persistence and Time Travel
If an agent communicates with a user across multiple iterations or a process takes hours, keeping everything in JVM memory isn't feasible.
LangGraph4j includes a checkpoint module. Ready-made adapters are available for PostgreSQL, Redis, MySQL, SQLite, OracleDB, Hazelcast, and DynamoDB. You can:
- Save state after each step;
- Resume execution from a specific point after a service restart;
- Implement Human-in-the-loop, where the graph waits for human confirmation of an action and then continues;
- "Rewind" the graph back to a previous state snapshot.
3. Native Integration with Spring AI and LangChain4j
You won't need to rewrite model calls for a separate API. The repository already includes integration modules.
Here's how to run a ReAct agent with LangGraph4j and LangChain4j:
var model = OllamaChatModel.builder()
.modelName("qwen2.5:7b")
.baseUrl("http://localhost:11434")
.build();
var agent = AgentExecutor.builder()
.chatModel(model)
.toolsFromObject(new TestTool())
.build()
.compile();
for (var item : agent.stream(Map.of("messages", "Проверь статус и верни число потоков"))) {
System.out.println(item);
}
For Spring AI, the syntax is practically identical, using annotations and Spring beans.
4. LangGraph Studio and Visualization
Debugging complex graphs without visibility is difficult. LangGraph4j can generate graph diagrams in PlantUML and Mermaid formats.
The authors also built a web interface called LangGraph4j Studio, which you can embed directly into your Spring Boot, Quarkus, or Jetty application to visually run and inspect graph nodes in the browser.
Caveats
The library is actively developing (version 1.8.x at the time of this review), so some rare APIs may change between minor releases.
Some tutorials in the examples folder are formatted as Jupyter notebooks for Java. To run these examples, the authors require Java 22, even though the library core works fine on stable Java 17+.
Who Is This For
If you're building enterprise services on Spring Boot or Quarkus and want to implement agentic scenarios (technical support, CI/CD automation, multi-stage document processing), LangGraph4j removes the need to write your own task scheduler for LLMs.
The library provides a mature architectural foundation without forcing the team to switch to a Python stack just for agent orchestration. You can start experimenting with a local model via Ollama and a simple graph of two or three nodes.
Proyectos relacionados