Overview
Composition utilities let you build workflows from Steps without introducing a new DSL.
In coevolved.base.compose, you’ll find patterns you’ll use constantly:
- sequences (pipelines)
- fallback chains (try primary → fallback)
- parallel fan-out (run independent work)
- retry wrappers (resilience)
- graph compilation (introspection / visualization)
Sequential composition
Use run_sequence when step outputs feed into the next step:
from coevolved.base.compose import run_sequence
final_state = run_sequence([step1, step2, step3], state)
Fallback chains
Use run_first_success when you want “try A, then B, then C”:
from coevolved.base.compose import run_first_success
result = run_first_success([primary, fallback], state)
This pattern is useful for “fast path / slow path” designs.
Parallel execution
Use run_parallel to run multiple steps against the same input state.
from coevolved.base.compose import run_parallel
results = run_parallel([a, b, c], state)
Only parallelize steps that don’t mutate shared state (or rely on global mutable state). Prefer returning new values.
Retry wrappers
Wrap a step in a retry policy with exponential backoff:
from coevolved.base.compose import RetryPolicy, with_retry
policy = RetryPolicy(attempts=3, backoff_seconds=0.5)
safe_step = with_retry(unreliable_step, policy)
Compiling step graphs
compile_steps converts a sequence into a small graph structure containing node metadata and edges. This is useful for:
- Debugging “what is in this workflow?”
- Basic visualization
- Metadata inspection (step kinds, schemas, annotations)
Next steps