Designing pipelines
Writing good agents is about scoping
one agent well. This guide is the same judgment call one level up: how many
steps a pipeline should have, and which of VectorStep’s composition
mechanisms — sequential, parallel:, fan_out:, or a sub-pipeline —
fits a given decomposition.
One step is one auditable decision
Section titled “One step is one auditable decision”The reason to split rather than cram two jobs into one step’s prompt isn’t
stylistic — a step gets its own confidence score, its own verifier, its own
grounding check, its own calibration bucket, its own row in
pipeline_steps. A step doing two things blends two different decisions
into one number, the same argument Writing good
agents makes about agent scope, applied
to pipeline structure instead. If a step’s prompt reads as “investigate X,
then decide whether to Y,” ask what happens when it gets the first half
right and the second half wrong — one confidence score can’t say that, but
two steps can.
Sequential when order matters, parallel when it doesn’t
Section titled “Sequential when order matters, parallel when it doesn’t”Use plain sequential steps when a later step genuinely needs an earlier
one’s output — its summary, its next_step_context, a field from its own
JSON. Reach for a parallel: group specifically when branches are
independent and the branch set is fixed at authoring time: a fixed list
of sources to check (runbook, Grafana, recent deploys), each contributing
its own finding, joined back into one effective confidence before flow
control applies. See Parallel groups & fan-out
for the join strategies (all_must_pass, any_must_pass,
weighted_average) that decide how those branch scores combine.
fan_out: is the dynamic version of the same idea, not a different idea —
same join strategies, same confidence-then-flow-control shape, except the
branch count is a list a step returns at runtime rather than something
written into the YAML. Reach for it when you don’t know how many things
there are to check until the alert tells you — see Fan out over multiple
services for the mechanics and
Designing dynamic fan-out for inferring
that list well.
Reach for a sub-pipeline only when logic is genuinely shared
Section titled “Reach for a sub-pipeline only when logic is genuinely shared”executor: pipeline isn’t just “more steps in a different file.” A
sub-pipeline gets its own run_id linked back via parent_run_id, its own
trace, its own row in pipeline_runs, and — if it’s promoted
independently — its own stage. That independence is the whole point when
the same multi-step logic (a shared triage phase, say) is called from more
than one pipeline: each caller gets a real, queryable sub-run, and the
shared logic can be tested and promoted on its own schedule.
It’s the wrong tool for making one pipeline’s own YAML shorter. A
sub-pipeline used purely for readability inherits a real cost the split
doesn’t buy back: cost/token accounting on the parent step only sees the
sub-pipeline’s final step, so a multi-step sub-pipeline can silently
undercount against a parent’s budget: guardrail — a real trap for a
one-off cosmetic split, not just an edge case. See Chaining
pipelines for that and the other
gotchas (trigger matching, stage independence) that don’t show up until
you go looking.
The step library is for repeated shapes, not for hiding complexity
Section titled “The step library is for repeated shapes, not for hiding complexity”use: (see Step library) is the right tool when
the same step config is genuinely reused across pipelines — the
deep-merge on executor_config lets a dozen pipelines share an agent and
session-key pattern while each overrides just a threshold or a prompt. It’s
the wrong tool for making a single pipeline’s own YAML feel shorter by
moving a one-off step somewhere else to look at less often. A step nobody
else references gains nothing from living in the library except an extra
file to open — and the step library’s own UI, which shows exactly which
pipelines reference each entry, makes a single-use step easy to spot as
never having been shared in the first place.
Step count has a cost beyond code review
Section titled “Step count has a cost beyond code review”Every step is a calibration bucket that needs its own history before its confidence number means anything, a readiness tier that needs its own evidence before the pipeline can promote, a line in the Trust panel a human has to read during an incident. More granularity is only a win if each new step is actually a decision worth auditing on its own — not a reflex (“smaller steps are always better software engineering”). A step that never disagrees with the one before it, never gets its own verifier, and never shows up separately in an incident review is a step paying calibration and review cost without buying back any of the auditability point one above is about. When in doubt, start with fewer, coarser steps and split a step only once you can name the specific decision inside it that deserves a score of its own.
Where next
Section titled “Where next”- Parallel groups & fan-out — the mechanical reference for both composition mechanisms.
- Step library —
use:, deep-merge rules, and per-pipeline step analytics. - Executors
— the
pipelineexecutor’s full reference. - Chaining pipelines — the deeper hands-on guide for point 3 above, including the gotchas that don’t show up until you go looking (trigger matching, cost accounting, and stage independence between a sub-pipeline and whatever calls it).
- Designing dynamic fan-out — the deeper companion for fan-out specifically, once the branch list is genuinely runtime-determined rather than fixed at authoring time.