Architecture ClaudeLocal AI Advanced

Agent Pipelines

Four shapes for composing agent steps, and when each one is the right one

35 of 66

Four shapes

Most multi-step agent work is one of these. Picking the wrong one is where systems get slow, expensive, or unreliable.

1. Chain. Each step feeds the next

extract → normalise → validate → write

Use when each step genuinely depends on the last. Simple, debuggable, no coordination.

The failure mode is error propagation: a bad extraction produces a confidently normalised, validated, written wrong answer. Put the cheapest possible check between steps.

data = extract(doc)
assert data.get("total") is not None, "extraction produced no total"
clean = normalise(data)

2. Fan-out / fan-in, independent work, then synthesis

        ┌── analyse security  ──┐
plan ───┼── analyse perf      ──┼── synthesise
        └── analyse tests     ──┘

Use when subtasks are genuinely independent. The synthesis step is the one that needs capability, run the branches on a cheap tier and the join on a good one.

The failure mode is contradictory branches. Two agents reach opposite conclusions from different slices. The synthesiser must be told to surface disagreement rather than average it:

If the reports conflict, say so explicitly and state which one has
stronger evidence. Do not merge contradictory claims into a single
confident answer.

3. Loop with a critic, generate, check, revise

generate → validate ──fail──> revise ──┐
              │                        │
             pass                      └──> (max 3 attempts)
              ↓
            done

The most reliable shape for anything that must be correct. The critic should be a program, not a model, wherever possible. A test suite, a linter, a schema validator. A deterministic critic cannot be talked around.

for attempt in range(3):
    code = generate(spec, feedback=last_error)
    ok, last_error = run_tests(code)
    if ok:
        return code
raise PipelineError(f"failed after 3 attempts: {last_error}")

Always bound the loop. An unbounded revise cycle is how a $0.40 task becomes a $40 one.

4. Router, classify first, then dispatch

                ┌── simple  → fast tier
request ── classify ── standard → balanced tier
                └── hard    → frontier tier

The highest-leverage cost pattern there is. A fast-tier classifier costs almost nothing and routes most traffic away from the expensive tier.

tier = classify(request)          # haiku: ~$0.0002
model = TIERS[tier]
return run(model, request)

The failure mode is misrouting downward. A hard request sent to the fast tier returns a confident wrong answer. Build in escalation:

result = run(TIERS[tier], request)
if result.low_confidence or validation_failed(result):
    result = run(TIERS["hard"], request)   # escalate, don't retry the same tier

Choosing

If…Use
Steps depend on each otherChain
Steps are independentFan-out / fan-in
Correctness is checkable by a programLoop with a critic
Requests vary a lot in difficultyRouter
Two of the above applyCompose them, router in front of a critic loop is very common

Rules that apply to all four

Bound everything. Max attempts, max tokens, max wall-clock. An agent pipeline without limits will eventually find a way to spend all your money on one request.

Log the boundaries. Store the input and output of every step. When the pipeline produces something wrong, you need to know which step went wrong, and reconstructing that from the final output is impossible.

Fail loudly. A step that cannot do its job should stop the pipeline, not pass through a plausible default. Silent degradation in an agent pipeline produces output that looks fine and is not.

Make the critic deterministic where you can. A test suite, a schema, an exit code. Model-as-critic is a fallback, not a first choice.

See also: Single Agent or Subagents? · Chain Commands with Agents · Build a Golden Task Set

Working out which model to run this on? See The Codex. Packaging it as a reusable skill? See The Armory.