LangChain4j Agentic Framework provides a comprehensive Java library for building multi-agent AI systems with support for workflow orchestration, supervisor agents, planning-based execution, declarative configuration, agent-to-agent communication, and human-in-the-loop workflows.
Autonomous LLM-based orchestration that dynamically selects and coordinates sub-agents to accomplish complex tasks.
Supervisor agents enable:
static SupervisorAgentService<SupervisorAgent> supervisorBuilder();
static <T> SupervisorAgentService<T> supervisorBuilder(Class<T> agentServiceClass);Quick Start:
SupervisorAgent supervisor = AgenticServices.supervisorBuilder()
.chatModel(chatModel)
.subAgents(researchAgent, analysisAgent, writingAgent)
.maxAgentsInvocations(10)
.build();
Object result = supervisor.invoke("Create a comprehensive report on AI trends");SupervisorAgentService<T> chatModel(dev.langchain4j.model.chat.ChatModel chatModel);
SupervisorAgentService<T> subAgents(Object... agents);The ChatModel is used by the supervisor to make autonomous decisions about which agents to invoke.
SupervisorAgentService<T> contextGenerationStrategy(SupervisorContextStrategy strategy);
enum SupervisorContextStrategy {
CHAT_MEMORY, // Use conversation history only
INVOCATIONS, // Use agent invocation history only
FULL // Use both (default)
}Examples:
// Use full context (conversation + invocations)
.contextGenerationStrategy(SupervisorContextStrategy.FULL)
// Use only invocation history
.contextGenerationStrategy(SupervisorContextStrategy.INVOCATIONS)
// Use only conversation history
.contextGenerationStrategy(SupervisorContextStrategy.CHAT_MEMORY)SupervisorAgentService<T> responseStrategy(SupervisorResponseStrategy strategy);
enum SupervisorResponseStrategy {
LAST, // Return last agent's response
SUMMARY // Generate comprehensive summary
}Examples:
// Return last agent's response
.responseStrategy(SupervisorResponseStrategy.LAST)
// Generate summary of all agent outputs
.responseStrategy(SupervisorResponseStrategy.SUMMARY)SupervisorAgentService<T> maxAgentsInvocations(int maxInvocations);Control maximum number of agent invocations to prevent infinite loops:
.maxAgentsInvocations(15) // Allow up to 15 agent invocationsSupervisorAgentService<T> requestGenerator(Function<AgenticScope, String> requestGenerator);Customize the request sent to the supervisor LLM:
.requestGenerator(scope -> {
String userInput = (String) scope.readState("user_input");
String priority = (String) scope.readState("priority", "normal");
return String.format(
"Task: %s (Priority: %s). Coordinate agents to complete efficiently.",
userInput,
priority
);
})SupervisorAgentService<T> supervisorContext(String context);Provide additional context to guide the supervisor's decision-making:
.supervisorContext(
"You are an expert project manager coordinating specialists. " +
"Always start with research agent to gather information. " +
"Only invoke writing agent after analysis is complete. " +
"Aim to complete tasks in minimum number of steps."
)// Define specialized agents
UntypedAgent researcher = AgenticServices.agentBuilder()
.chatModel(chatModel)
.name("researcher")
.description("Searches and gathers information on topics")
.tools(searchTool)
.outputKey("research_data")
.build();
UntypedAgent analyzer = AgenticServices.agentBuilder()
.chatModel(chatModel)
.name("analyzer")
.description("Analyzes data and identifies patterns")
.outputKey("analysis")
.build();
UntypedAgent validator = AgenticServices.agentBuilder()
.chatModel(chatModel)
.name("validator")
.description("Validates findings for accuracy")
.outputKey("validation")
.build();
// Create supervisor
SupervisorAgent supervisor = AgenticServices.supervisorBuilder()
.chatModel(chatModel)
.name("research-supervisor")
.description("Coordinates research, analysis, and validation")
.subAgents(researcher, analyzer, validator)
.maxAgentsInvocations(10)
.contextGenerationStrategy(SupervisorContextStrategy.FULL)
.responseStrategy(SupervisorResponseStrategy.SUMMARY)
.supervisorContext(
"You coordinate a research team. First gather information, " +
"then analyze it, and finally validate the findings."
)
.build();
// Supervisor autonomously determines agent invocation order
Object result = supervisor.invoke("Research the impact of AI on healthcare");interface CustomerSupportSystem {
@SupervisorAgent(
name = "support-coordinator",
description = "Coordinates specialists to resolve customer issues",
subAgents = {TechnicalAgent.class, BillingAgent.class, ProductAgent.class},
maxAgentsInvocations = 15,
contextStrategy = SupervisorContextStrategy.FULL,
responseStrategy = SupervisorResponseStrategy.SUMMARY
)
String handleCustomerIssue(String customerQuery);
@ChatModelSupplier
default dev.langchain4j.model.chat.ChatModel chatModel() {
return yourChatModelInstance;
}
@SupervisorRequest
default String generateRequest(AgenticScope scope) {
String query = (String) scope.readState("user_input");
return "Help resolve this customer issue: " + query;
}
}SupervisorAgent supervisor = AgenticServices.supervisorBuilder()
.chatModel(chatModel)
.subAgents(researcher, analyzer, writer)
.output(scope -> {
List<AgentInvocation> invocations = scope.agentInvocations();
return Map.of(
"final_result", scope.readState("final_output"),
"research_data", scope.readState("research_data"),
"analysis", scope.readState("analysis"),
"total_invocations", invocations.size(),
"agents_used", invocations.stream()
.map(AgentInvocation::agentName)
.distinct()
.collect(Collectors.toList())
);
})
.build();Example:
interface ProjectManagementSystem {
@SupervisorAgent(
name = "project-orchestrator",
description = "Manages project tasks by coordinating team agents",
subAgents = {
PlanningAgent.class,
DevelopmentAgent.class,
TestingAgent.class,
DeploymentAgent.class
},
maxAgentsInvocations = 20,
contextStrategy = SupervisorContextStrategy.FULL,
responseStrategy = SupervisorResponseStrategy.SUMMARY
)
String manageProject(String projectDescription);
@ChatModelSupplier
default dev.langchain4j.model.chat.ChatModel getChatModel() {
return chatModelInstance;
}
}SupervisorAgent supervisor = AgenticServices.supervisorBuilder()
.chatModel(chatModel)
.subAgents(agent1, agent2, agent3)
.errorHandler(errorContext -> {
Throwable error = errorContext.error();
AgenticScope scope = errorContext.agenticScope();
System.err.println("Supervisor error: " + error.getMessage());
int invocationCount = scope.agentInvocations().size();
if (invocationCount < 3) {
return new ErrorRecoveryResult("Partial result", true);
} else {
return new ErrorRecoveryResult(null, false);
}
})
.build();Configure chat memory for conversation-aware supervision:
SupervisorAgent supervisor = AgenticServices.supervisorBuilder()
.chatModel(chatModel)
.chatMemoryProvider(chatMemoryProvider)
.subAgents(agent1, agent2, agent3)
.contextGenerationStrategy(SupervisorContextStrategy.FULL)
.build();INVOCATIONS is more efficient than FULL for simple tasksLAST is faster than SUMMARY when you don't need aggregationInstall with Tessl CLI
npx tessl i tessl/maven-dev-langchain4j--langchain4j-agentic@1.11.0docs
declarative
A2AClientAgent
ActivationCondition
Agent
ConditionalAgent
ErrorHandler
ExitCondition
HumanInTheLoop
HumanInTheLoopResponseSupplier
LoopAgent
LoopCounter
Output
ParallelAgent
ParallelExecutor
PlannerAgent
SequenceAgent
SupervisorAgent
SupervisorRequest
quick-start
workflows