Skip to content

Chapter 4: Technical Foundations of the Modern Agent

Orientation Note: This is the densest chapter of the volume. It unifies the cognitive architecture of autonomous agents, reasoning patterns (ReAct and its variants), context architecture, production execution harness design, and the translation of Clean Code and SOLID into synthetic codebases. See the Reading Guide in the front matter.

From Raw Text Sequences to Cognitive Systems

Section titled “From Raw Text Sequences to Cognitive Systems”

The most critical conceptual leap for an engineer transitioning from classical software engineering is recognizing that a modern agent is not a “glorified chatbot.” It is a cognitive system with explicit internal architecture: perception, internal state, reasoning, action, and persistent memory, organized around a foundation language model serving as an inference and planning engine.

The reference architecture directly descends from classical agent theory Russell & Norvig, 2020, translated into the foundation model era across five core subsystems:

Diagram 4.1: Internal Architecture of a Modern Agent

  1. The Model (Reasoning Engine): An API-accessible foundation model, swappable and strictly versioned.
  2. The Context (Perception + Working Memory): System instructions, conversation trajectories, tool execution returns, and injected RAG knowledge chunks.
  3. The Tools (Effectors): Typed, executable interfaces exposed to the model.
  4. The Memory (Persistent State): External persistence (filesystems, vector indexes, relational/document databases) surviving beyond transient inference sessions.
  5. The Harness (Execution Runtime): The host code executing the agentic loop, enforcing permission boundaries, recording immutable audit logs, and bounding compute spend. The harness is the software layer that model providers do not provide—and which ultimately defines the true security and reliability perimeter of the system.

The ReAct Pattern: The Algorithmic Bedrock

Section titled “The ReAct Pattern: The Algorithmic Bedrock”

The ReAct (Reasoning + Acting) pattern serves as the foundational algorithm powering modern autonomous agents Yao, Zhao, et al., 2023. Its breakthrough, empirically validated across reasoning and decision benchmarks, demonstrated that interleaving step-by-step reasoning traces with concrete environmental actions consistently outperforms both pure reasoning (which hallucinates detached from reality) and pure action (which acts blindly without planning):

ReAct Cycle:
1. THOUGHT: "I need to discover which Python source files exist across the repository"
2. ACTION: glob(pattern="**/*.py")
3. OBSERVE: ["src/main.py", "src/agents/orchestrator.py", "tests/test_agent.py"]
4. THOUGHT: "Found 3 files. The most relevant target is orchestrator.py"
5. ACTION: read_file("src/agents/orchestrator.py")
6. OBSERVE: [file content payload]
7. THOUGHT: "The codebase implements pattern X. The synthesized response to the user is..."
8. ANSWER: [final response returned to user]

Every loop iteration consumes inference tokens; every iteration incurs financial and latency costs. Mastering ReAct is the prerequisite to diagnosing and mitigating Token-Burn: the count of loop cycles per business task represents the foundational unit-economic variable of agentic software, governed by termination criteria, iteration budgets, and tool schemas engineered to minimize failed attempts.

# Example 4.1: Minimal production-grade agentic loop using the Anthropic API.
# This represents the skeleton of EVERY agent: a while-loop alternating
# inference and tool execution until the model emits a termination token.
import json
import anthropic
client = anthropic.Anthropic()
TOOLS = [{
"name": "get_weather",
"description": "Retrieves the current weather for a city. USE when the "
"user asks about current temperature or meteorological conditions.",
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string", "description": "City name"}},
"required": ["city"],
},
}]
def execute_tool(name: str, tool_input: dict) -> str:
if name == "get_weather":
# In production: invocation of live meteorological microservice
return f"22°C and clear skies in {tool_input['city']}"
return f"Unknown tool: {name}"
def run_agent(user_input: str, max_iterations: int = 10) -> str:
"""ReAct execution loop with an explicit iteration budget cutoff."""
messages = [{"role": "user", "content": user_input}]
for _ in range(max_iterations): # ALWAYS bound the loop
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=4096,
tools=TOOLS,
messages=messages,
)
if response.stop_reason != "tool_use":
return next(b.text for b in response.content if b.type == "text")
# The model requested tool invocation: execute and feed back results
messages.append({"role": "assistant", "content": response.content})
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result,
})
messages.append({"role": "user", "content": tool_results})
return "Iteration budget exhausted without reaching a final answer."

Three implementation details in this code represent critical production lessons. First, the loop is strictly bounded (max_iterations): an agent without an invariant termination condition is a runaway billing incident waiting to happen. Second, the raw assistant response content—including tool invocation blocks—is appended back into the trajectory history: API protocol contracts mandate this, and omitting it is the most common junior bug. Third, every returned tool result payload includes the exact tool_use_id that triggered it: distributed traceability begins at the protocol level.

Beyond ReAct: The Taxonomy of Reasoning Patterns

Section titled “Beyond ReAct: The Taxonomy of Reasoning Patterns”

ReAct does not stand alone. Research spanning 2022–2024 established a family of reasoning patterns that every AI Engineer must master, as each trades compute tokens for accuracy along distinct curves:

  • Chain-of-Thought (CoT). Prompting the model to decompose reasoning into intermediate steps before generating an answer measurably enhances performance on multi-step analytical tasks Wei, Wang, et al., 2022. It represents the most compute-efficient pattern: a single inference pass resulting in higher output token density. Frontier models now integrate this natively as “extended thinking” or “adaptive reasoning,” where the model dynamically determines reasoning depth.
  • Tree of Thoughts (ToT). Generalizing CoT into an exploratory search tree: generating multiple candidate reasoning branches, self-evaluating intermediate states, and backtracking upon dead ends Yao, Yu, et al., 2023. Multiplies token expenditure significantly; reserved for complex search and architectural planning where initial hypotheses are frequently suboptimal.
  • Self-Refine. The model critiques its own synthesized draft and refines it across iterative evaluation passes without parameter updates, yielding average gains of ~20% in human preference benchmarks across varied domains Madaan et al., 2023.
  • Reflexion. Following a verifiable failure (a broken unit test, an unhandled exception, a schema validation error), the agent synthesizes a verbal retrospective of the root cause, persists it to episodic working memory, and re-executes with that diagnostic context injected into the prompt Shinn et al., 2023. This serves as the foundational algorithm for the self-reflection loops detailed in Chapter 8.

The architectural selection rule is governed by unit economics: CoT by default; Self-Refine when automated heuristic quality checks exist; Reflexion when deterministic binary pass/fail verification signals exist; ToT exclusively when complex combinatorial solution spaces demand non-linear exploration. Ascending this taxonomy increases unit cost per task; Volume 4, Chapter 1 provides the mathematical framework for budgeting these trade-offs.

A widespread, costly architectural misconception is treating the transformer context window as reliable long-term memory. Empirical reality proves otherwise: model recall degrades precipitously when target information is situated in the middle of extended context windows, following a pronounced U-shaped curve where attention concentrates predominantly at the start and end of the prompt Liu et al., 2024. The architectural design consequences:

  1. Information Position Dictates Attention. Mission-critical system invariants and primary task definitions must be positioned at the absolute start (System prompt) or the absolute end (Final User turn), never buried within massive raw documentation dumps.
  2. Precision Outperforms Volume. Injecting precisely targeted, semantically relevant chunks via tuned RAG pipelines consistently outperforms dumping entire source repositories into the prompt, both in generation accuracy and token spend.
  3. Long-Term Memory Must Be Externalized. Frameworks like MemGPT formalize the operating systems analogy: a multi-tiered memory hierarchy where the context window functions as scarce, volatile RAM, and external vector/relational stores serve as persistent disk storage, with the model itself orchestrating what to page in, page out, and persist Packer et al., 2024.

Extended Thinking: The Deliberative Agent Frontier

Section titled “Extended Thinking: The Deliberative Agent Frontier”

The emergence of models equipped with extended thinking capabilities (formalized across 2024–2025) fundamentally reshaped agentic architecture. Empirical benchmarks demonstrate that dynamic test-time compute scaling represents a vector of optimization distinct from parameter scaling: on complex reasoning tasks, allocating more compute during inference proves dramatically more efficient than training larger models Snell et al., 2024.

This reality yields two primary architectural implications. First, the classic dichotomy between fast heuristics (System One) and deliberate analytical reasoning (System Two)—originally advanced in cognitive science by Kahneman (2011)—finds a direct computational analog in frontier architectures: models like OpenAI o1 (2024) and Claude’s extended thinking runtime Anthropic, 2024 synthesize extensive internal chain-of-thought traces spanning thousands of hidden tokens before emitting user-facing outputs. Second, this introduces a new systems configuration parameter—the thinking budget—which the AI Engineer must govern with the identical rigor applied to ReAct iteration budgets.

The foundational engineering rule is straightforward: not every task warrants extended thinking. Inference costs can exceed conventional calls by an order of magnitude; enabling deep deliberative reasoning on basic entity extraction is equivalent to solving differential equations to balance a checkbook. The selection heuristic aligns with classical systems engineering:

Operational Workload Standard Reasoning (CoT) Extended Thinking
Classification, structured entity extraction ✓ Sufficient ✗ Over-engineered waste
Moderate code generation and unit testing ✓ Sufficient ✗ Unless security-critical invariants apply
Multi-step formal mathematical reasoning ✓ Limited reliability ✓ High ROI when errors carry high cost
High-consequence architectural planning ~ Boundary of reliability ✓ Fully justified
Complex distributed production incident triage ~ High risk of hallucination ✓ Deep deliberation protects enterprise SLAs
# Example 4.2: Extended thinking with an explicit token budget.
# The thinking_budget functions as the max_iterations counterpart for internal deliberation.
# Reserve exclusively for workloads where the cost of a defect dwarfs compute costs.
#
# NOTE: Requires models supporting extended thinking.
# Verify Anthropic documentation for active model support and pricing.
import anthropic
client = anthropic.Anthropic()
def analyze_complex_architecture(
description: str,
thinking_budget: int = 10_000,
) -> dict:
"""
Architectural risk analysis leveraging extended thinking.
Potential compute cost: 10–20× a conventional inference pass.
"""
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=16_000,
thinking={"type": "enabled", "budget_tokens": thinking_budget},
messages=[{
"role": "user",
"content": (
"Analyze this system architecture and determine: "
"(1) The top three risks ranked by probability × blast radius, "
"(2) The most urgent design decision requiring immediate refactoring, "
"(3) The lowest-risk migration path if a critical flaw is detected.\n\n"
f"Architecture Specification: {description}"
),
}],
)
reasoning_tokens, text_content = 0, ""
for block in response.content:
if block.type == "thinking":
reasoning_tokens = len(block.thinking.split())
elif block.type == "text":
text_content = block.text
return {
"analysis": text_content,
"estimated_reasoning_tokens": reasoning_tokens,
"estimated_cost_usd": (
(response.usage.input_tokens / 1_000_000) * 5.00
+ (response.usage.output_tokens / 1_000_000) * 25.00
),
}

On empirical benchmarks, the AIME 2024 Olympic mathematics competition demonstrated that standard models solved under 15% of problems, whereas extended thinking models exceeded 70% accuracy OpenAI, 2024. In software engineering, SWE-bench Verified (the curated edition of the benchmark Jimenez et al., 2024) proved that agents using extended thinking achieved a 40% relative improvement over standard CoT when resolving real-world repository defects. These benchmarks formalize the class of problems where test-time compute scaling generates positive ROI.

Resilience in Production Agents: The Harness as a Control Plane

Section titled “Resilience in Production Agents: The Harness as a Control Plane”

Production failure modes in agentic systems differ fundamentally from deterministic microservices. Unlike classical REST endpoints—where failures are discrete binary events (200 OK vs. 500 Internal Server Error)—an autonomous agent can fail silently and continuously: synthesizing plausible-looking outputs that omit the single mission-critical validation check, or operating correctly 95% of the time while failing on subtle edge cases that escape manual review. Three resilience patterns must be implemented immediately:

Agentic Circuit Breaker. Adapted from Fowler’s classical distributed pattern (2002), modified for non-deterministic execution: it monitors the moving failure rate of agent cycles over a rolling time window; if failures exceed the threshold, it trips the circuit open and routes traffic to a deterministic fallback rather than allowing the agent to burn tokens in a corrupted state.

Exponential Backoff with Jitter and State Persistence. While ReAct incorporates implicit loop retries, production retries require state persistence: the agent must snapshot its partial reasoning trace before retrying to prevent duplicating completed computation. The Reflexion pattern Shinn et al., 2023 formalizes this inter-cycle state management.

Per-Tool Confidence Budgets. Every registered tool tracks its rolling success rate within the session; if a tool encounters $N$ consecutive runtime failures, the harness dynamically revokes its availability and issues an operational alert. The audit log provides all necessary state without external APM tooling.

# Example 4.3: Minimal Agentic Circuit Breaker.
# Confidence budgets per tool follow an identical data structure.
from collections import deque
from dataclasses import dataclass, field
@dataclass
class DisyuntorAgéntico:
"""
Trips the circuit open when the failure rate of agentic cycles
exceeds the threshold across the configured rolling window.
Stateless per session: instantiated per agent run.
"""
tamaño_ventana: int = 10
umbral_fallo: float = 0.5
_resultados: deque = field(
default_factory=lambda: deque(maxlen=10))
_abierto: bool = False
def registrar(self, exito: bool):
self._resultados.append(exito)
if len(self._resultados) == self.tamaño_ventana:
tasa = 1 - sum(self._resultados) / len(self._resultados)
self._abierto = tasa >= self.umbral_fallo
@property
def esta_abierto(self) -> bool:
return self._abierto
def flujo_degradado(self, peticion: str) -> str:
"""Invoked when circuit is tripped open: never fail silently."""
return (
f"Agent operating in degraded fallback mode. Payload queued "
f"for human-in-the-loop review: {peticion[:100]}…"
)
# English alias for export compatibility
AgenticCircuitBreaker = DisyuntorAgéntico

■ EXECUTIVE TRACK: The Four Dimensions of an Agentic SLA

A traditional availability SLA (expressed as percentage of server uptime) is dangerously insufficient for agentic systems: an agent service can maintain 99.99% uptime (responding in under 500 ms) while generating syntactically defective code on 20% of requests. A robust enterprise SLA must codify four dimensions:

  1. Technical Availability: Percentage of requests returning valid HTTP responses without runtime infrastructure crashes. Measured via standard APM tooling.
  2. First-Pass Human Acceptance Rate: Percentage of agent outputs approved by human reviewers without manual edits. This is the definitive quality metric; without it, reported velocity gains are optical illusions (Peng et al., 2023; Ziegler et al., 2024).
  3. Cost per Completed Business Task: Unit economic cost per resolved business milestone rather than raw inference invocations; directly mapped to the Cost per Useful Iteration (CIU) metric in Volume 4, Chapter 1.
  4. End-to-End Cycle Latency: Total elapsed time from task inception to verified final artifact, encompassing all intermediate ReAct cycles and tool executions. This reflects the actual business turnaround time experienced by stakeholders.

An executive leadership team greenlighting agent adoption without codifying these four SLA dimensions is adopting technology without success criteria. What is not defined cannot be measured; what is not measured cannot be governed.

Worked Exercise 4.1: Architect a Production Execution Harness

Section titled “Worked Exercise 4.1: Architect a Production Execution Harness”

Problem Statement. A contract analysis agent has operated in production for three weeks, averaging 2.3 iterations per document. Telemetry reveals that specific contracts trigger 15+ loop iterations before exhausting the compute budget without delivering a usable output. Architect the three harness modifications required to diagnose and remediate the pathology.

Walkthrough Solution. The three modifications follow a strict sequence: telemetry, protection, and capability enhancement:

Telemetry: Ingest document-level metadata (byte size, language, clause typology) into the structured audit log. Clusters of 15+ cycles almost invariably correlate with a specific edge case: non-standard PDF encodings, multi-lingual agreements, or complex tables that OCR extractors corrupt. Without diagnostic telemetry, debugging is blind guesswork.

Protection: Implement a circuit breaker calibrated against historical percentiles rather than arbitrary maximums. If the $p_{95}$ of successful runs is 4 cycles, a budget of 10 is reasonable; allowing 15+ cycles is an unmonitored spend incident. The breaker must escalate rather than silently terminating: contracts tripping the threshold are enqueued for human review accompanied by their full execution trace.

Capability Enhancement: Once the edge case is isolated, the solution is rarely “expand the token budget”; it is engineering a specialized tool (a tabular parser, a character set normalizer) that collapses iterations back down to 2–3. The cardinal engineering rule: agentic performance bottlenecks are almost always tool design flaws, never foundation model token shortages.

Harness Decoupling: Typed Control Planes (System One) and Persistent Agents

Section titled “Harness Decoupling: Typed Control Planes (System One) and Persistent Agents”

The evolution of production harnesses in 2026 solidified a paradigm shift away from monolithic ReAct loops: decoupling deterministic control flow from generative text inference. In early harnesses, a single deliberative model (System Two) was tasked with everything: semantic comprehension, prose generation, selecting tools from large JSON schemas, auditing security permissions, and judging termination. In production, this architecture suffers from three structural flaws:

  1. Syntactic Overhead: Requiring a foundation model to output freeform prose interleaved with strict JSON blocks induces formatting failures, burning tokens on syntax retries.
  2. Accumulated Latency: Invoking a heavy reasoning model simply to evaluate whether a read-only tool invocation is safe injects seconds of unnecessary latency per cycle.
  3. Adversarial Coupling: Environmental state and security policies share the identical context window, exposing control flow to indirect prompt injections from untrusted external data.

To resolve this fragility, architectures such as Jev (TypeSafe AI, 2026) enforce strict separation between deliberation and execution control via a System One control plane:

  • Inference Without Text Generation: The control runtime generates neither markdown prose nor JSON schemas. It evaluates typed probability distributions over constrained types (Choice for tool selection, Score for risk estimation, and Noul for boolean confirmations).
  • The Four-Stage Execution Cycle:
    • SELECT: Pinpoints the target tool from the registry satisfying the objective via Choice.
    • GATE: Concurrently evaluates whether the action is destructive, computes its blast radius, and checks reversibility. The architectural invariant is non-negotiable: the gate advises, the runtime enforces. If an action is destructive against external environments, the runtime denies (deny) execution automatically without human fatigue.
    • EXECUTE: Executes within a sandboxed runtime (sandbox.ts) where arguments are extracted deterministically by code (arguments.ts), treating untrusted text strictly as passive data.
    • JUDGE: Evaluates completion and loop stagnation, guarded by an immutable step limit.
  • Dependency Inversion (DIP) for Offline Testing: The harness programs to an abstract Decider interface. This allows teams to hot-swap the real foundation model with a deterministic FakeDecider in CI, testing 100% of sandboxing branches and edge cases instantaneously at zero token cost.

At an organizational level, this isolation principle is mirrored in Dots (OpenAI, 2026): persistent digital coworkers operating within isolated cloud sandboxes governed by a centralized control plane. Rather than unmonitored monolithic agents connected haphazardly, Dots enforce strict bounded contexts and communicate via typed asynchronous events, ensuring that enterprise security policies and observability invariants reside in infrastructure rather than the fragility of a prompt.

Synthetic Clean Code: The Enduring Principles

Section titled “Synthetic Clean Code: The Enduring Principles”

Software technologies decay; foundational principles endure. Clean Code established that code is written primarily for human readers and that readability is an economic rather than aesthetic imperative Martin, 2009; Refactoring codified that improving internal structure without altering external behavior is a disciplined science Fowler, 2018. Neither text mentions foundation models, yet both describe precisely how to engineer reliable agentic systems—because the core artifacts of the agentic era (prompts, tool schemas, agent skills, orchestrators) are structured text evaluated by a fallible interpreter. That is what software source code has always been.

We formulate the Synthetic Clean Code paradigm: the direct translation of classical software engineering principles into synthetic agentic systems:

Classical Principle In Traditional Code (Martin, 2009; Fowler, 2018) In Synthetic Agentic Systems
Meaningful Names Variables named after their contents A tool or skill’s name IS its prompt: search_technical_documentation is invoked reliably; helper2 is misinvoked or ignored
Single Responsibility (SRP) A function executes one task A tool executes a discrete action; an agent embodies a discrete role; a skill encapsulates a discrete procedure. The “do-everything agent” is the god class of this decade
Honest Comments Explains the why, never the obvious what Tool descriptions declare when to use and when NOT to use, rather than restating the JSON schema
Explicit Errors Typed exceptions, never magic error codes Tool returns with is_error=True and actionable diagnostics: “City not found; provide ‘City, Country’ format” enables self-correction; “Error 500” forces blind guessing
DRY (Don’t Repeat Yourself) A single authoritative source of truth Master system prompts and versioned templates (Chapter 5); model identifiers and pricing centralized in single modules
Boundaries Clean interfaces isolating third-party code Strict Bounded Contexts (Chapter 6) and absolute separation of instructions from untrusted data (Volume 4, Chapter 4)
Tests First Automated tests define expected behavior Automated evals define quality baselines before optimizing prompts (Volume 4, Chapter 3)
The Boy Scout Rule Leave the codebase cleaner than you found it Leave the prompt cleaner than you found it: every production incident terminates in a versioned commit to the prompt, skill, or context harness

Two implications of this matrix warrant emphasis. First: prompt refactoring is real software engineering, practiced with the identical discipline of code refactoring: incremental changes verified against regression evals before and after every commit Fowler, 2018. Second: pull request reviews for prompts are non-negotiable; pushing unreviewed prompt modifications to production is deploying untracked commits directly to main.

This represents the architectural thread uniting this volume: Chapter 5 applies these principles to agent roles and master prompts; Chapter 6 to domain boundaries; Chapter 7 to agent skills and templates; Chapter 8 to multi-agent orchestrators; and Chapter 9 to MCP servers.

SOLID as an Interrogation: Refactoring Questions for Agents

Section titled “SOLID as an Interrogation: Refactoring Questions for Agents”

The preceding matrix translates principles into theory; actionable engineering requires operational execution. A principle stated abstractly is affirmed nod-and-forget style; a principle formulated as an interrogation is an executable algorithm. The difference is that between “classes should have single responsibilities” and “what second, unstated reason for change is concealed within this class?”. The former decorates a slide; the latter catches bugs.

The author synthesized the five SOLID principles Martin, 2017 as an active refactoring questionnaire, which gains transformative power in the agentic era: these identical questions form the system prompt of an automated architectural review agent. What once lived as an expert engineer’s mental checklist becomes an automated code review skill (Chapter 7) executed against every pull request.

Diagram 4.2: SOLID as a Refactoring Interrogation: Questions That Transform Each Principle into an Executable Procedure (Figure Published by the Author)

The interrogation, principle by principle:

  • Single Responsibility Principle (SRP). How can this class or function be decomposed into smaller units with single responsibilities? What secondary responsibilities can be extracted? In agentic systems, the question translates directly: What does this agent execute beyond its declared domain role? The reviewer that also categorizes and the categorizer that also drafts responses represent the prompt god class.
  • Open/Closed Principle (OCP). How can this class be restructured to be open for extension but closed for modification? What design pattern facilitates future extensions? In multi-agent swarms: Can a new domain specialist be onboarded without refactoring the central orchestrator? If onboarding a role requires modifying the control loop, the orchestrator is tightly coupled to implementation details (Chapter 8).
  • Liskov Substitution Principle (LSP). Can this subclass substitute for its parent without breaking system invariants? Do subclasses honor the base contract? Its agentic analog is the tool contract: Does an alternative model adapter (Chapter 3) honor the identical input/output schema, or does it introduce unhandled edge cases?
  • Interface Segregation Principle (ISP). Does this interface declare excessive methods? How can it be partitioned into targeted interfaces? For autonomous agents: A tool exposing fifteen optional parameters represents an ISP violation; models hallucinate over fat schemas, whereas three specialized tools yield deterministic invocations.
  • Dependency Inversion Principle (DIP). How can dependencies be inverted to depend on abstractions rather than concrete implementations? This embodies the core thesis of Volume 4, Chapter 6: “the foundation model is a low-level detail.” Core domain logic must depend on an abstract inference port, never a vendor SDK.

Closing the loop, the general architectural improvement questions appended to the five principles: What design patterns elevate system maintainability? How can clarity be improved without altering runtime behavior? Which subsystems are hardest to test, and why? That final question forms the bridge to Volume 4, Chapter 3: what is difficult to test is almost always poorly architected, and in agentic software, what cannot be evaluated cannot be governed.

Formulating SOLID as an interrogation yields a dual benefit. For human engineers, it translates abstract theory into concrete review actions. For autonomous agents, the questions become the prompt: a design-review skill traversing this questionnaire across a Git diff produces actionable architectural findings rather than the generic praise (“looks good to me!”) that represents the default failure mode of unguided LLM reviewers. Fowler’s refactoring discipline (2018)—micro-steps verified by regression tests before and after—governs execution: the agent proposes the refactoring; the human engineer approves it; automated evals verify behavioral invariants remain intact.

Worked Exercise 4.2: Two Tools, an Iteration Budget, and an Actionable Error Contract

Section titled “Worked Exercise 4.2: Two Tools, an Iteration Budget, and an Actionable Error Contract”

Problem Statement. Extend the minimal agentic loop (Example 4.1) by implementing: (a) a secondary tool convert_temperature, (b) actionable error propagation via is_error, and (c) an automated test verifying that the loop budget is strictly enforced under cascading tool failures.

Walkthrough Solution.

# Solution 4.2 — Extended tool definitions and error handling
TOOLS = [
{
"name": "get_weather",
"description": "Retrieves the current weather for a city. USE when the "
"user asks about current temperature or meteorological conditions.",
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string", "description": "City name"}},
"required": ["city"],
},
},
{ # (a) Secondary tool: name = verb + noun, unambiguous semantics
"name": "convert_temperature",
"description": "Converts temperature between Celsius and Fahrenheit. USE when "
"the user explicitly requests conversion or asks for "
"weather in a unit different from the source data.",
"input_schema": {
"type": "object",
"properties": {
"value": {"type": "number"},
"to_unit": {"type": "string", "enum": ["C", "F"]},
},
"required": ["value", "to_unit"],
},
},
]
def execute_tool(name: str, tool_input: dict) -> tuple[str, bool]:
"""Returns (content, is_error). Errors MUST provide ACTIONABLE instructions."""
if name == "get_weather":
city = tool_input.get("city", "").strip()
if not city:
# (b) Error that explicitly instructs the model on how to self-correct:
return ("Empty city provided. Retry providing a valid city name, "
"e.g., 'Lima' or 'San Francisco'.", True)
return (f"22°C and clear skies in {city}", False)
if name == "convert_temperature":
v, u = tool_input["value"], tool_input["to_unit"]
return (f"{v * 9 / 5 + 32:.1f}°F" if u == "F"
else f"{(v - 32) * 5 / 9:.1f}°C", False)
return (f"Unknown tool: '{name}'. Check tool registry.", True)

In the main execution loop, tool outputs are returned with their error status flags: {"type": "tool_result", "tool_use_id": block.id, "content": content, "is_error": is_error}. For requirement (c), verification is a deterministic unit test (Tier 1 of the testing pyramid in Volume 4, Chapter 3): mocking execute_tool to always return an error, the loop must terminate in exactly max_iterations cycles and return the budget exhaustion error payload.

Why This Matters. These three modifications represent Synthetic Clean Code in miniature: tools that describe their invocation boundaries, error messages that teach self-correction, and iteration budgets that are unit-tested. Actionable error reporting is the single highest-leverage optimization for increasing agentic self-healing rates in production, yet remains the most widely omitted.

  • A modern agent = Model + Context + Tools + Memory + Harness; the harness is authored by you and establishes the true security perimeter.
  • ReAct interleaves reasoning and action Yao, Zhao, et al., 2023; every cycle incurs cost; execution loops must ALWAYS be strictly bounded.
  • Apply CoT by default; Self-Refine with automated heuristics; Reflexion with deterministic verification signals; ToT exclusively when complex search spaces demand branching.
  • Context windows are not persistent memory: position matters, precision beats volume, and long-term state must be externalized (Liu et al., 2024; Packer et al., 2024).
  • Harness decoupling (System One / Jev TypeSafe AI, 2026) and persistent execution sandboxes (Dots OpenAI, 2026) migrate critical governance invariants out of generative text into typed runtime contracts.
  • Synthetic Clean Code principles (unambiguous names, SRP, actionable errors, DRY, domain boundaries, evals-first, Boy Scout rule) govern the remaining chapters of this volume.