Skip to main content

The Problem

A real pipeline has many steps — fetch context, rebase, run tests, run AI assessments, judge output, generate a report. Passing every leaf step to a single top-level constructor produces an argument list that’s hard to read, hard to test, and hard to explain:
The fix is not cosmetic. The constructor is wrong at the level of abstraction — it describes leaves when it should describe structure.

The Pattern

Pre-assemble sub-workflows as named Spring beans. The top-level workflow takes phases, not leaves:
The constructor body becomes a pure description of how the phases connect — no wiring, no service lookups:

The Factory

The Spring @Configuration class is the wiring hub. It assembles each phase as a @Bean. Because Workflow<I, O> implements Step<I, O>, sub-workflows compose directly into parent workflows with no adapter needed.
The factory assembles the pieces; the workflow describes only their arrangement. Each bean is independently inspectable and testable.

Why This Structure

Separation of concerns: the workflow is a structural description — it answers “what runs when.” The factory is the wiring layer — it answers “what object gets what dependency.” Mixing them produces the 13-argument constructor. Independent testability: each sub-workflow is a Workflow bean that can be tested in isolation with a minimal set of mock steps. You don’t need to construct all 13 collaborators to test the AI assessment phase:
Readable at every level: a reader of PrReviewDslWorkflow sees the four phases and the gate. A reader of PrReviewConfig.assessAndReport() sees the five steps. Neither method is overwhelmed by the other’s details.

What Other Frameworks Do

This is the standard pattern across Java workflow and batch frameworks:
  • LangChain4j@SequenceAgent(subAgents = {A.class, B.class}) references agents (phases), not the services inside them. The orchestrator doesn’t know how agent A is wired.
  • Google ADK JavaSequentialAgent.builder().addSubAgent(parallelAgent).build() where parallelAgent is already assembled. Leaf services stay inside sub-agents.
  • Spring BatchJob references Step beans. A Step may contain an ItemReader, ItemProcessor, and ItemWriter, but the job definition never sees those — it sees only the step.
The consistent rule: the top-level orchestrator describes structure; the factory describes wiring.

Summary

The workflow constructor should be readable to anyone who wants to understand the pipeline. The configuration class should be readable to anyone who wants to understand how dependencies flow in.

DSL Primitives

Full vocabulary of composable primitives

API Reference

Sub-workflow composition, AgentContext, StepRunner