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.
Execute agents conditionally based on runtime predicates for dynamic branching and selective execution.
Conditional workflows enable:
static ConditionalAgentService<UntypedAgent> conditionalBuilder();
static <T> ConditionalAgentService<T> conditionalBuilder(Class<T> agentServiceClass);Quick Start:
UntypedAgent conditional = AgenticServices.conditionalBuilder()
.subAgents(
scope -> "premium".equals(scope.readState("user_tier")),
premiumAgent
)
.build();ConditionalAgentService<T> subAgents(Predicate<AgenticScope> condition, Object... agents);
ConditionalAgentService<T> subAgents(String description, Predicate<AgenticScope> condition, Object... agents);
ConditionalAgentService<T> subAgent(Predicate<AgenticScope> condition, AgentExecutor agent);
ConditionalAgentService<T> subAgent(String description, Predicate<AgenticScope> condition, AgentExecutor agent);Single branch:
.subAgents(
scope -> (Boolean) scope.readState("feature_enabled", false),
featureAgent
)Multiple branches (if-else-if):
.subAgents(
"Premium tier check",
scope -> "premium".equals(scope.readState("user_tier")),
premiumAnalyzer
)
.subAgents(
"Standard tier check",
scope -> "standard".equals(scope.readState("user_tier")),
standardAnalyzer
)
.subAgents(
"Basic tier fallback",
scope -> true, // Always execute if previous conditions failed
basicAnalyzer
)ConditionalAgentService<T> fallbackValue(Object fallbackValue);
ConditionalAgentService<T> fallback(Function<AgenticScope, Object> fallbackFunction);Static fallback:
.fallbackValue("Feature not available")Dynamic fallback:
.fallback(scope -> {
String tier = (String) scope.readState("user_tier");
if ("premium".equals(tier)) {
return premiumAgent.invoke(scope);
}
return "Upgrade required";
})true:
false:
interface FeatureFlaggedSystem {
@ConditionalAgent(
name = "experimental-feature",
conditionMethod = "isFeatureEnabled",
fallbackMethod = "legacyImplementation",
subAgents = {ExperimentalFeature.class}
)
String processWithFeature(String input);
default boolean isFeatureEnabled(AgenticScope scope) {
String userId = (String) scope.readState("user_id");
return featureFlagService.isEnabled("new-algorithm", userId);
}
default String legacyImplementation(AgenticScope scope) {
String input = (String) scope.readState("input");
return legacyProcessor.process(input);
}
}UntypedAgent abTest = AgenticServices.conditionalBuilder()
.condition(scope -> {
String userId = (String) scope.readState("user_id");
int bucket = Math.abs(userId.hashCode()) % 100;
return bucket < 50; // 50% in variant A
})
.subAgents(variantA)
.fallback(scope -> variantB.invoke(scope))
.listener(experimentTrackingListener)
.build();interface SecureSystem {
@ConditionalAgent(
name = "admin-operation",
conditionMethod = "hasAdminPermission",
fallbackMethod = "accessDenied",
subAgents = {AdminOperationAgent.class}
)
OperationResult performAdminOperation(String operation);
default boolean hasAdminPermission(AgenticScope scope) {
User user = (User) scope.readState("current_user");
return user != null && user.hasRole("ADMIN");
}
default OperationResult accessDenied(AgenticScope scope) {
return new OperationResult(false, "Access denied: admin role required");
}
}UntypedAgent envConditional = AgenticServices.conditionalBuilder()
.condition(scope -> {
String env = (String) scope.readState("environment");
return "production".equals(env);
})
.subAgents(productionAgent)
.fallback(scope -> {
String env = (String) scope.readState("environment");
if ("staging".equals(env)) {
return stagingAgent.invoke(scope);
}
return developmentAgent.invoke(scope);
})
.beforeCall(scope -> {
String env = System.getenv("APP_ENV");
scope.writeState("environment", env != null ? env : "development");
})
.build();UntypedAgent smartRouter = AgenticServices.conditionalBuilder()
.condition(scope -> {
// Multiple factors
String tier = (String) scope.readState("user_tier");
boolean isPremium = "premium".equals(tier) || "enterprise".equals(tier);
int dataSize = (Integer) scope.readState("data_size");
boolean isLarge = dataSize > 1000;
int hour = LocalTime.now().getHour();
boolean isOffPeak = hour < 8 || hour > 20;
boolean hasResources = resourceManager.checkAvailability("gpu");
return isPremium && isLarge && (isOffPeak || hasResources);
})
.subAgents(intensiveProcessor)
.fallback(scope -> {
int dataSize = (Integer) scope.readState("data_size");
if (dataSize > 1000) {
jobQueue.enqueue(scope);
return "Job queued for off-peak processing";
}
return standardProcessor.invoke(scope);
})
.build();Use @ActivationCondition to conditionally activate agents within larger workflows:
Example:
interface DataPipeline {
@SequenceAgent(
name = "data-pipeline",
subAgents = {DataFetcher.class, DataEnricher.class, DataValidator.class}
)
String processPipeline(String input);
default boolean shouldEnrichData(AgenticScope scope) {
boolean enabled = (Boolean) scope.readState("enable_enrichment");
String dataType = (String) scope.readState("data_type");
return enabled && "customer".equals(dataType);
}
}
interface DataEnricher {
@Agent(name = "enricher", outputKey = "enriched_data")
@ActivationCondition(conditionMethod = "shouldEnrichData")
String enrichData(AgenticScope scope) {
String data = (String) scope.readState("raw_data");
return enrichedData;
}
}Example:
interface SmartProcessingSystem {
@ConditionalAgent(
name = "smart-validator",
conditionMethod = "shouldUseAdvancedValidation",
fallbackMethod = "basicValidation",
subAgents = {AdvancedValidator.class}
)
ValidationResult validate(String data);
default boolean shouldUseAdvancedValidation(AgenticScope scope) {
String data = (String) scope.readState("input_data");
int complexity = calculateComplexity(data);
boolean isPremium = (Boolean) scope.readState("is_premium_user");
return complexity > 10 && isPremium;
}
default ValidationResult basicValidation(AgenticScope scope) {
String data = (String) scope.readState("input_data");
return new ValidationResult(true, "Basic validation passed");
}
}UntypedAgent conditional = AgenticServices.conditionalBuilder()
.condition(scope -> (Boolean) scope.readState("should_execute"))
.subAgents(riskyAgent)
.errorHandler(errorContext -> {
AgenticScope scope = errorContext.agenticScope();
Integer retryCount = scope.readState("retry_count", 0);
if (retryCount < 3) {
scope.writeState("retry_count", retryCount + 1);
return new ErrorRecoveryResult("retry", true);
}
return new ErrorRecoveryResult("max_retries_exceeded", false);
})
.fallback(scope -> safeAgent.invoke(scope))
.build();Install 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