You Probably Don't Need All of This: Build the Minimum Production Agent Architecture
You Probably Don’t Need All of This
Over the previous forty-five steps, we built almost every major mechanism you might need in a serious agent platform.
Search.
Critique.
Planning.
Memory.
Verification.
Distributed execution.
Leases.
Fencing.
Backpressure.
Behavioral releases.
Replay.
Incident forensics.
SLOs.
Competence envelopes.
Authority boundaries.
Capability portfolios.
Placement.
Portable execution state.
Temporal consistency.
Intent versioning.
Commitments.
Durable workflows.
Transaction recovery.
Security boundaries.
Multi-agent coordination.
An explicit control plane.
And finally, in Step 44, we assembled those ideas into a complete reference architecture for a production AI agent.
Now we should remove most of it.
That is not a contradiction.
It is the point.
The final lesson of this series is not how to build the largest possible agent architecture.
It is how to recognize the smallest architecture that is sufficient for the failure modes you actually have.
The core principle is:
Complexity must continuously earn its place.
A second principle follows immediately:
Do not add an agent mechanism because it sounds more intelligent. Add it because you can identify the failure it is supposed to fix and measure whether it fixes it.
And the final principle for the series is:
The minimum production agent is not the agent with the fewest lines of code. It is the smallest system that preserves the correctness boundaries your task actually requires.
The trap at the end of an architecture series
There is an obvious danger in a series like this.
We spend dozens of chapters learning mechanisms.
Then we begin to treat possession of those mechanisms as architectural maturity.
That creates systems like this:
user
↓
planner
↓
router
↓
mixture of agents
↓
tree search
↓
critic swarm
↓
memory hierarchy
↓
learned scheduler
↓
policy optimizer
↓
distributed workflow engine
↓
control plane
↓
verification mesh
↓
side-effect coordinator
It looks sophisticated.
It may also be slower, more expensive, harder to understand, harder to verify and less reliable than:
request
↓
model
↓
validated tool call
↓
external verifier
↓
result
The correct comparison is not:
simple architecture
vs
advanced architecture
It is:
architecture A
vs
architecture B
under the same task distribution,
resource budget,
risk constraints,
and external verification.
That was the lesson of Step 12, and it still applies at the end.
Start from the failure, not the mechanism
The most useful architectural question is not:
What advanced agent pattern should we add next?
It is:
What measurable failure is preventing the current system from meeting its objective?
For example:
Failure: model produces malformed tool arguments
Mechanism: typed tool schema + deterministic validation
Not:
Failure: model produces malformed tool arguments
Mechanism: multi-agent debate
Or:
Failure: one-shot answers have high variance
Mechanism: generate several candidates + rank
Not:
Failure: one-shot answers have high variance
Mechanism: durable workflow engine
Or:
Failure: external side effects may commit twice after retry
Mechanism: stable operation identity + idempotency + reconciliation
Not:
Failure: external side effects may commit twice after retry
Mechanism: better system prompt
The architecture should be shaped by the failure topology.
The minimum production agent
For many useful production systems, the minimum architecture looks approximately like this:
authoritative request
│
▼
model
│
proposed action
│
▼
typed tool boundary
│
deterministic validation
│
▼
authority gate
│
▼
external action
│
▼
external verifier
│
▼
recorded outcome
Around it, keep a trajectory log.
That gives us six important pieces:
- A model for semantic work.
- Typed tools for structured action.
- Authoritative state outside the model.
- A small authority boundary before consequential mutations.
- An external verifier that determines whether the outcome is real.
- A trajectory log that records what happened.
For a surprising number of production agents, that is enough.
Component 1: the model
The model should do the work that genuinely benefits from probabilistic semantic reasoning.
Examples:
- interpret a support request;
- identify which code area probably matters;
- extract meaning from a document;
- propose a patch;
- select among semantically plausible routes;
- summarize evidence;
- construct a candidate answer.
The model should not be forced to impersonate deterministic infrastructure.
Do not ask it to remember counters that belong in a database.
Do not ask it whether a lease is still valid when the lease store can answer exactly.
Do not ask it whether a Git SHA changed when Git can answer exactly.
Do not ask it whether a tool call conforms to a schema when a parser can answer exactly.
Do not ask it whether an external mutation actually happened when the external system exposes authoritative state.
A useful default rule is:
Use the model for ambiguity. Use software for exactness.
Component 2: typed tools
A production agent should not interact with consequential systems through an unconstrained natural-language interface when a narrow typed interface is possible.
Prefer:
create_pull_request(
repository: str,
head_branch: str,
base_branch: str,
title: str,
body: str,
draft: bool,
)
over:
Use the shell to do whatever is necessary to open a PR.
The narrow interface gives you:
- validation;
- observability;
- permission scoping;
- deterministic failure;
- structured logs;
- easier testing;
- safer retries;
- lower accidental authority.
This is one of the cheapest high-value improvements you can make.
If your agent only needs three actions, give it three actions.
Do not give it a shell because a shell is easier to expose.
Component 3: authoritative state outside the model
The model can maintain working context.
It should not own operational truth.
For example:
bad:
"The model remembers that the PR has not been created yet."
better:
"The system asks GitHub whether the PR exists."
Or:
bad:
"The model remembers that approval was granted."
better:
"The approval store contains a scoped, current approval record."
Or:
bad:
"The model believes the branch is still abc123."
better:
"The mutation path compares the current SHA with abc123."
You do not need a giant knowledge graph to follow this rule.
A few database rows may be enough.
The architectural principle matters more than the infrastructure size:
Operational truth must survive model replacement, context truncation and worker restart.
Component 4: a small authority gate
Before a consequential action, ask a small number of deterministic questions.
For a coding agent, that might be:
def may_merge(ctx):
if not ctx.intent_is_current:
return False, "STALE_INTENT"
if not ctx.branch_head_matches_expected:
return False, "STATE_CONFLICT"
if not ctx.tests_passed:
return False, "VERIFICATION_REQUIRED"
if not ctx.approval_is_valid:
return False, "AUTHORITY_REQUIRED"
return True, "ALLOW"
That is already a control boundary.
You do not need to call it a control plane yet.
You do not need a policy language.
You do not need a distributed authority service.
You need the invariant.
The implementation can remain tiny until the workload proves it needs more.
Component 5: external verification
This is the part I would be most reluctant to remove.
If the agent can claim success merely because the same model says it succeeded, the architecture has a serious weakness.
A coding agent should prefer evidence like:
tests passed
lint passed
build succeeded
repository state matches expected result
PR actually exists
A browser agent should prefer:
confirmation page
provider transaction ID
server-side order state
A data agent should prefer:
schema checks
row-count invariants
reconciliation query
expected output artifact
A research agent should prefer:
source-backed claims
retrievable citations
current-state refresh where required
The rule from earlier in the series remains:
The agent may produce the action, but it does not get to define reality.
Component 6: trajectory logging
At minimum, record:
request / intent identity
model release
input state identity
proposed action
tool invocation
validation result
authority decision
external response
verification evidence
final outcome
cost / latency
This does not require a massive observability platform.
A structured JSON event log is a good beginning.
Why preserve it?
Because when the system fails, you want to answer:
What did it observe?
What did it decide?
What action did it attempt?
What authority allowed it?
What happened externally?
What evidence produced the final outcome?
If you cannot answer those questions, adding more agents is unlikely to help.
A minimum implementation skeleton
A tiny implementation can preserve surprisingly strong boundaries.
from dataclasses import dataclass
from enum import Enum
from typing import Any
class Outcome(str, Enum):
PASS = "PASS"
FAIL = "FAIL"
UNKNOWN = "UNKNOWN"
@dataclass(frozen=True)
class Intent:
intent_id: str
version: int
objective: str
@dataclass(frozen=True)
class ProposedAction:
tool: str
arguments: dict[str, Any]
@dataclass(frozen=True)
class AuthorityDecision:
allowed: bool
reason: str
@dataclass(frozen=True)
class VerificationResult:
outcome: Outcome
evidence: dict[str, Any]
class Reasoner:
def propose(self, intent: Intent, state: dict[str, Any]) -> ProposedAction:
...
class AuthorityGate:
def check(
self,
intent: Intent,
state: dict[str, Any],
action: ProposedAction,
) -> AuthorityDecision:
...
class Executor:
def execute(self, action: ProposedAction) -> dict[str, Any]:
...
class Verifier:
def verify(
self,
intent: Intent,
before: dict[str, Any],
action: ProposedAction,
execution: dict[str, Any],
) -> VerificationResult:
...
Then the run itself is straightforward:
def run(intent, state, reasoner, gate, executor, verifier, log):
action = reasoner.propose(intent, state)
log("action_proposed", action)
decision = gate.check(intent, state, action)
log("authority_decision", decision)
if not decision.allowed:
return VerificationResult(
outcome=Outcome.UNKNOWN,
evidence={"reason": decision.reason},
)
execution = executor.execute(action)
log("execution_result", execution)
result = verifier.verify(intent, state, action, execution)
log("verification_result", result)
return result
This is not enough for every production system.
But it is enough to expose the important boundaries.
And that is where you should start.
What not to add by default
Now we can revisit many mechanisms from this series and ask when they actually earn their cost.
Do you need critique-and-revision?
Add it if one-pass generation produces systematic correctable mistakes and revision measurably improves verified success.
Do not add it because:
critique sounds more agentic
Measure:
single-pass verified success
vs
single-pass + critic + revision verified success
under comparable budget.
If the improvement is negligible, remove the critic.
Do you need multiple candidates?
Add candidate generation if outcome variance is meaningful and candidate selection has a useful signal.
If your verifier is strong, candidate search can be valuable.
If your selector is weak, five candidates may simply create five ways to be wrong.
Measure:
best-of-N gain
selection accuracy
extra cost
latency
cost per verified success
If the selection mechanism cannot reliably distinguish better candidates, more generation may not help.
Do you need tree search?
Add search when the task genuinely has consequential branching and premature commitment is a measured failure.
You probably do not need tree search for:
classify this ticket
extract this field
call this deterministic API
You may need it for:
multi-step code repair
proof search
complex planning
open-ended research
Even then, compare against a simpler generate-and-rank baseline.
Do you need MCTS?
MCTS is not the natural next step after tree search.
Use it when repeated simulation/evaluation can provide useful value estimates and adaptive search allocation beats simpler exploration.
If your reward function is weak, MCTS can efficiently optimize noise.
The relevant question is not:
Can we implement UCB?
It is:
Does adaptive branch allocation improve verified outcomes per unit compute?
Do you need agent memory?
Do not add memory because agents are supposed to remember things.
Ask what information must survive.
You may only need:
current task state
recent tool results
known user preference
A database lookup may beat a vector store.
A small structured profile may beat episodic memory.
Repository state may beat remembered repository facts.
The recurring rule is:
Retrieve authoritative state before retrieving remembered narrative about state.
Do you need learned routing?
Start with deterministic routing when the distinctions are explicit.
if task.type == "sql":
use(sql_specialist)
elif task.type == "code":
use(code_model)
else:
use(default_model)
Only learn the router if:
- deterministic rules leave meaningful performance on the table;
- you have enough routing data;
- you can externally evaluate routing quality;
- you can keep hard policy constraints outside the learned router.
A learned router is another model that can drift.
It needs to earn that operational cost.
Do you need multiple agents?
Probably less often than architecture diagrams suggest.
A single agent with:
several candidate generations
+
independent verifier
may outperform a team of agents exchanging long messages.
Add multiple agents when you have demonstrated value from:
- genuine specialization;
- parallel independent work;
- isolated failure domains;
- explicit role separation;
- independently useful evidence.
Do not add agents merely to assign names like:
Planner
Researcher
Critic
Manager
Supervisor
Architect
Role labels are not competence evidence.
Do you need a durable workflow engine?
Not if the entire task completes quickly in one process and all important side effects are already idempotent.
You begin to need durable workflow semantics when the run must survive:
- worker restart;
- long external jobs;
- human approval;
- timers;
- dependency outages;
- multi-hour or multi-day execution;
- cancellation while suspended;
- durable commitments.
Do not introduce distributed workflow machinery before you have distributed workflow problems.
Do you need a commitment ledger?
If your agent only proposes text, probably not.
If it can create:
reservations
approvals
external jobs
promises
resource holds
scheduled operations
then yes, the distinction between plans and commitments becomes important.
But start from the obligation.
Do not create a commitment subsystem because the concept is elegant.
Do you need transaction compensation?
If the agent performs one atomic external mutation with a reliable idempotent API, perhaps not.
If the agent coordinates several non-atomic external systems, you eventually do.
The trigger is not complexity of reasoning.
It is complexity of external effects.
Do you need a distributed control plane?
A three-function authority module may be enough initially.
Do not create ten microservices for:
intent
competence
authority
security
placement
budget
release
ownership
if all of those concerns can safely exist as narrow modules in one application.
The control-plane boundary is conceptual before it is physical.
Keep the invariants.
Split the deployment only when scaling, ownership, reliability or security boundaries justify it.
Do you need a knowledge graph?
Sometimes.
A graph is valuable when relationships are first-class and graph traversal answers real engineering questions.
But if your task can be answered with:
SELECT ... WHERE ...
use the table.
Do not convert every state store into a graph because the system is called an agent platform.
The complexity budget
Earlier we gave agents compute budgets.
We should give architectures complexity budgets too.
Every mechanism costs something.
Not just runtime tokens.
It creates:
implementation cost
maintenance cost
operational cost
observability cost
failure modes
integration surface
state transitions
on-call burden
migration burden
security surface
benchmark burden
A useful architecture decision should account for all of those.
You can think of a mechanism as having a lifecycle cost:
mechanism value
=
verified failure reduction
-
engineering cost
-
operational cost
-
new failure risk
The exact formula will be domain-specific.
The mindset is not.
Measure marginal value, not theoretical capability
Suppose your baseline coding agent achieves:
verified task success: 72%
cost per run: $0.18
p95 latency: 24 s
You add multi-candidate search:
verified task success: 78%
cost per run: $0.44
p95 latency: 51 s
Then tree search:
verified task success: 79%
cost per run: $1.12
p95 latency: 144 s
Then a critic swarm:
verified task success: 79.2%
cost per run: $2.04
p95 latency: 281 s
The right answer may be:
keep candidate search
remove tree search
remove critic swarm
Even if the last architecture is more sophisticated.
This is exactly why Step 12 insisted on equal-budget benchmarking.
Architecture should be reversible
When possible, add mechanisms behind replaceable boundaries.
For example:
class ReasoningPolicy:
def produce_candidate(self, context): ...
Implementations might be:
OneShotReasoning
GenerateAndRank
TreeSearch
MCTS
That makes architecture a measurable policy choice rather than permanent infrastructure.
Likewise:
class PlacementPolicy:
...
class VerificationPolicy:
...
class RetryPolicy:
...
If a complicated mechanism stops earning its cost, removing it should not require rebuilding the platform.
Deletion is an optimization strategy
Agent teams often talk about adding capabilities.
Production engineering also needs a deletion discipline.
Track mechanisms that are candidates for removal because they:
- no longer improve verified outcomes;
- duplicate another mechanism;
- increase correlated failure;
- create operational burden;
- have become unnecessary as the base model improved;
- can now be replaced by deterministic software;
- were introduced for a workload that no longer exists.
A mature architecture should sometimes become smaller over time.
That is not regression.
It may be evidence that the platform has learned where complexity is unnecessary.
Model improvements should simplify the system when possible
Suppose a new model reduces planning failure enough that a planner/critic loop no longer helps.
Remove it.
Suppose structured-output reliability improves enough that a repair agent no longer adds value.
Remove it.
Suppose tool-use accuracy becomes strong enough that your routing ensemble stops earning its cost.
Remove it.
A better model should not automatically be used to make the same architecture bigger.
Sometimes its best architectural value is that it allows infrastructure to disappear.
Deterministic software should replace agent behavior when the route becomes known
A recurring pattern in agent systems is:
unknown process
↓
agent discovers workable procedure
↓
procedure stabilizes
↓
turn procedure into software
For example, if the model repeatedly learns that the correct operation is:
parse JSON
validate schema
lookup account
call endpoint
verify response
you may not need the model in that path anymore.
The agent helped discover the workflow.
Software should own the workflow once it becomes deterministic.
This is not a failure of the agent.
It is one of the highest-value outcomes of using one.
Keep the verifier even when you simplify the agent
One simplification deserves special caution.
Do not remove the verifier merely because the generator became stronger.
Generator quality and verifier independence are different properties.
A stronger model can reduce failure frequency while still producing confident false successes.
If verification is cheap and authoritative, keep it.
You might remove:
critic
planner
search
extra candidates
multi-agent debate
while preserving:
postcondition verification
That is often a very good trade.
Keep authority outside the model even when you simplify the agent
Similarly, do not collapse authority back into natural-language instructions merely because the agent seems trustworthy.
The minimal version may be very small:
if action.kind == "read":
allow()
elif action.kind == "write" and user_approved:
allow()
else:
deny()
But preserve the boundary.
You can simplify the implementation without removing the concept.
Keep authoritative state outside the model
A simple architecture can still have good state discipline.
For a coding agent:
repository SHA
PR state
test result
approval
may be sufficient.
You do not need a universal state graph.
But do not replace those facts with:
"The assistant remembers that the tests passed."
The smaller the architecture, the more valuable precise boundaries become.
Keep UNKNOWN
This may be the smallest but most important design decision in the entire series.
Do not force every run into:
SUCCESS
FAILURE
Keep:
UNKNOWN
when reality cannot be established.
Examples:
- the provider timed out after a consequential request;
- the verifier is unavailable;
- state changed during execution;
- the external system exposes insufficient reconciliation data;
- authorization state cannot be proven current.
A minimal architecture that preserves UNKNOWN can be safer than a giant architecture that forces certainty.
A practical growth ladder
Instead of starting with Step 44’s full architecture, grow only when failure earns the next layer.
A useful progression is:
LEVEL 0
model
Use for pure low-risk generation where no external effect exists.
Then:
LEVEL 1
model
+
typed tools
Add when the system must take structured actions.
Then:
LEVEL 2
model
+
typed tools
+
external verification
Add when correctness matters.
Then:
LEVEL 3
model
+
typed tools
+
verification
+
authority gate
+
trajectory log
This is a good default minimum production agent.
Then add only when observed failure requires it:
variance -> multiple candidates
premature commitment -> search
uncertain route -> routing
long waits -> durable workflow
retries + side effects -> idempotency/reconciliation
cross-system effects -> compensation/recovery
stale external state -> temporal preconditions
changing objective -> intent versioning
external obligations -> commitment ledger
multiple workers -> leases/fencing
multiple specialists -> explicit coordination
security exposure -> stronger trust boundaries
large platform -> explicit control plane
That is a much healthier way to arrive at the complete architecture.
Example: a minimum coding agent
Suppose the user asks:
Fix the failing unit test and open a draft PR.
A minimum production architecture could be:
1. read repository at exact base SHA
2. run failing test
3. ask model for patch
4. apply patch in isolated workspace
5. run targeted test
6. run required validation
7. verify diff and repository state
8. check write authority
9. create branch/commit/PR using typed GitHub operations
10. verify PR exists and points at expected commit
11. record trajectory
No MCTS.
No agent swarm.
No memory graph.
No learned scheduler.
No workflow engine if the run completes quickly.
No complex capability portfolio.
And yet the important boundaries remain.
That is a production agent.
Example: a minimum research agent
Suppose the user asks:
Compare the current pricing of three APIs.
A minimum architecture might be:
1. classify claim as current-state
2. search/fetch authoritative pricing pages
3. preserve source/time provenance
4. ask model to normalize and compare
5. verify extracted numbers against source evidence
6. return answer with citations
7. log retrieval + reasoning metadata
You do not automatically need:
- multi-agent debate;
- episodic memory;
- durable workflow execution;
- control-plane microservices.
The important requirement is freshness and evidence.
Example: a minimum browser agent
Suppose the user asks an agent to book something.
Now the minimum gets stronger because external side effects matter.
You may need:
intent
current live page state
typed action representation
recipient/price/date confirmation
authority gate
idempotency / transaction identity
postcondition verification
Still, you do not need every mechanism from the series.
Risk determines the floor.
Example: a minimum DevOps agent
A production deployment agent might start with:
current desired release
exact target environment
validated deployment manifest
independent pre-deploy checks
explicit approval boundary
current cluster state
mutation gateway
deployment operation ID
post-deploy health verification
structured audit log
Only if deployments become long-running, multi-region or multi-system do durable workflows, compensation and more sophisticated placement become necessary.
Architecture selection is itself a benchmarkable policy
At this point we can define an architecture selector.
Not a model selector.
An architecture selector.
For each workload class, track:
baseline mechanism set
verified success
false-success rate
UNKNOWN rate
cost
latency
incident rate
operational burden
Then test candidate additions and removals.
A mechanism stays only when the evidence justifies it.
This turns architecture from doctrine into empirical engineering.
The architecture registry
You can even keep a small registry:
ARCHITECTURES = {
"simple_read": {
"tools": True,
"verification": False,
"authority_gate": False,
"search": False,
"durable_workflow": False,
},
"verified_write": {
"tools": True,
"verification": True,
"authority_gate": True,
"search": False,
"durable_workflow": False,
},
"long_running_write": {
"tools": True,
"verification": True,
"authority_gate": True,
"durable_workflow": True,
"idempotency": True,
},
}
Then benchmark those architecture classes against real workloads.
You do not need to enable the full platform for every request.
Complexity can be task-specific
The same system may run different tasks with different architectures.
For example:
summarize file
→ one model call
suggest code change
→ model + repository context + tests
open PR
→ add authority + GitHub verification
deploy to production
→ add current-state checks + approval + idempotency + postconditions
multi-day migration
→ add durable workflow + commitments + transaction recovery
That is better than giving every task the maximum architecture.
Advanced agent engineering is partly the art of not invoking advanced machinery when it is unnecessary.
Keep the simplest mechanism that fixes the measured problem
We can summarize much of the series in one table.
| Measured failure | First mechanism to try |
|---|---|
| malformed actions | typed schemas / deterministic validation |
| output variance | multiple candidates + ranking |
| premature path commitment | simple search |
| poor search allocation | adaptive search / MCTS |
| repeated correctable mistakes | critique + revision |
| long unstable tasks | explicit state + stopping conditions |
| tool ambiguity | narrower tools / routing |
| missing useful history | targeted memory |
| false success | independent verification |
| wasted compute | dynamic budgets |
| vague confidence | typed uncertainty |
| expensive unnecessary observation | value of information |
| duplicated distributed work | leases / idempotency / fencing |
| overload | admission control / backpressure |
| dependency cascades | circuit breakers / bulkheads |
| behavioral degradation | drift detection / rollback |
| unsafe releases | behavioral contracts / promotion gates |
| irreproducible incidents | replay + provenance |
| unclear failure cause | incident forensics |
| reliability ambiguity | SLOs / error budgets |
| unclear investment priority | reliability prioritization |
| autonomy too broad | authority boundaries |
| unknown task regime | competence envelopes |
| capability expansion risk | sandboxed acquisition |
| too many possible capabilities | capability portfolio |
| shared hidden dependencies | dependency graph |
| heterogeneous execution environments | capability-aware placement |
| worker migration | portable execution state |
| stale external state | temporal consistency |
| stale goals | intent versioning |
| durable obligations | commitment ledger |
| multi-day execution | durable workflows |
| partial external side effects | transaction recovery |
| untrusted content controls actions | trust boundaries |
| multi-agent ownership/conflict | explicit coordination |
| platform-wide policy sprawl | explicit control plane |
The important phrase is first mechanism to try.
Not permanent destination.
The final architecture test
Before adding any mechanism, answer these questions:
1. What failure are we fixing?
2. How often does it happen?
3. How costly or dangerous is it?
4. What simpler mechanism could fix it?
5. How will we externally measure improvement?
6. What new failure modes does the mechanism introduce?
7. What is its engineering and operational cost?
8. Can we remove it later?
If you cannot answer those questions, you probably do not yet have enough evidence to add the mechanism.
The final benchmark
The best agent architecture is not the one with the most advanced components.
It is the architecture that produces the best externally verified outcomes for the actual workload under acceptable:
cost
latency
risk
operational complexity
maintenance burden
That may be:
one model call
Or:
model + tools + verifier
Or:
full durable multi-agent control-plane architecture
The architecture is subordinate to the workload.
The deepest lesson from the series
We started with advanced reasoning techniques.
It was easy to imagine that progress meant making the model think harder:
more candidates
more branches
more critics
more agents
more memory
more planning
But as the series progressed, the center of gravity moved.
The most important questions became:
What is the current intent?
What is actually true?
What evidence do we have?
What has this system demonstrated competence at?
What is it authorized to do?
What state may have changed?
What external effects have actually occurred?
What can be verified independently?
What happens when the workflow fails halfway through?
What should remain UNKNOWN?
Those are not primarily model questions.
They are engineering questions.
That is why the complete architecture in Step 44 looked less like a giant prompt and more like a production systems platform.
And then the final correction
But even that complete architecture is not the default answer.
It is a map of where concerns belong when you need them.
The map is useful precisely because it lets you avoid building the entire city for every problem.
Start here:
model
+
typed tools
+
authoritative state
+
external verification
+
small authority gate
+
trajectory log
Then ask:
Where does this fail?
Add the smallest mechanism that directly addresses the observed failure.
Benchmark it.
Keep it if it earns its place.
Remove it if it does not.
And repeat.
The final rule
If you remember one rule from Advanced Agents From First Principles, make it this:
Build the simplest agent that can produce externally verified useful behavior under the authority and reliability constraints that actually matter.
Then let evidence—not fashion, architecture diagrams or the desire to make the system look intelligent—decide what gets added next.
That is the end of the series.
And, in production, it is usually the beginning of the real engineering.