Skip to main content
The first question everyone asks: “How do I get data into my steps?” There are three levels, presented as a progression. Most users start at Level 1 and add complexity only when needed.

Pattern 1: Constructor Injection

Configuration known at build time — model, prompt template, threshold, API client. Same step class, different parameters, different behavior.
Use when: Configuration is static — model selection, prompt templates, thresholds, API clients. Works exactly like a Spring @Bean with constructor injection.

Pattern 2: Input Chaining

Each step receives the previous step’s output as its input parameter. No context keys, no configuration — just linear data flow.
Use when: The pipeline is linear — step B only needs step A’s output.

Pattern 3: Context Keys

What if step C needs step A’s output, but step B sits between them? The executor auto-propagates every step’s output into AgentContext under Steps.outputOf(stepName). Any downstream step can read any prior step’s result by name.

Typed context for structured data

When steps produce structured data (lists, records, domain objects), downstream steps cast from the auto-propagated output:
Use when: A downstream step needs a non-adjacent prior step’s output, or steps exchange structured data.

Pattern 4: Mixed — All Three Together

Real-world steps combine constructor config + input chaining + context state:

Pattern 5: Context Writes (updateContext)

A step’s primary job is to return a value — the category string for branching, the translated text for the next step. But sometimes a step also knows metadata that other steps need: the confidence score, the detected language, the list of sources used. Without updateContext(), the only way to pass all of this is to return a record — which forces every downstream step to know about that record type, killing reusability. With updateContext(), the step returns its primary output AND publishes metadata as typed context keys.

Example: Classification with confidence and reasoning

The classifier returns "medical" as its primary output (used by the branch). The confidence and reasoning are published as side-channel metadata. Any downstream step reads them without knowing anything about the classifier’s internals:

Example: Language detection as side-channel

Use when: A step produces a primary result AND secondary data (confidence, language, token counts, source lists). The step class owns ContextKey constants as its published output contract. Downstream steps read by key — no coupling to the producing step’s record type.
Most users never need updateContext(). Start with input chaining (Pattern 1). Add Steps.outputOf() when you need non-adjacent data (Pattern 3). Reach for updateContext() only when a step genuinely produces metadata that should travel separately from its primary output.

Quick Reference

DSL Primitives

Sequential, parallel, gate, loop, branch, and more

Complete Examples

Runnable integration tests including context writes