Agent Systems Engineering — how production AI executes work
Published
Your bar: explain how a production agent actually executes work end-to-end — plan, hold state, run the loop, recover from failure, and survive for hours — and run an architecture review that separates real engineering from autonomy theatre. Every module maps the agent onto something you already trust: a runtime, a workflow engine, a distributed system.
An agent run = a long-lived, non-deterministic distributed computation
the runtime is the execution engine — not the model
every failure mode has a distributed-systems precedent
autonomy is a dial set by blast radius
What Is Agent Systems Engineering?
Agent engineering makes one agent work. Agent systems engineering makes it execute work reliably, for hours, under failure, at a cost you can defend. Same jump as script → service.
Is The discipline of running agents as production systems: planning, state, an execution engine, loop control, recovery, orchestration, durability, cost, and observability — the operational layer around the model.
Why it exists A demo agent is a happy-path script. Production adds crashes, timeouts, hostile inputs, runaway loops, multi-hour tasks, and a bill. None of that is fixed by a better prompt; it is fixed by systems engineering.
Like (world) A line cook who can make one dish vs running a restaurant at dinner rush: inventory, tickets, timing, substitutions when the salmon runs out, and a P&L. The recipe was never the hard part.
Like (code)
A main() that calls an API once vs a service: retries, queues, idempotency, observability, autoscaling, on-call. ASE is the move from “it ran on my machine” to “it runs for everyone, always.”
Memory check — 3 questions
- In one line, the difference between agent engineering and agent systems engineering? → Engineering = make one agent work (prompt + tools + loop). Systems engineering = make it execute reliably in production (state, recovery, durability, cost, observability).
- Name three problems that appear only in the third box (agent system) and not the second (agent). → Any three of: re-planning, orchestration across agents, crash recovery / durability, cost control at scale, observability/audit, long-running persistence.
- Why can’t a better model close that gap? → The gap is operational, not cognitive — crashes, budgets, hostile inputs, and multi-hour durability are runtime concerns the model never sees.
Planning Systems — goal → plan → execution
A goal is not executable. Planning turns it into ordered, checkable steps — and re-planning is what separates a system that adapts from one that confidently marches off a cliff.
Plan-then-execute Generate the full plan first, then run it (Plan-and-Solve / Plan-and-Execute2). Cheaper, auditable, parallelizable — but rigid if the world shifts mid-run.
Interleaved (ReAct) Think one step, act, observe, repeat (ReAct1). Maximally adaptive — but more LLM calls, and it can wander without a plan to anchor it.
Like (world) A surgeon’s plan vs the operation. There is a plan, but the moment they open you up and find something unexpected, they re-plan. Sticking to a wrong plan is how people die.
Like (code) A query planner. The optimizer builds a plan from statistics, but an adaptive executor can re-plan mid-flight when row estimates turn out wrong. Static plan = prepared statement; dynamic = adaptive execution.
| Task | Decomposition | Re-plan trigger |
|---|---|---|
| Fix an authentication bug | Reproduce → locate → patch → test → verify | Repro fails, or the “fix” breaks another test |
| Investigate a production outage | Gather signals (logs/metrics/traces in parallel) → hypothesize → confirm → mitigate | Hypothesis disproven by evidence → new branch |
| Generate a monthly billing report | Pull usage → rate → aggregate → render → reconcile | Mostly static — this is a workflow, not an agent (see M14) |
ReAct vs Plan-and-Execute — when do you pick each?
Memory check — 3 questions
- What are the three levels of decomposition granularity to balance? → Too coarse (unverifiable), right-sized (executable + checkable), too fine (token waste / overhead).
- What is the single most important property of a planning system? → The ability to re-plan — discard the stale tail and regenerate when reality diverges from the plan.
- Why is the billing report arguably not an agent task? → The steps are known and stable; a deterministic workflow is cheaper, testable, and debuggable. Agency buys nothing.
State Management — what the agent “knows” right now
The LLM is stateless: pure f(input)→output. Every appearance of memory is the runtime threading state back in. Get this wrong and you get amnesia, or a context that poisons itself.
Stateless agent
- Each request is independent; no carry-over.
- Trivially horizontally scalable; any worker handles any request.
- Crash-safe by default — nothing to lose.
- Cost: re-establish context every time; can’t do multi-step tasks that span requests.
Stateful agent
- Carries plan + history across steps; can do real multi-step work.
- Needs a state store, session affinity or externalized state, and a recovery story.
- Crash mid-task = lost work unless checkpointed (→ M9).
- Failure mode: context bloat & poisoning — stale/wrong state degrades every later step.
Like (world) A consultant with amnesia who reads the entire case file before every meeting. The “file” is your state store; what they can hold in their head for one meeting is the context window.
Like (code) HTTP is stateless; the session is reconstructed from a cookie + server-side store each request. The LLM is the stateless handler; the runtime is the session layer.
Memory check — 3 questions
- Where does agent state actually live, and what is the context window relative to it? → State lives in the runtime/store; the context window is the slice of state assembled for one call.
- One operational advantage of stateless and one of stateful? → Stateless: trivial scaling + crash-safety. Stateful: real multi-step tasks (at the cost of a store + recovery).
- What is context poisoning? → Stale/wrong/irrelevant state accumulating in the window and degrading every subsequent step’s output.
Execution Engines — how steps actually run
Goal → task → subtask → execution. The engine decides the shape: sequential, parallel, or branching. The twist vs a workflow engine: the agent draws the graph at runtime, not at deploy time.
| System | Who defines the graph | Determinism | Best at |
|---|---|---|---|
| Workflow engine (Airflow, Temporal) | Developer, at deploy time | Deterministic | Known multi-step pipelines |
| Queue system (SQS, Kafka) | Developer; decoupled producers/consumers | At-least-once delivery | Buffering, backpressure, fan-out |
| Distributed job system (k8s Jobs, Spark) | Developer; scheduler places work | Deterministic placement | Throughput over a fixed DAG |
| Agent execution engine | The model, at runtime | Non-deterministic | Open-ended tasks with an unknown path |
Is The component that turns the plan into running steps — ordering them, fanning out independent work, gathering results, and choosing branches — while enforcing the runtime’s limits on each step.
Why it exists Sequential-only execution wastes wall-clock on independent work; un-checked branching wanders. The engine is where parallelism, ordering, and dependency tracking are made explicit and safe.
Like (world) A kitchen expediter: some dishes must follow an order (sear before plating), some run in parallel (three pans), and some depend on a taste-test result (more salt or not).
Like (code) A DAG executor — but the DAG is emitted by a non-deterministic planner step by step, so you need idempotency and tracing that a static Airflow DAG gets for free.
Memory check — 3 questions
- The three execution shapes and when to use each? → Sequential (dependent steps), parallel (independent work, cut wall-clock), branching (choose path from a result).
- The defining difference between a workflow engine and an agent execution engine? → Who defines the graph and when: developer-at-deploy (deterministic) vs model-at-runtime (non-deterministic).
- Why run an agent inside a workflow engine? → To borrow durable retries, checkpointing, and observability for the non-deterministic loop.
Loop Control — observe → think → act → repeat
The loop is trivial to write and brutal to control. The hard questions are all about stopping: when, how do you know it worked, and how do you guarantee it can’t run forever or burn the budget.
Like (world) A search party doesn’t stop when a searcher says “found them” — it confirms. And it has a hard rule: turn back at sunset regardless. Self-report plus an independent stop.
Like (code)
A retry library + a watchdog timer + a circuit breaker around a while(!done). The loop body is one line; the control plane around it is the engineering.
Your agent occasionally loops forever and runs up cost. Where do you fix it — and why is it not “the model”?
Memory check — 3 questions
- What are the two categories of stop condition? → Completion (final answer / done tool / verifier passes) and safety (step cap, timeout, repetition, budget, human halt).
- Why is model self-report insufficient for success detection? → The model is frequently wrong about being done — external verification (tests/schema/artifact) is the only reliable signal.
- On retry, what must change and what must be guaranteed? → Change the strategy (don’t repeat the identical failing call); guarantee idempotency so the retry can’t double-apply a side effect.
Human In The Loop — autonomy is a dial, not a switch
The question is never “autonomous or not.” It’s “which actions, at what blast radius, behind which gate.” Reads earn autonomy fast; irreversible writes earn it slowly.
Memory check — 3 questions
- What two properties of an action set its autonomy level? → Reversibility and blast radius (how much damage the worst single call does).
- What does a pre-approval gate require from the runtime? → Durable, resumable state so the agent can pause for a human and survive a restart while waiting.
- What should an agent do when a request is outside its scope or below confidence? → Escalate to a human queue (dead-letter), not hallucinate an answer or force a risky action.
Failure Recovery — the agent is a distributed system
Five things fail: the tool, the model, the context, the plan, the execution. Every one has a distributed-systems precedent. You don’t need new theory — you need to apply the old theory.
| Failure type | Looks like | Primary recovery | Distributed-systems twin |
|---|---|---|---|
| Tool | Timeout, 5xx, rate limit, bad output | Retry (idempotent) → fallback tool | Downstream service failure + circuit breaker |
| Model | Refusal, malformed/invalid tool call, hallucinated args, timeout | Re-prompt / repair, schema-validate, retry on a different tier | Bad RPC response → validate + retry |
| Context | Overflow, lost-in-the-middle, poisoned by stale data | Compress, re-rank, re-inject goal, prune | Cache pollution / memory pressure |
| Planning | Wrong decomposition, impossible step, wrong order | Re-plan (M2); detect via no-progress check | Bad query plan → re-plan |
| Execution | Right plan, wrong action; partial completion; double side effect | Idempotency keys, compensation, checkpoint + resume | Partial write → saga / 2-phase commit |
Like (world) Aviation: a checklist for each failure, a backup system to fall back to, and — when neither works — declare an emergency and hand to ATC. Pilots don’t improvise recovery; they escalate a ladder.
Like (code) Resilience4j / Polly around every external call: retry + circuit breaker + bulkhead + timeout + fallback. The agent’s tools are exactly those external calls.
An agent sent a wrong email / issued a wrong refund mid-task, then the task failed. How do you recover?
Memory check — 3 questions
- The four rungs of the recovery ladder, in order? → Retry → fallback → compensate → escalate.
- When is retry the wrong tool? → Non-idempotent side effects (double-charge) and non-transient failures (refusals, bad plans) — it loops or duplicates.
- What pattern recovers an irreversible side effect? → Compensation (Saga) — a registered undo action, since there’s no rollback for “already sent”.
Orchestration — one agent, a router, or a coordinator + workers
Three topologies, increasing cost. Most teams jump to coordinator+workers because it looks sophisticated. Justify every split exactly like you’d justify carving out a microservice.
Delegation The coordinator owns the goal; it hands a worker one scoped subtask plus exactly the context that worker needs. There is no shared memory — under-specify and the worker fails blind.
Routing Classify, then dispatch. The router owns the decision, not the work. Failure mode: misroute → the wrong specialist confidently handles the wrong thing.
Ownership Exactly one component owns each task’s outcome and its retries. Diffuse ownership = “who was supposed to handle the failure?” = dropped work.
Like (code) Monolith (single) → API gateway with routing (router) → orchestrator fronting microservices (coordinator+workers). The trade-offs transfer one-for-one.
| Use multi-agent when… | Stay single-agent when… |
|---|---|
| Subtasks are genuinely independent & parallel (fan out over 20 files) | Work is sequential with shared state |
| Context is separable and exceeds one window | It all fits in one context |
| Subtasks need distinct toolsets / permissions | One toolset covers it |
| You can attribute & trace each agent independently | You’d struggle to debug “which agent broke” |
Memory check — 3 questions
- The three legitimate topologies in increasing cost? → Single agent → router → coordinator + workers.
- What must the coordinator do that shared-memory systems get for free? → Explicitly assemble and pass each worker’s context, then synthesize outputs — there is no shared state.
- The one-line test for “is multi-agent justified”? → Is the work genuinely independent/parallel or separable-context? If it’s sequential with shared state, stay single-agent.
Long-Running Tasks — surviving minutes, hours, days
A 6-hour task will meet a deploy, a crash, or a rate-limit pause. The in-memory while loop dies with the process. The fix is the durable-execution model: persist, checkpoint, resume.
| Horizon | Example | What must persist | Dominant risk |
|---|---|---|---|
| Minutes | Deep research, multi-file refactor | Plan + partial results in memory/store | Rate-limit pauses, context overflow |
| Hours | Large code migration, dataset processing | Checkpointed state to durable store | Process restart / deploy mid-run |
| Days | Customer investigation, monitoring loop | Durable workflow + event log; resumable across hosts | Drift, stale context, cost creep, human handoff |
Checkpointing Snapshot enough state (history, plan, cursor, artifacts) to resume from a known-good point — not from zero. Frequency trades durability against overhead.
Durable execution Model the run as a workflow whose state is an event log; on restart, deterministically replay to rebuild state, then continue (the Temporal model4).
Like (world) A long expedition with base camps. You don’t restart from sea level after a storm — you resume from the last camp. Camps are checkpoints.
Like (code) Spark stage checkpoints / a resumable DB migration with a version cursor / Temporal workflow replay. The agent loop is just the non-deterministic step inside it.
Design a multi-hour code-migration agent that must survive deploys and crashes. What’s the skeleton?
Memory check — 3 questions
- Why can’t an hours-long task be a plain in-memory loop? → It dies with the process (deploy/crash/restart) and loses all in-flight state.
- What makes resume-from-checkpoint safe? → Idempotent replayed steps — so re-running completed steps doesn’t duplicate side effects.
- What is the durable-execution model in one line? → Persist state as an event log; on restart, deterministically replay to rebuild state, then continue.
Cost Engineering — why agents cost super-linearly
A demo costs cents. The same agent at scale, or in a loop, costs thousands — because history is re-sent every step, so cost compounds. The unit to manage is cost per completed task.
| Lever | What it does | Typical effect |
|---|---|---|
| Prompt caching | Reuse the stable system/context prefix across calls | Large cut on re-sent input tokens |
| History compaction | Summarize / prune old turns so context stops growing | Caps the super-linear term |
| Model tiering | Cheap model for routing/navigation; strong model for the hard step | Most steps at a fraction of the cost |
| Step / cost budget | Hard cap per task + kill switch | Bounds the worst case |
| Cost attribution | Per task + per tenant, with anomaly alert (~3× baseline) | Runaway trips an incident before the invoice |
Like (world) A taxi meter that re-charges for the whole trip so far at every block. The only way to control the fare is fewer blocks (steps) and a cheaper rate (tier) — and a hard ceiling.
Like (code) Egress + per-request compute that scales with payload size, where the payload grows each call. You cache the static prefix and trim the payload, exactly as you would a chatty N+1 API.
Memory check — 3 questions
- Why is cost super-linear in steps? → The whole conversation history is re-sent as input every step, so input tokens grow each call.
- The two levers that flatten the curve? → Prompt caching (stable prefix) and history compaction; model tiering also cuts per-step cost.
- What’s the right unit of cost to track and govern? → Cost per completed task, attributed per tenant, with an anomaly alert and a kill switch.
Observability — “why did the agent do that?”
A non-deterministic system you can’t replay is unknowable. The answer to “why” is always the same: show the exact context the model saw at that step. If you didn’t capture it, you can’t answer.
Like (world) An aircraft flight recorder. After an incident you don’t ask the pilot to remember — you replay the black box. The trace is the agent’s black box.
Like (code) Distributed tracing (OpenTelemetry) for a request that fans out across services — plus the one agent-specific field: the assembled prompt/context each step saw.
A user says the agent did something wrong three days ago. How do you investigate without re-running it?
Memory check — 3 questions
- The single most important field to capture per step, and why? → The assembled context the model saw — without it you can’t reproduce or explain the decision.
- How do traces let you separate a retrieval failure from a reasoning failure? → If the context was wrong/missing → retrieval failure; if context was right but the decision wrong → reasoning failure.
- What property must the audit trail have, and for what? → Immutable / append-only — for compliance, abuse detection, and trustworthy post-mortems.
Production Architecture Reviews
The same lens on five real systems. Reviewing by class beats reviewing by brand — the failure modes cluster by autonomy, blast radius, and how the system holds state.
Reviewed as archetypes, not from privileged internals. Claude Code and Cursor are public coding agents (see Lesson 3); “OpenClaw-style” stands in for the autonomous computer-use / browser-agent class; the support and billing agents are common business designs. Treat specifics as illustrative.
| System (class) | Strengths | Weaknesses / failure modes | Scalability & ops risk |
|---|---|---|---|
| Claude Code coding agent, human-present | Tight HITL (edits visible, approvals); local execution; rich tools; user supplies context | Destructive shell/file actions; prompt injection via repo/web content; long tasks saturate context | Per-user, so scaling is the model API + rate limits; cost is the user’s; main ops risk is sandbox escape |
| Cursor IDE coding agent | Deep editor context (open files, LSP); fast inline loop; retrieval over the repo | Wrong-context edits; retrieval recall misses; multi-file changes hard to verify | Index freshness at repo scale; latency budget; cost per active developer |
| OpenClaw-style autonomous computer-use / browser | Operates real UIs with no API; broad reach across web apps | Highest blast radius (clicks real buttons); brittle to UI drift; prime prompt-injection target via page content | Hard to sandbox; flaky → retry storms; auditing GUI actions is painful; ops risk is acting on the wrong account |
| Enterprise support agent RAG + actions, semi-auto | Deflects volume; consistent answers; escalates the hard cases | Hallucination outside KB; per-tenant data leakage; injection via ticket/page content | Multi-tenant isolation & cost attribution; KB freshness; escalation-queue backpressure |
| Billing agent financial writes, gated | Automates credits/retries/invoices; clear ROI; auditable | Double-charge on non-idempotent retry; compliance exposure; wrong-customer action | Correctness & idempotency are non-negotiable; immutable audit; reconciliation; approval gates above a threshold |
Memory check — 2 questions
- Which archetype has the highest blast radius and why? → The autonomous computer-use/browser agent — it acts on real UIs with no API guardrails and is a prime injection target via page content.
- What is the non-negotiable control for a billing agent? → Idempotency on every write (+ immutable audit + approval gate above a threshold) — to prevent double-charges.
Design Patterns — the reusable shapes
Six patterns cover most production agents. Like GoF patterns, the skill is knowing when not to use one. Each is a named answer to a recurring structural problem.
| Pattern | Solves | Don’t use when |
|---|---|---|
| Planner | Open-ended task needs structure / approval | Steps are fixed → use a workflow |
| Executor | Isolate + validate side-effecting steps | Single trivial tool call |
| Supervisor | Long/expensive runs need a governor | Short cheap tasks (pure overhead) |
| Approval | Irreversible / high-blast actions | Fully reversible low-value actions |
| Retriever | Answers depend on external/fresh data | Self-contained input or known facts |
| Research/Reflection | Broad discovery; quality needs a critic | Narrow lookup — cost > benefit |
Memory check — 2 questions
- Which pattern separates deciding steps from doing them, and what does that buy you? → Planner — inspectable/approvable plans, parallelizable steps, and a clean re-plan boundary.
- When is the Research/Reflection pattern the wrong choice? → Narrow lookups — the parallel fan-out + synthesis + critique costs far more than the task is worth.
Anti-Patterns — how agent projects actually fail
None of these fail in the demo. They fail in week three of production — quietly, then expensively. Each is a default you have to actively resist.
Memory check — 3 questions
- Why is “guardrails in the system prompt” an anti-pattern? → The prompt is advisory and injectable; enforcement (caps, budgets, permissions, idempotency, gates) must live in the runtime.
- What’s the consequence of the “agent for everything” anti-pattern? → Paying non-determinism, latency, and token cost for control flow a workflow or if/else would handle deterministically.
- Why does “autonomy theatre” fail on long tasks specifically? → Per-step errors compound: ~0.99^40 ≈ 67% end-to-end, so long autonomous chains are quietly unreliable.
★ Executive summary
What you now understand (Phase 4)
Fourteen modules, one idea: an agent run is a long-lived, non-deterministic distributed computation. Three things to carry into every review:
The runtime is the execution engine, not the model. Planning, state, the loop, recovery, durability, cost, and observability all live around the LLM. When an agent behaves badly in production, look at the runtime first.
Every failure mode has a precedent. Retries, fallbacks, sagas/compensation, circuit breakers, dead-letter queues, checkpointing, durable execution — you already know this from distributed systems. Apply it; don’t reinvent it.
Autonomy is earned per action, by blast radius. Guardrails belong in the runtime, success needs an external verifier, and “fully autonomous over a long task” is quietly unreliable (0.99⁴⁰ ≈ 67%).
The one diagram to draw
Goal → Planner (decompose + re-plan) → Execution engine (sequential / parallel / branching) → Loop (observe→think→act, runtime stop-gates) → over durable state (checkpoint + resume), with recovery (retry→fallback→compensate→escalate), HITL gates on irreversible actions, and traces + budgets wrapping the whole thing. That’s a production agent.
★ Retrieval practice — Modules 1–14
Q1. Agent cost grows super-linearly with step count primarily because...
Q2. The safe way to recover an agent that already issued a wrong, irreversible refund is...
Q3. The most reliable way to know an agent task actually succeeded is...
Q4. A multi-hour agent must survive a deploy that restarts its process. The right model is...
Q5. To answer "why did the agent do that?" three days later, you must have captured...
★ Interview — pick your bar
Answer out loud in ~60s, then reveal. Core = recall · Senior = trade-offs & failure modes · Staff = synthesis under ambiguity · System Design = open design round (a different axis, not a harder level).
Define agent systems engineering and name its core concerns.
Walk through the agent loop and say exactly when it stops.
What is agent state, and why is the LLM called stateless?
Name the four rungs of agent failure recovery and a one-line example of each.
Why is success detection hard, and how do you make stopping reliable?
Why is multi-agent so often the wrong call, and how do you decide?
Map agent failures onto distributed-systems patterns — and name the one agents get wrong.
An agent's bill 10×'d overnight. Diagnose and design the controls.
Design the execution + durability layer for an agent that runs for hours and survives crashes.
An engineer wants to convert a stable, well-defined business process into an agent. Make the call.
"Ship it fully autonomous." Make the principal-level call on autonomy and reliability.
- Clarify the job: responsibilities, success metric, and the risk profile of its actions.
- Agent or workflow? Put it on the spectrum — reserve agency for genuinely open-ended paths; keep the rest deterministic.
- Planning & execution: decomposition, re-plan triggers, and the execution shape (sequential / parallel / branching).
- State & durability: externalized state, checkpoint granularity, resume-by-replay, idempotent steps.
- Loop control: completion (external verifier) + safety stops (cap, timeout, budget, repetition, halt).
- Recovery: retry → fallback → compensate → escalate; circuit breakers; compensation for irreversible actions.
- Autonomy & HITL: gates by reversibility × blast radius; escalation/dead-letter path.
- Cost: caching, compaction, tiering, per-task budgets + kill switch, per-tenant attribution + anomaly alert.
- Observability: per-step traces with assembled context, immutable audit log, evals gating prompt/model changes.
Design an autonomous incident-investigation agent that runs for days across on-call handoffs.
Design a billing-operations agent that applies credits, retries charges, and updates plans — safely.
★ Agent systems engineering cheat sheet
Concept → engineering translation
| Agent concept | Engineering equivalent | One-line test |
|---|---|---|
| Planning | Query planner / decomposition | ”Can it replace the stale tail of the plan?” If no, it’s a script. |
| State | Server-side session over a stateless handler | ”Remove the re-sent history — does memory vanish?” Yes. |
| Execution engine | DAG executor (drawn at runtime) | “Who defines the graph & when?” Model-at-runtime = agent. |
| Loop control | while-loop + watchdog + circuit breaker | ”What guarantees it terminates?” Runtime caps, not the prompt. |
| Success detection | External verifier / assertion | ”Did a check pass, or did the model just say so?” |
| Failure recovery | Retry / fallback / saga / DLQ | ”Is there a compensation for irreversible actions?” |
| Long-running | Durable execution (Temporal) | “Does it resume from a checkpoint or restart from zero?” |
| HITL | Approval gate / IAM step-up | ”Does a human gate irreversible, high-blast actions?” |
| Cost | Per-task budget + attribution | ”What’s cost per completed task, and the kill switch?” |
| Observability | Distributed tracing + audit log | ”Can you replay the assembled context of any step?” |
Five rules to carry into any agent review
The runtime is the execution engine, not the model. Bad production behavior → look at the runtime first.
The plan is a hypothesis; re-planning is the algorithm. No re-plan path = brittle script.
The model proposes stopping; the runtime decides. Verify success externally; enforce safety stops independently.
Every failure mode has a distributed-systems twin. Apply the old theory; the only new trap is compensation.
Autonomy is earned per action by blast radius. Guardrails live in the runtime; long full-auto chains compound to unreliable.
★ Catalogs & checklists
The portable artifacts — print these. The unifying lens:
an agent request is a long-lived, stateful, non-deterministic session over privileged tools.
Almost every line below follows from that.
Architecture review checklist
Is this even an agent? Could a workflow / plain code do it deterministically?
Planning: is there a re-plan path when reality diverges, or is the plan a one-shot script?
State: is it externalized so any worker can resume, or trapped in process memory?
Execution: where does parallelism live, and is dependency/ordering explicit?
Loop: step cap + wall-clock + budget + repetition enforced by the runtime?
Success: is there an external verifier, or does the agent self-certify?
Recovery: retry/fallback/compensation/escalate mapped per failure type?
Autonomy: gates by reversibility × blast radius; irreversible actions never auto-fire?
Durability: checkpoint + resume; replayed steps idempotent?
Observability: per-step traces with assembled context; immutable audit log?
Cost: per-task budget + kill switch; per-tenant attribution + anomaly alert?
Evals: a harness that gates prompt/model changes against regression?
Production readiness checklist
Termination guaranteed by runtime caps (step + wall-clock), not the prompt.
Budget + kill switch per task and per tenant; anomaly alert at ~3× baseline.
Idempotency keys on every mutating tool; retries can’t double-apply.
Compensation registered for every irreversible action.
Circuit breakers + bulkheads + timeouts per tool and per provider.
Checkpoint + resume for any task > a few minutes; tested by killing it mid-run.
HITL gates on irreversible / high-blast actions; escalation/dead-letter path exists.
Per-step traces (assembled context + output + tokens + cost + status) retained.
Immutable audit log for every mutation; PII/secret redaction in logs.
Prompt-injection defense: tool/RAG outputs tagged as data, never instructions.
Least privilege per agent/tool; read and write paths separated.
Eval set + canary/rollback for prompt and model changes.
Failure mode catalog
| Failure | Trigger | Control |
|---|---|---|
| Runaway loop | No progress / repeated calls; no cap | Step cap + wall-clock + repetition detector |
| Cost explosion | Re-sent history; multi-agent fan-out | Caching, compaction, tiering, budget + kill switch |
| Double side effect | Non-idempotent retry / resume | Idempotency keys; checkpoint before write |
| Unrecoverable side effect | Irreversible action then failure | Compensation (Saga); HITL gate upstream |
| Context poisoning | Stale/wrong data accumulates | Compaction, re-rank, goal re-injection, pruning |
| Lost-in-the-middle | Over-stuffed window | Context budget per section; retrieve, don’t dump |
| Prompt injection | Adversarial tool/RAG content | Tag outputs as data; least privilege; sandbox |
| Silent regression | Prompt/model tweak, no eval | Eval harness gating changes; canary + rollback |
| ”Can’t reproduce” | No trace / no assembled context | Per-step traces; immutable audit log |
| Lost work on crash | In-memory state, long task | Durable workflow: checkpoint + resume |
| Compounded unreliability | Long full-auto chain | HITL gates; shorten chains; external verifiers |
| Noisy neighbor | One tenant starves quota/cost | Per-tenant isolation, quotas, attribution |
Design pattern catalog
Planner (decide vs do · skip if steps fixed) · Executor (isolate side-effecting steps · skip if one tool) · Supervisor (govern long/expensive runs · skip if short) · Approval (gate irreversible actions · skip if reversible) · Retriever/RAG (ground in external data · skip if self-contained) · Research/Reflection (parallel discovery + critic · skip narrow lookups) · Router (classify & dispatch · skip if one path) · Coordinator+Workers (parallel/separable work · skip if sequential shared-state).
Anti-pattern catalog
Agent for everything (workflow would do) · Multi-agent overuse (sequential shared-state work split into agents) · Unlimited autonomy (no gates on irreversible actions) · Poor context (dump-everything → poison + cost) · Missing observability (no traces → “can’t reproduce”) · No evaluation (silent regressions) · No guardrails (limits live in the prompt) · Autonomy theatre (demo-grade shipped as production).
VP Engineering review questions
“Why is this an agent and not a workflow? What’s the irreducible uncertainty agency buys us?”
“What’s the per-step success rate, and therefore the end-to-end rate over a full task?” (0.99⁴⁰ ≈ 67%.)
“What guarantees the loop terminates — show me the runtime cap, not a prompt sentence.”
“Enumerate every irreversible action. For each: what’s the gate, and what’s the compensation?”
“Where does state live if a worker dies at step 40 of 60? Walk me through the resume.”
“What’s cost per completed task, the kill switch, and the per-tenant anomaly alert?"
- "Show me how you debug a wrong action from three days ago without re-running it.”
“I change one prompt line — what automatically catches a 5% regression before it ships?"
- "Why this topology? Justify every agent split like a microservice boundary.”
★ Revision guides & what to learn next
5-minute weekly recall
Recite from memory, no looking:
The one-line definition: an agent run is a ______ computation. (long-lived, non-deterministic, distributed.)
Draw the production-agent diagram: Goal → Planner → Execution engine → Loop, over durable state, with recovery + HITL + traces.
- Two stop categories and the members of each (completion vs safety).
- The four recovery rungs in order, and the one agents get wrong.
- Why cost is super-linear, and the two levers that flatten it.
- The microservice test for “is multi-agent justified?”
Stuck on one? Re-read that module’s .rule band, close it, try again. Recall > re-reading.
30-minute deep dive (before a big review)
Planning & loop — Read the ReAct and Plan-and-Solve abstracts; from memory, draw the plan→execute→re-plan cycle and label where each lives.
Patterns — Re-read Anthropic’s “Building effective agents”; map prompt-chaining, routing, parallelization, orchestrator-workers, evaluator-optimizer to Modules 8 & 13.
Durability — Read the Temporal “durable execution” overview; restate checkpoint/replay/idempotency in agent terms (M9).
Observability — Skim the OpenTelemetry GenAI semantic conventions; list the span attributes you’d require per step (M11).
Apply it — Take one system from Module 12 and run the full architecture-review checklist on it out loud. Could you defend it to a CTO?
Roadmap — what to learn next
| Topic | Why next | Start here |
|---|---|---|
| Agent evaluation & testing | The hardest unsolved production problem — you can’t ship changes safely without it. The natural Phase 5. | Anthropic eval guide; Braintrust; LangSmith |
| Durable execution in depth | The backbone of long-running agents; learn it as a primitive, not a library. | Temporal docs; “durable execution” patterns |
| Agent security (deep) | Prompt injection, tool abuse, data exfiltration scale with autonomy. | OWASP LLM Top 10; Anthropic RSP |
| Context engineering at scale | Retrieval, ranking, compaction are where production leverage and cost live (Phase 3, deeper). | Revisit Lesson 2; pgvector + rerankers |
| Build one end-to-end | Nothing cements it like shipping. Build the billing or investigation agent with real durability + traces. | Claude API + MCP SDK + a workflow engine |
These notes reflect my current understanding and are updated as I learn, build, and discover better explanations.