CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-dev-langchain4j--langchain4j-agentic

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.

Overview
Eval results
Files

workflows.mddocs/api/

Workflows Overview

Overview of all workflow types for orchestrating multiple agents with different execution patterns.

Quick Reference

Workflow TypeUse CaseKey Methods
SequentialExecute agents one after anothersequenceBuilder()
ParallelExecute agents concurrentlyparallelBuilder(), threadPoolSize()
LoopExecute agents iterativelyloopBuilder(), maxIterations(), exitCondition()
ConditionalExecute agents based on conditionsconditionalBuilder(), subAgents(predicate, ...)
SupervisorLLM-based autonomous orchestrationsupervisorBuilder(), maxAgentsInvocations()
PlannerCustom logic-based orchestrationplannerBuilder(), planner()

Sequential Workflows

Execute agents one after another in a defined sequence.

/**
 * Create sequential workflow builder
 * @return SequentialAgentService for building sequential workflows
 */
static SequentialAgentService<UntypedAgent> sequenceBuilder();

Quick Example:

UntypedAgent pipeline = AgenticServices.sequenceBuilder()
    .subAgents(fetchAgent, processAgent, validateAgent)
    .name("data-pipeline")
    .build();

When to Use:

  • Data processing pipelines where each step depends on the previous
  • Multi-stage workflows with clear sequential dependencies
  • Workflows where order matters

See: sequential.md for complete API reference

Parallel Workflows

Execute multiple agents concurrently with configurable thread pool execution.

/**
 * Create parallel workflow builder
 * @return ParallelAgentService for building parallel workflows
 */
static ParallelAgentService<UntypedAgent> parallelBuilder();

Quick Example:

UntypedAgent parallel = AgenticServices.parallelBuilder()
    .subAgents(validator1, validator2, validator3)
    .threadPoolSize(4)
    .name("multi-validator")
    .build();

When to Use:

  • Independent tasks that can run simultaneously
  • Validation from multiple sources
  • Aggregating results from parallel operations
  • Maximizing throughput and reducing latency

See: parallel.md for complete API reference

Loop Workflows

Execute agents iteratively with configurable exit conditions and iteration limits.

/**
 * Create loop workflow builder
 * @return LoopAgentService for building loop workflows
 */
static LoopAgentService<UntypedAgent> loopBuilder();

Quick Example:

UntypedAgent loop = AgenticServices.loopBuilder()
    .subAgents(refinementAgent)
    .maxIterations(10)
    .exitCondition(scope -> {
        double quality = (Double) scope.readState("quality_score");
        return quality >= 0.95;
    })
    .build();

When to Use:

  • Iterative refinement until quality threshold
  • Retry logic with configurable attempts
  • Convergence-based algorithms
  • Incremental improvement workflows

See: loop.md for complete API reference

Conditional Workflows

Execute agents conditionally based on runtime predicates.

/**
 * Create conditional workflow builder
 * @return ConditionalAgentService for building conditional workflows
 */
static ConditionalAgentService<UntypedAgent> conditionalBuilder();

Quick Example:

UntypedAgent conditional = AgenticServices.conditionalBuilder()
    .subAgents(
        scope -> "premium".equals(scope.readState("user_tier")),
        premiumAgent
    )
    .subAgents(
        scope -> true,  // fallback
        basicAgent
    )
    .build();

When to Use:

  • Feature flags and A/B testing
  • Permission-based execution
  • Environment-specific behavior
  • Dynamic workflow routing

See: conditional.md for complete API reference

Supervisor Agents

Autonomous LLM-based orchestration that dynamically selects and coordinates sub-agents.

/**
 * Create supervisor agent builder
 * @return SupervisorAgentService for building supervisor-based orchestration
 */
static SupervisorAgentService<SupervisorAgent> supervisorBuilder();

Quick Example:

SupervisorAgent supervisor = AgenticServices.supervisorBuilder()
    .chatModel(chatModel)
    .subAgents(researchAgent, analysisAgent, writingAgent)
    .maxAgentsInvocations(10)
    .contextGenerationStrategy(SupervisorContextStrategy.FULL)
    .responseStrategy(SupervisorResponseStrategy.SUMMARY)
    .build();

When to Use:

  • Complex tasks requiring dynamic decision-making
  • Workflows where agent invocation order isn't predetermined
  • Tasks that benefit from LLM reasoning about agent selection
  • Adaptive workflows that respond to intermediate results

See: supervisor.md for complete API reference

Planner-Based Agents

Custom logic-based orchestration where you define the planning algorithm.

/**
 * Create planner-based agent builder
 * @return PlannerBasedService for building planner-based orchestration
 */
static PlannerBasedService<UntypedAgent> plannerBuilder();

Quick Example:

UntypedAgent agent = AgenticServices.plannerBuilder()
    .planner(() -> new MyCustomPlanner())
    .subAgents(agent1, agent2, agent3)
    .name("custom-orchestrator")
    .build();

When to Use:

  • Business logic requires specific orchestration rules
  • Complex state machines or workflow engines
  • Custom algorithms for agent coordination
  • Workflows with sophisticated decision trees

See: planner.md for complete API reference

Composing Workflows

Workflows can be nested and composed to create sophisticated multi-tier orchestrations.

Sequential + Parallel

Execute stages sequentially, with parallel execution within stages:

UntypedAgent stage1Parallel = AgenticServices.parallelBuilder()
    .subAgents(validator1, validator2, validator3)
    .name("validation-stage")
    .build();

UntypedAgent stage2Parallel = AgenticServices.parallelBuilder()
    .subAgents(enricher1, enricher2)
    .name("enrichment-stage")
    .build();

UntypedAgent pipeline = AgenticServices.sequenceBuilder()
    .subAgents(fetchAgent, stage1Parallel, stage2Parallel, saveAgent)
    .name("etl-pipeline")
    .build();

Loop + Sequential

Execute a sequence of agents iteratively:

UntypedAgent refinementSequence = AgenticServices.sequenceBuilder()
    .subAgents(critic, improver)
    .name("refinement-cycle")
    .build();

UntypedAgent refinementLoop = AgenticServices.loopBuilder()
    .subAgents(refinementSequence)
    .maxIterations(5)
    .exitCondition(scope -> {
        double quality = (Double) scope.readState("quality_score");
        return quality >= 0.9;
    })
    .build();

Conditional + Parallel

Route to different parallel execution branches:

UntypedAgent premiumValidation = AgenticServices.parallelBuilder()
    .subAgents(advancedValidator1, advancedValidator2, advancedValidator3)
    .build();

UntypedAgent basicValidation = AgenticServices.parallelBuilder()
    .subAgents(basicValidator1, basicValidator2)
    .build();

UntypedAgent tieredValidator = AgenticServices.conditionalBuilder()
    .subAgents(
        scope -> "premium".equals(scope.readState("tier")),
        premiumValidation
    )
    .subAgents(
        scope -> true,
        basicValidation
    )
    .build();

Supervisor + Specialized Workflows

Use supervisor to coordinate complex sub-workflows:

UntypedAgent dataWorkflow = AgenticServices.sequenceBuilder()
    .subAgents(fetcher, validator, transformer)
    .name("data-workflow")
    .build();

UntypedAgent analysisWorkflow = AgenticServices.parallelBuilder()
    .subAgents(statisticalAnalyzer, sentimentAnalyzer, trendAnalyzer)
    .name("analysis-workflow")
    .build();

SupervisorAgent supervisor = AgenticServices.supervisorBuilder()
    .chatModel(chatModel)
    .subAgents(dataWorkflow, analysisWorkflow, reportGenerator)
    .maxAgentsInvocations(15)
    .build();

Common Configuration

All workflow builders share common configuration methods through AgenticService:

/**
 * Common configuration methods for all workflow types
 */
interface AgenticService<S extends AgenticService<S, T>, T> {
    /**
     * Build and return the configured workflow
     */
    T build();

    /**
     * Set workflow name
     */
    S name(String name);

    /**
     * Set workflow description
     */
    S description(String description);

    /**
     * Set output key for AgenticScope
     */
    S outputKey(String outputKey);

    /**
     * Set custom output function
     */
    S output(Function<AgenticScope, Object> output);

    /**
     * Set error handler
     */
    S errorHandler(Function<ErrorContext, ErrorRecoveryResult> errorHandler);

    /**
     * Add agent listener
     */
    S listener(AgentListener listener);

    /**
     * Set pre-invocation callback
     */
    S beforeCall(Consumer<AgenticScope> beforeCall);
}

Choosing the Right Workflow

Your NeedRecommended Workflow
Steps must happen in orderSequential
Maximize speed with independent tasksParallel
Retry until success/thresholdLoop
Different paths based on stateConditional
LLM decides agent coordinationSupervisor
Custom orchestration logicPlanner
Complex multi-stage processingCompose multiple workflows

Best Practices

1. Use outputKey for Data Flow

UntypedAgent agent1 = AgenticServices.agentBuilder()
    .chatModel(chatModel)
    .name("fetcher")
    .outputKey("data")  // Store result in AgenticScope
    .build();

UntypedAgent agent2 = AgenticServices.agentBuilder()
    .chatModel(chatModel)
    .name("processor")
    .context(scope -> {
        String data = (String) scope.readState("data");  // Read from AgenticScope
        return "Process this: " + data;
    })
    .build();

2. Add Error Handlers

UntypedAgent workflow = AgenticServices.sequenceBuilder()
    .subAgents(agent1, agent2, agent3)
    .errorHandler(errorContext -> {
        System.err.println("Error: " + errorContext.error().getMessage());
        return new ErrorRecoveryResult("fallback", false);
    })
    .build();

3. Use Listeners for Monitoring

AgentListener listener = new AgentListener() {
    @Override
    public void afterAgentInvocation(AgentResponse response) {
        System.out.println(response.agentName() + " took " +
                         response.duration().toMillis() + "ms");
    }
};

UntypedAgent workflow = AgenticServices.parallelBuilder()
    .subAgents(agent1, agent2, agent3)
    .listener(listener)
    .build();

4. Initialize State with beforeCall

UntypedAgent workflow = AgenticServices.loopBuilder()
    .subAgents(agent)
    .maxIterations(5)
    .beforeCall(scope -> {
        scope.writeState("attempt", 0);
        scope.writeState("start_time", System.currentTimeMillis());
    })
    .build();

Advanced Topics

See Also

Install with Tessl CLI

npx tessl i tessl/maven-dev-langchain4j--langchain4j-agentic

docs

index.md

tile.json