A library for building stateful, multi-agents applications with LLMs
Core functionality for building and managing stateful workflow graphs. Supports nodes, edges, conditional routing, and subgraph composition.
Create and configure state graphs with custom state types and serialization.
/**
* Creates a new StateGraph with the specified state factory
* @param stateFactory Factory for creating agent states
*/
StateGraph<State> StateGraph(AgentStateFactory<State> stateFactory);
/**
* Creates a new StateGraph with channels and state serializer
* @param channels State schema defining how state values are updated
* @param stateSerializer Serializer for state objects
*/
StateGraph<State> StateGraph(Map<String, Channel<?>> channels, StateSerializer<State> stateSerializer);
/**
* Creates a new StateGraph with channels and state factory
* @param channels State schema defining how state values are updated
* @param stateFactory Factory for creating agent states
*/
StateGraph<State> StateGraph(Map<String, Channel<?>> channels, AgentStateFactory<State> stateFactory);Usage Example:
import org.bsc.langgraph4j.StateGraph;
import org.bsc.langgraph4j.state.AgentState;
// Simple state class
class MyState extends AgentState {
public MyState(Map<String, Object> initData) {
super(initData);
}
}
// Create state graph with factory
StateGraph<MyState> workflow = new StateGraph<>(MyState::new);
// Or with channels for complex state management
Map<String, Channel<?>> channels = Map.of(
"messages", Channels.appender(ArrayList::new)
);
StateGraph<MyState> workflowWithChannels = new StateGraph<>(channels, MyState::new);Add nodes with various action types and behaviors.
/**
* Adds a node with an asynchronous action
* @param id Unique identifier for the node
* @param action Asynchronous action to execute
* @return This StateGraph for method chaining
* @throws GraphStateException if node ID is invalid or already exists
*/
StateGraph<State> addNode(String id, AsyncNodeAction<State> action);
/**
* Adds a node with a configuration-aware asynchronous action
* @param id Unique identifier for the node
* @param action Configuration-aware asynchronous action
* @return This StateGraph for method chaining
* @throws GraphStateException if node ID is invalid or already exists
*/
StateGraph<State> addNode(String id, AsyncNodeActionWithConfig<State> action);
/**
* Adds a node that behaves as conditional edges
* @param id Unique identifier for the node
* @param action Command action to determine next target node
* @param mappings Mappings of command results to target nodes
* @return This StateGraph for method chaining
* @throws GraphStateException if mappings are empty or node already exists
*/
StateGraph<State> addNode(String id, AsyncCommandAction<State> action, Map<String, String> mappings);
/**
* Adds a compiled subgraph as a node
* @param id Unique identifier for the subgraph node
* @param subGraph Compiled subgraph to execute
* @return This StateGraph for method chaining
* @throws GraphStateException if node ID is invalid or already exists
*/
StateGraph<State> addNode(String id, CompiledGraph<State> subGraph);
/**
* Adds a state graph as a node (compiled during parent compilation)
* @param id Unique identifier for the subgraph node
* @param subGraph State graph to include as subgraph
* @return This StateGraph for method chaining
* @throws GraphStateException if node ID is invalid or already exists
*/
StateGraph<State> addNode(String id, StateGraph<State> subGraph);Usage Examples:
// Simple async node
workflow.addNode("processor", (state) ->
CompletableFuture.completedFuture(Map.of("processed", true))
);
// Configuration-aware node
workflow.addNode("configurable", (state, config) -> {
String threadId = config.threadId().orElse("default");
return CompletableFuture.completedFuture(Map.of("thread", threadId));
});
// Conditional node with routing
workflow.addNode("router",
(state, config) -> {
boolean condition = state.value("ready").orElse(false);
return CompletableFuture.completedFuture(
new Command(condition ? "success" : "failure", Map.of())
);
},
Map.of(
"success", "success_node",
"failure", "failure_node"
)
);
// Subgraph node
StateGraph<MyState> subWorkflow = new StateGraph<>(MyState::new);
// ... configure subWorkflow ...
workflow.addNode("sub_process", subWorkflow);Define routing between nodes with simple and conditional edges.
/**
* Adds a simple edge between two nodes
* @param sourceId Source node identifier
* @param targetId Target node identifier
* @return This StateGraph for method chaining
* @throws GraphStateException if source ID is invalid or edge conflicts
*/
StateGraph<State> addEdge(String sourceId, String targetId);
/**
* Adds conditional edges based on command action results
* @param sourceId Source node identifier
* @param condition Command action to determine routing
* @param mappings Map of command results to target node IDs
* @return This StateGraph for method chaining
* @throws GraphStateException if mappings are empty or edge conflicts
*/
StateGraph<State> addConditionalEdges(String sourceId, AsyncCommandAction<State> condition, Map<String, String> mappings);
/**
* Adds conditional edges using edge action (alternative form)
* @param sourceId Source node identifier
* @param condition Edge action returning target node ID
* @param mappings Map of edge results to target node IDs
* @return This StateGraph for method chaining
* @throws GraphStateException if mappings are empty or edge conflicts
*/
StateGraph<State> addConditionalEdges(String sourceId, AsyncEdgeAction<State> condition, Map<String, String> mappings);Usage Examples:
// Simple sequential edges
workflow.addEdge(StateGraph.START, "first_node");
workflow.addEdge("first_node", "second_node");
workflow.addEdge("second_node", StateGraph.END);
// Conditional routing
workflow.addConditionalEdges("decision_node",
(state, config) -> {
int value = state.<Integer>value("score").orElse(0);
String route = value > 50 ? "high" : "low";
return CompletableFuture.completedFuture(new Command(route, Map.of()));
},
Map.of(
"high", "high_score_handler",
"low", "low_score_handler"
)
);Compile the state graph into an executable form with optional configuration.
/**
* Compiles the state graph into a compiled graph with default configuration
* @return Compiled graph ready for execution
* @throws GraphStateException if graph validation fails
*/
CompiledGraph<State> compile();
/**
* Compiles the state graph with specific configuration
* @param config Compilation configuration
* @return Compiled graph ready for execution
* @throws GraphStateException if graph validation fails
*/
CompiledGraph<State> compile(CompileConfig config);Usage Examples:
// Basic compilation
CompiledGraph<MyState> app = workflow.compile();
// Compilation with configuration
CompileConfig config = CompileConfig.builder()
.checkpointSaver(new MemorySaver())
.interruptBefore("human_review")
.build();
CompiledGraph<MyState> app = workflow.compile(config);Generate diagram representations of the graph structure.
/**
* Generates a graph representation with specified type and title
* @param type Diagram format (PLANTUML or MERMAID)
* @param title Title for the diagram
* @return Graph representation containing diagram code
*/
GraphRepresentation getGraph(GraphRepresentation.Type type, String title);
/**
* Generates a graph representation with conditional edge control
* @param type Diagram format
* @param title Title for the diagram
* @param printConditionalEdges Whether to include conditional edges in diagram
* @return Graph representation containing diagram code
*/
GraphRepresentation getGraph(GraphRepresentation.Type type, String title, boolean printConditionalEdges);Usage Examples:
// Generate PlantUML diagram
GraphRepresentation diagram = workflow.getGraph(
GraphRepresentation.Type.PLANTUML,
"My Workflow"
);
System.out.println(diagram.content());
// Generate Mermaid diagram without conditional edges
GraphRepresentation mermaid = workflow.getGraph(
GraphRepresentation.Type.MERMAID,
"Simplified View",
false
);// Built-in node identifiers
static final String START = "__START__"; // Entry point identifier
static final String END = "__END__"; // Exit point identifierGraph validation occurs during compilation and checks for:
Common Validation Errors:
missingEntryPoint: No edge from START nodeduplicateNodeError: Node ID already existsinvalidNodeIdentifier: Using reserved END as node IDmissingNodeReferencedByEdge: Edge references non-existent nodeedgeMappingIsEmpty: Conditional edge has no mappingsInstall with Tessl CLI
npx tessl i tessl/maven-org-bsc-langgraph4j--langgraph4j-core