Reasoning Architectures · Steps 00–11Chapter 11 of 45

Which Advanced Agent Architecture Should You Use? A Practical Selection Guide

Page content

Which Advanced Agent Architecture Should You Use?

You now have too many options.

That is a better problem than having none.

But it is still a problem.

You can add:

  • self-consistency,
  • Tree of Thoughts,
  • beam search,
  • Monte Carlo Tree Search,
  • evolutionary search,
  • specialist routing,
  • planner/executor/critic separation,
  • multi-agent debate,
  • adaptive policies,
  • learning from previous runs,
  • or a mixture-of-agents runtime that chooses among several of them.

The temptation is to combine everything.

That is usually the wrong move.

The useful question is not:

Which agent architecture is most advanced?

The useful question is:

What measurable failure are you trying to fix, and what is the cheapest mechanism that can fix it?

That question turns an architectural fashion problem into an engineering decision.

This post is the selection guide for the entire Advanced Agents From First Principles series.


Start With the Failure, Not the Mechanism

Suppose your coding agent fails 30% of repository tasks.

That number is not enough to choose an architecture.

You need to know how it fails.

For example:

failure
  ├── chooses bad first hypothesis
  ├── cannot recover after early mistake
  ├── generates several good options but ranks badly
  ├── weak at one specialist subtask
  ├── misses obvious defects in its own output
  ├── wastes compute on easy tasks
  ├── repeats failures seen on previous runs
  └── claims success without evidence

Those failures point to different mechanisms.

Adding MCTS to a bad verifier will not repair the verifier.

Adding debate to a routing problem may simply produce several agents debating the wrong task.

Adding more reasoning to a deterministic workflow may only increase latency.

The first step is therefore a failure taxonomy.


A Fast Selection Map

Use this as the first pass.

Failure mode First mechanism to test
Output varies, but some samples are correct Self-consistency / Best-of-N
Agent commits too early Tree of Thoughts / shallow branch search
Need bounded search over promising branches Beam search
Must balance exploring unknown branches vs exploiting strong ones MCTS
Solutions improve through mutation/recombination Evolutionary search
Different tasks need different capabilities Specialist routing / MoE
Planning and execution interfere with each other Planner / executor separation
Agent misses defects in its own work Critic / verifier separation
Independent perspectives catch different errors Multi-agent review / debate
Easy and hard tasks deserve different compute Adaptive budgets / routing
Same failures recur over many runs Learning from previous runs
No single mechanism wins everywhere Mixture-of-agents runtime

That table is deliberately conservative.

You should start with the smallest relevant mechanism.


Step 1: Can the Task Be Verified?

Before choosing an advanced architecture, ask whether the task has a useful verifier.

This is more important than it first appears.

A strong verifier turns extra computation into something the runtime can control.

candidate
verification
keep / reject / continue

Examples of strong verification include:

  • unit and integration tests,
  • compiler success,
  • schema validation,
  • exact database state,
  • browser DOM state,
  • numerical invariants,
  • source-backed factual claims,
  • deployment health checks,
  • deterministic business rules.

If verification is strong, search becomes much safer.

You can generate many candidates and let evidence decide.

If verification is weak, advanced search can amplify evaluator mistakes.

bad evaluator
search follows bad scores
more compute spent on wrong branch

This creates a simple rule:

The stronger the verifier, the more aggressively you can use search.

When the verifier is weak, prefer simpler orchestration and invest in better evidence before adding deeper search.


Step 2: Is the Failure Stochastic or Structural?

This distinction is crucial.

Stochastic failure

The model can solve the task, but not reliably.

Run it several times and some answers are good.

same task
  ├── wrong
  ├── correct
  ├── wrong
  └── correct

That suggests self-consistency or Best-of-N.

You do not necessarily need a tree.

Structural failure

The model repeatedly follows the same bad process.

same task
  ├── same wrong assumption
  ├── same wrong assumption
  ├── same wrong assumption
  └── same wrong assumption

Sampling more may not help.

You may need:

  • a different role,
  • a specialist,
  • external evidence,
  • a search process that forces alternative states,
  • or a learned strategy change.

A useful diagnostic is oracle@N.

If at least one of N samples is usually correct, generation is capable and selection may be the bottleneck.

If none of the N samples are correct, more sampling is unlikely to solve the problem.


When to Use Self-Consistency

Self-consistency is one of the cheapest advanced techniques.

Generate several independent solutions and aggregate them.

problem
  ├── solution A
  ├── solution B
  ├── solution C
  └── solution D
       aggregate

Use it when:

  • the task is stochastic,
  • independent samples differ meaningfully,
  • final answers are cheap to compare,
  • and you do not need to preserve partial trajectories.

Good examples:

  • classification,
  • short reasoning problems,
  • structured extraction,
  • candidate patches with strong tests,
  • SQL generation with executable validation.

Avoid it when:

  • all samples make the same structural mistake,
  • the answer cannot be cheaply judged,
  • or long trajectories must diverge earlier than the final output.

The baseline to beat is simple repeated sampling at the same call budget.


When to Use Tree of Thoughts

Tree of Thoughts is useful when intermediate decisions matter.

Instead of generating complete solutions, the system maintains partial reasoning states.

root
 ├── thought A
 │    ├── A1
 │    └── A2
 ├── thought B
 │    ├── B1
 │    └── B2
 └── thought C

Use it when:

  • early decisions constrain later success,
  • partial states can be meaningfully evaluated,
  • and preserving alternatives is valuable.

Good examples:

  • decomposition-heavy planning,
  • mathematical strategy selection,
  • multi-step research hypotheses,
  • code repair approaches,
  • complex transformation pipelines.

Avoid it when:

  • only the final answer can be judged,
  • partial scores are unreliable,
  • branching factor is huge,
  • or Best-of-N already captures most of the gain.

The key question is not whether a tree can be built.

It is whether partial branches can be ranked well enough to justify keeping the tree.


Beam search is a practical compromise between one trajectory and full tree expansion.

At each depth:

expand
score
keep top-k
expand again

Use it when:

  • there are many possible next states,
  • you need bounded memory and compute,
  • and a scoring function can identify promising partial branches.

Beam search is especially attractive for production systems because the budget is explicit.

beam width = 4
max depth = 8
max nodes = 32

Good examples:

  • code-edit trajectories,
  • workflow planning,
  • navigation paths,
  • query-plan generation,
  • structured synthesis.

Avoid it when:

  • the evaluator is noisy enough to prune good branches early,
  • exploration of low-scoring but uncertain states matters,
  • or branches converge so quickly that width adds little value.

That last limitation leads naturally to MCTS.


When to Use MCTS

Monte Carlo Tree Search becomes useful when you need to balance:

exploit what looks good
          vs
explore what remains uncertain

A simple greedy search repeatedly expands the current best-looking state.

MCTS deliberately spends some budget on less-tested branches.

Use it when:

  • the search tree is large,
  • partial evaluations are imperfect,
  • promising branches need repeated refinement,
  • and uncertainty itself should influence where compute goes.

Good examples:

  • difficult code repair,
  • complex planning,
  • program synthesis,
  • tool-use trajectories,
  • environments where downstream outcomes reveal information about earlier choices.

Avoid it when:

  • beam search already solves the task,
  • each node expansion is very expensive,
  • the value estimate is weak,
  • or there is no meaningful rollout/evaluation signal.

The correct baseline is not one-shot generation.

It is usually a compute-matched beam or random-search baseline using a similar node budget.


Evolutionary approaches are useful when solutions can improve through modification.

population
score
select
mutate / recombine
new population

Use them when:

  • candidate quality is not strictly tied to a sequential path,
  • good partial ideas can be recombined,
  • mutations can produce meaningful local improvements,
  • and there is a useful fitness signal.

Good examples:

  • prompt/program optimization,
  • code variants,
  • configuration tuning,
  • workflow design,
  • candidate policy improvement.

Avoid evolutionary search when:

  • candidates cannot be meaningfully mutated,
  • recombination destroys important structure,
  • or each evaluation is too expensive.

A particularly strong signal for evolutionary methods is when your best solutions consistently contain useful fragments that could be grafted into other candidates.


When to Use Specialist Routing

Not every task needs search.

Sometimes the problem is simply that one model or agent is not equally strong at every subtask.

task
router
  ├── coding specialist
  ├── retrieval specialist
  ├── data specialist
  ├── cheap local model
  └── expensive frontier model

Use routing when:

  • task classes have distinct requirements,
  • specialists demonstrably outperform the generalist on their domains,
  • and routing can be measured independently.

Good examples:

  • coding vs retrieval vs summarization,
  • language-specific code agents,
  • domain-specific research,
  • local-model-first systems with escalation,
  • tool family selection.

Start with deterministic routing when the boundaries are obvious.

if task.kind == "sql":
    return sql_agent
if task.kind == "python":
    return python_agent

Only add learned routing when the boundary is actually ambiguous.

Metrics matter:

  • routing accuracy,
  • specialist success rate,
  • fallback rate,
  • cost per success,
  • regret relative to the best specialist.

When to Separate Planner, Executor and Critic

A single model can plan, execute and critique.

That does not mean it should.

Role separation helps when different stages need different context or incentives.

planner
executor
critic
verifier

Use separation when:

  • planning context is different from execution context,
  • execution should not rewrite the plan silently,
  • critique benefits from independence,
  • or permissions differ by role.

Coding is a strong example.

The planner may inspect repository structure and produce an implementation plan.

The executor edits files.

The critic reviews the diff.

The verifier runs tests.

The architecture becomes useful because responsibilities are explicit, not because there are more agents.

Avoid adding role separation when all roles receive the same context, use the same model, produce nearly identical outputs and add no measurable benefit.

That is ceremony, not architecture.


When to Use Multi-Agent Debate

Debate sounds powerful because disagreement sounds like intelligence.

It can also be expensive noise.

A useful debate architecture looks like:

proposal A ─┐
            ├→ adjudicator → decision
proposal B ─┘

or:

proposal
challenge
response
independent judge

Use debate when:

  • independent agents reliably surface different failure modes,
  • arguments can be grounded in evidence,
  • and the judge can distinguish stronger evidence from stronger rhetoric.

Good examples:

  • code review,
  • security analysis,
  • research synthesis,
  • policy interpretation,
  • architectural review.

Avoid debate when:

  • agents are highly correlated,
  • the judge has no external evidence,
  • or the task is objectively testable and direct verification is cheaper.

If tests can answer the question, run the tests.

Do not hold a five-agent philosophical discussion about whether the code compiles.


When to Use Adaptive Agents

Fixed orchestration is often wasteful.

An easy task and a difficult task may receive the same expensive pipeline.

easy task
planner
5 samples
critic
MCTS
verifier

That is unnecessary if a single verified action would work.

Adaptive systems change compute based on evidence.

task
cheap attempt
verified?
  ├── yes → stop
  └── no  → escalate

Use adaptation when:

  • task difficulty varies,
  • confidence can be calibrated,
  • verification provides feedback,
  • and expensive mechanisms are only useful on a subset of tasks.

Possible adaptive decisions include:

  • model choice,
  • search depth,
  • beam width,
  • number of candidates,
  • critic count,
  • retrieval depth,
  • escalation to frontier models,
  • whether to invoke MCTS at all.

This can produce a major efficiency gain because the runtime stops treating maximum complexity as the default.


When to Learn From Previous Runs

Memory and learning are not the same thing.

Memory stores what happened.

Learning changes future behavior because of what happened.

run
verified outcome
store evidence
aggregate patterns
change future policy

Use run-history learning when:

  • the same task classes recur,
  • outcomes are verified,
  • failure categories can be extracted,
  • and future decisions can benefit from those patterns.

Examples:

  • repository-specific repair strategies,
  • browser-site quirks,
  • model routing performance,
  • search-depth calibration,
  • recurring incident remediation,
  • prompt/tool failures.

Be conservative.

A bad run should not become a durable policy merely because it happened.

Promote learning from verified, repeated evidence rather than single trajectories.


When to Build a Mixture of Agents

A mixture-of-agents runtime is not simply “use many agents.”

It is a controller that decides which mechanism should run.

request
controller
   ├── simple agent
   ├── Best-of-N
   ├── specialist
   ├── beam search
   ├── MCTS
   ├── debate
   └── human escalation

Use a mixture when:

  • no single mechanism wins across the workload,
  • task classes differ substantially,
  • cost matters,
  • and you have enough evaluation data to learn or encode useful routing decisions.

The mixture should reduce unnecessary complexity, not guarantee that every task passes through every mechanism.

The ideal controller often looks like progressive escalation:

cheap deterministic path
        ↓ if insufficient
single agent
        ↓ if insufficient
specialist / retrieval
        ↓ if insufficient
candidate search
        ↓ if insufficient
advanced search / debate
        ↓ if still unresolved
human or explicit UNKNOWN

That is much healthier than the monster pipeline where every technique runs every time.


The Three Axes That Matter Most

You can simplify architecture selection to three questions.

Axis 1: How strong is verification?

weak -------------------------------- strong

Stronger verification supports more aggressive search.

Axis 2: How variable is task difficulty?

uniform ----------------------------- highly variable

Higher variability favors adaptive orchestration.

Axis 3: How heterogeneous are the required capabilities?

one skill --------------------------- many distinct skills

Higher heterogeneity favors routing and specialization.

Combine the axes:

Verification Difficulty variance Capability diversity Likely architecture
Strong Low Low Simple agent + verifier
Strong High Low Adaptive search
Strong High High Routed specialists + adaptive search
Weak Low Low Simple agent + better evaluator
Weak High Low Conservative sampling + review
Weak High High Specialists + evidence gathering before deep search

This table is not a law.

It is a useful starting point.


Do Not Compare Architectures at Unequal Compute

One of the easiest ways to fool yourself is:

baseline: 1 model call
advanced system: 23 model calls

Then announce that the advanced architecture is better.

It may be.

But the comparison does not tell you whether the architecture helped or whether more inference helped.

Use compute-matched comparisons.

For example:

A: one-shot                         1 call
B: repeated sampling              10 calls
C: Tree of Thoughts               10 calls
D: beam search                    10 calls
E: MCTS                           10 node expansions

Then compare verified outcomes.

The same principle applies to multi-agent systems.

If three specialist agents beat one generalist, also compare against three independent runs of the generalist.

Otherwise you may be measuring compute rather than specialization.


Track Cost Per Verified Success

Raw success rate is not enough.

Suppose:

Architecture Success Avg cost/task
Single agent 74% $0.05
Best-of-N 82% $0.18
Beam search 86% $0.32
MCTS 88% $0.95

MCTS has the highest success rate.

That does not automatically make it the best production choice.

A useful metric is:

cost per verified success

You may also care about:

  • p50/p95 latency,
  • tokens per success,
  • tool calls per success,
  • failure recovery rate,
  • false-success rate,
  • verifier coverage,
  • human escalation rate.

The correct architecture depends on the economics of the application.


Measure Marginal Gain

Advanced mechanisms should be added incrementally.

Suppose you test:

baseline                         72%
+ Best-of-N                      79%
+ critic                         80%
+ beam search                    85%
+ second critic                  85.2%
+ debate                         85.1%

The second critic and debate are not earning their place.

Remove them.

A production agent architecture should be treated like an optimization problem:

maximize verified success
subject to:
  cost
  latency
  safety
  complexity
  maintainability

That is a much stronger objective than “use the most advanced technique available.”


A Coding-Agent Example

Imagine a coding agent with these benchmark results:

100 tasks
  70 solved
  10 wrong-file edits
   8 bad implementation strategies
   6 correct patch, bad selection
   4 test regressions
   2 verifier failures

Do not add MCTS immediately.

Fix the highest-value bottlenecks in order.

Wrong-file edits

Improve repository state and retrieval.

Correct patch, bad selection

Improve evaluator or Best-of-N selection.

Bad implementation strategies

Introduce shallow branch search.

Regressions

Strengthen verification.

Verifier failures

Fix the verifier before spending more search compute.

Only after those changes should you ask whether deeper beam search or MCTS improves the remaining hard cases.

The failure distribution determines the architecture.


A Research-Agent Example

Suppose a research agent fails because:

40% weak sources
25% missed counter-evidence
20% synthesis errors
15% search-query failures

MCTS is not the obvious answer.

A better sequence might be:

source-quality rules
parallel search strategies
adversarial counter-evidence pass
claim/evidence verification

Only if hypothesis exploration itself remains the bottleneck would tree search become attractive.

Again: mechanism follows failure.


A DevOps-Agent Example

An incident agent may need the opposite architecture.

Production actions are risky.

So the runtime should spend compute on cheap, read-only information before acting.

incident
several hypotheses
read-only diagnostics
update evidence
rank hypotheses
select remediation
precondition check
execute
postcondition verification

This resembles search, but the key design constraint is side-effect safety.

The agent may explore many hypotheses.

It should not execute many speculative production remediations.


A Good Escalation Policy

One practical production pattern is progressive escalation.

async def solve(task):
    result = await simple_agent(task)
    if verify(result):
        return result

    result = await best_of_n(task, n=3)
    if verify(result):
        return result

    result = await specialist_route(task)
    if verify(result):
        return result

    result = await beam_search(task, width=3)
    if verify(result):
        return result

    return UnknownResult(reason="verification_not_reached")

The important property is not the exact stages.

It is that complexity is earned by failure.

Easy tasks stop early.

Hard tasks receive more compute.

The system has an explicit UNKNOWN instead of pretending every escalation must eventually produce success.


What to Log

Advanced orchestration is almost impossible to improve if you only store the final answer.

Log at least:

task id
architecture selected
model/tool calls
candidate ids
parent-child lineage
evaluator scores
pruning decisions
verification results
latency
cost
final outcome
failure category

For routing systems, also log:

selected specialist
available specialists
router confidence
counterfactual benchmark winner when available

For adaptive systems:

budget allocated
budget consumed
why escalation occurred
why search stopped

This turns agent architecture into something you can calibrate rather than merely observe.


The Architecture Selection Loop

A healthy advanced-agent development loop looks like this:

collect real failures
classify failure modes
choose smallest mechanism
run controlled benchmark
compare compute-matched baseline
inspect verifier quality
measure cost per verified success
keep / tune / remove
repeat

That is the real “advanced” system.

Not the number of agents.

Not the size of the orchestration graph.

The sophistication is in the feedback loop between evidence and architecture.


Final Decision Rules

If you remember only a few rules from this entire series, use these:

  1. If repeated independent samples solve the problem, use sampling before search.
  2. If early decisions matter, preserve partial alternatives.
  3. If greedy pruning loses uncertain branches, consider exploration-aware search such as MCTS.
  4. If different tasks need different capabilities, route rather than forcing one agent to do everything.
  5. If roles need different context, permissions or incentives, separate them.
  6. If disagreement exposes real defects, adversarial review can help—but verify externally whenever possible.
  7. If task difficulty varies, allocate compute adaptively.
  8. If failures repeat across runs, learn from verified history rather than merely storing it.
  9. If no mechanism wins everywhere, use a mixture that selects mechanisms instead of stacking them all.
  10. Always compare against a simpler, compute-matched baseline.

And one rule sits above all of them:

Use the simplest architecture that achieves the required verified success rate at an acceptable cost.

That is the same principle that governed the model series and the basic agent series.

It matters even more here because advanced orchestration makes complexity extremely easy to add.

The purpose of advanced agents is not to build a bigger machine.

It is to spend computation where it actually changes the answer.