Skip to content

01 · Agent design: choose the skeleton by failure cost

Choose an agent runtime by failure cost and observability, then follow the source paths that are worth borrowing.

Chapter brief

Question to answer

When failure costs differ, which runtime skeleton should you borrow from?

By the end, you can

  • Choose reference systems by verifiability, autonomy, and runtime boundary
  • Separate reusable mechanisms from assumptions that do not transfer
  • Create a reading route for your own product
Read this now if
Readers choosing an architecture, reviewing one, or entering this site for the first time
Prerequisites
Know that agents can change external state through tools
Deliverable
An agent-architecture selection table ordered by failure cost
Evidence boundary
Pinned source snapshots explain trade-offs, not universal performance rankings

Imagine reviewing two products:

  • Repository-fix agent: edits real code and executes commands. One bad commit can block a release, while tests, diffs, and Git provide external evidence.
  • Weekly research assistant: carries topics, sources, and preferences across sessions. One answer may be imperfect, but a bad memory can amplify across future work.

Both are agents; they should not inherit the same default runtime. Fill four boxes first:

Constraint to answer firstWhat the answer changes
Can the worst side effect be rolled back?Approval, sandbox, idempotency, and human-gate strength
What external signal can prove completion?Whether the verifier is tests, rules, source checks, or human review
How long must state live?Whether a trajectory is enough or you need sessions, memory, and background work
Does the system cross users, channels, or concurrent runs?Identity, routing, session lanes, and isolation boundaries

Completion check: by the end, you should name one primary reference system, one system whose mechanisms you will borrow selectively, and at least one assumption you must not copy.

Map failure cost to four useful boundaries

Section titled “Map failure cost to four useful boundaries”
Four systems on the short-term control to long-term autonomy axis
One axis, four engineering answers: the left emphasizes auditability within one run; the right emphasizes continuity across runs.

These are not four implementations of one product. They are four answers to different failure surfaces:

Decision CodexClaude CodeOpenClawHermes
Failure controlled first Bad patches, dangerous commands, and unreviewable editsUnexplained retries, compaction, and context driftRaces and routing errors across users and channelsPreferences, feedback, and memory failing to persist
Primary external signals Diff, patch checks, tests, policy, and rollouttransition.reason, hooks, token, and compaction staterunId, session lanes, tool and lifecycle eventsCheckpoints, memory, insights, and skill feedback
Boundary worth borrowing Event loop, execution policy, Git, and sandboxContinuation reasons, layered compaction, IDE-state restoreAsync runs, session control plane, plugin hooksCross-session memory, background work, input scanning
Assumption easiest to copy badly Every task has tests or machine-verifiable outputA tightly coupled query loop is friendly to external extensionAn observable background job has recoverable side effectsPersisting feedback proves long-term improvement
Locate the failure surface first; then choose the source path

Read source only where the decision splits

Section titled “Read source only where the decision splits”

Codex · Separate reviewable signals for a coding workflow

Section titled “Codex · Separate reviewable signals for a coding workflow”

Codex is OpenAI’s first-party coding agent. The source snapshot exposes several signals that a host can review: patch grammar, configured test results, command policy, and Goal state. None of those signals is a general proof of business completion.

The Rust core (codex-rs workspace) shows this judgement at every layer.

The loop is modeled in four-level granularity: Turn (one model speaks, tool runs, model speaks again minimal cycle, corresponding to TurnContext), Goal (long-cycle task target spanning multiple Turns, supporting “resume by goal” rather than “resume by last conversation”), with all external actions wrapped as Op and submitted via submit(), internal events output via next_event() for external observers.

This event-driven design lets the loop become “a pausable, observable state machine” instead of “a black-box function running blindly”. Every step writes to rollout/*.jsonl JSONL files, so any run can be replayed or resumed.

Machine restart? Read rollout, rebuild state. Want to view agent history? Replay rollout. Multi-agent communication runs through the same mechanism.

The Codex snapshot exposes several reviewable signals. Whether they form a task’s completion gate is a host-workflow choice. apply_patch validation uses V4A grammar to reject malformed patches; run tests exit code can report failure when the host configures tests; execpolicy::Decision is a three-state command review (Allow / Prompt / Forbidden) with git-trackable Starlark rules; goals.rs convergence detection tracks Goal budget and state. These signals make parts of the run machine-checkable, but they do not prove every task is complete.

These signals mainly serve coding work. A PRD or research task may have no patch or test, and Goal state cannot replace content review; the host needs source checks, human review, or another domain-specific gate.

Claude Code · A single-file loop with explicit transition reasons

Section titled “Claude Code · A single-file loop with explicit transition reasons”

Claude Code is Anthropic’s CLI implementation snapshot. It foregrounds transition reasons so an observer can distinguish retries, compaction, and ordinary turns.

The source makes an observability problem explicit: a long message stream does not by itself explain why the loop continued. A reason label gives downstream analysis a field to inspect.

So Claude Code models all “why is the loop still running” reasons explicitly into transition.reason tags, turning the loop state machine into a “state machine annotated with reasons”.

The core is src/query.ts, with queryLoop() (1729 lines, async generator) the entry point.

Each continue site sticks a transition.reason label, with 7 reasons total: reactive_compact_retry (context overflow forced reactive compaction, must rerun), collapse_drain_retry (after history collapse must re-confirm state), max_output_tokens_escalate (output exceeded token limit, escalate to bigger model), max_output_tokens_recovery (escalation also insufficient, recovery handling), stop_hook_blocking (stop hook forces continue), token_budget_continuation (near budget limit nudge model to keep going), next_turn (normal next round).

These 7 tags make the selected transition points inspectable; they are not a complete account of every runtime decision.

The 4 context-compression pipelines (applyToolResultBudgetsnipCompactcontextCollapseautocompact) are stacked from cheap to expensive, with each tier independently judging whether to trigger; any tier failing 3 times consecutively trips the circuit breaker (MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3).

The code comment directly cites a production incident: “1,279 sessions had 50+ consecutive failures (up to 3,272), wasting ~250K API calls/day globally”. TOKEN_BUDGET then adds a local heuristic (90% threshold + 3 rounds < 500 tokens = diminishing returns). Treat those constants as the Claude Code implementation, not as a universal stop rule.

The cost: query.ts at 1729 lines couples all paths together with no plugin hooks. To plug in external verifier middleware or replace the compression strategy, you must fork.

OpenClaw · A public loop specification with middleware-based verification

Section titled “OpenClaw · A public loop specification with middleware-based verification”

Among these four snapshots, OpenClaw is the one that publishes the whole loop as a document (docs/concepts/agent-loop.md, lines 18-148). The document gives a useful boundary; source is still needed for implementation details.

A user may send a message through Telegram while a run is still active; the example illustrates why progress, interruption, and a second conversation need explicit lifecycle state.

“Synchronous function” mode just won’t hold up these scenarios. So OpenClaw makes the loop an “observable background job”.

The user calling the agent RPC returns { runId, acceptedAt } immediately, the job runs in the background, and external parties can subscribe to event streams via runId at any time.

Among the four reviewed snapshots, OpenClaw is the one that documents this 5-step pipeline in docs/concepts/agent-loop.md: receive → context_pack → model_call → tool_dispatch → response. SessionManager gives every session an explicit lifecycle, and subscribeEmbeddedPiSession bridges pi-agent-core events into 3 streams (assistant / tool / lifecycle).

Many checks are exposed through middleware hooks (before_tool_call / after_tool_call / tool_result_persist etc.), so a host can register verification without editing the core loop. The snapshot does not establish that every verifier is middleware-driven.

The session lane serialises multiple runs in the same session, reducing one class of history races; tool-loop-detection.ts lists four detector kinds in this snapshot. Their coverage and defaults still need deployment tests.

In this sample, OpenClaw puts the clearest extension boundary around the loop. The same hook depth also makes debugging more involved.

Hermes · Long-running Python agent, spreading verifier across the time axis

Section titled “Hermes · Long-running Python agent, spreading verifier across the time axis”

Hermes is a Python agent with long-running and cross-session paths. The snapshot separates per-loop budgets, post-hoc insights, and memory prefetch; whether that is the right split depends on the workload.

One design trade-off is strict per-run verification versus carrying feedback into later runs. Memory and self-grading can support the latter, but they do not replace an external check when a single result must be correct.

Under this trade-off, a deployment may choose a softer per-loop stop, provided it keeps an explicit budget and a failure state.

The main loop defaults to 90 steps (50 for subagents); on exhaustion it makes a grace call, writes a summary, then stops.

Memory prefetch: _memory_manager.prefetch_all() is called once before the loop starts to load the user’s long-term memory (preferences, past tasks, relationships) into RAM.

Subsequent in-loop memory queries then read from RAM, saving N retrieval round-trips against the memory store.

After the loop ends, agent/insights.py makes one LLM call to evaluate “how did this run go” and writes the result to memory; next similar task prefetch will inject the experience. The verifier is “spread across the time axis”.

A single loop is not strict. Later runs can retrieve memory and insights, but whether that improves outcomes depends on memory quality, triggers, and workload; this snapshot contains no cross-session evaluation.

One distinctive move is scanning external files for prompt injection before injection. _scan_context_content scans listed pattern types and invisible Unicode characters; on a match it replaces the file with [BLOCKED]. This reduces one input risk but is not a complete security boundary.

The other three default to trusting local-repo AGENTS.md / CLAUDE.md (assumed authored by the developer).

Hermes assumes “the user might have cloned a repo with a malicious AGENTS.md” (attackers poisoning via PR), pulling the trust boundary down to the file-read layer.

Keep the shared floor before the trade-offs

Section titled “Keep the shared floor before the trade-offs”

Across the four source snapshots, seven recurring constraints emerge. Use them as a design checklist, not as a certification of “production readiness”:

First, tasks that require multiple actions usually need a state machine (detailed in ch. 02). Simple Q&A may not. The four samples can be mapped to observe, plan, act, and verify, but their boundaries differ.

Second, Observe → Plan → Act → Verify is a useful design lens, not a claim that every runtime implements the same four nodes.

Third, all four leave room for reviewable evidence because “model confidence ≠ ground truth” (detailed in ch. 05). The evidence needed in production depends on the task and its failure cost.

Fourth, side-effecting or costly loops need explicit termination conditions (max_steps / token_budget / goal_done). Pick the cap and fallback from observed workload and risk.

Fifth, static / dynamic context separation is an option for caching (detailed in ch. 03). Provider rules differ; measure token use, cache hits, and latency before treating it as a requirement.

Sixth, tools must use JSON Schema description (detailed in ch. 04). Schema makes parameter types and required fields explicit. The impact on call failures must be measured with the target model and tool set; the source comparison alone cannot justify a universal percentage.

Seventh, high-impact tools need an explicit policy or approval boundary (execpolicy / canUseTool / hook / per-tool check). Defaults and coverage differ by deployment, so label the actual boundary.

Four agents on a 2D plane: short-term control × long-term autonomy
X: short-term control (how hard each step is to approve). Y: long-term autonomy (self-driving + self-learning). The four sit on a diagonal, one per use-case archetype.

Four workloads map cleanly onto the four systems. Pick the system that matches your scenario, don’t pick “the most popular” or “the most highly starred”:

You want the model to patch a real repo, with every step reviewable: examine Codex first. Patch parsing, test exit codes, command policy, and Goal state provide separate machine-readable signals; rollout persistence supports replay and audit. A host must still connect the applicable signals into a completion gate, and none of them alone proves business correctness. PRDs, research, and customer support need different acceptance evidence.

You already live inside the Anthropic stack and want a complete implementation to dissect: start with Claude Code (the source snapshot is unpackable). queryLoop puts 7 transition.reason tags, 4 compression pipelines, the TaskType model, and the TOKEN_BUDGET heuristic in one runtime. That coupling is useful to study, but external extensions carry fork or wrapper maintenance cost.

You need an agent that fans out to Telegram / Slack / Web / WhatsApp and handles many users at once: examine OpenClaw first. Session lanes serialise runs within one conversation, the tool catalog and profiles separate workloads, and middleware carries verifier, audit, and cache logic. It is the only sample positioned as a control plane; that does not remove races in external tools or shared data stores.

You want one agent on your laptop to retain preferences or cross-task feedback: evaluate Hermes’s memory_manager, insights, and skill hooks. They provide a cross-session record in this snapshot, not a demonstrated guarantee of improvement; SOUL.md supports user-edited identity, and the file scan covers one known input risk. Keep an external check for tasks that must be correct in one run.

Choose by failure cost, not framework name

Section titled “Choose by failure cost, not framework name”
Workload constraintSource route to inspectCost or boundary
A wrong edit is unacceptable and tests or patches can prove itCodex rollouts, goals, and execpolicyCoding-specific verifier assumptions
You need to explain retries and compactionClaude Code transition reasons and compactionCustomization follows a coupled file
Many users or channels need observable background runsOpenClaw session lanes and hooksMiddleware requires its own trace
Value accumulates across sessionsHermes checkpoints, memory, and insightsA single run has weaker hard evidence

Read by your goal

Start here

  • Building a coding agent: ch. 02 Agent Loop → 04 Tools → 07 Shell → 11 Sandbox
  • Building an agent server: ch. 02 Agent Loop → 04 Tools → 11 Session lifecycle → 14 Multi-channel intake
  • Building a long-runner: ch. 02 Agent Loop → 03 Context → 16 Memory → 19 Self-improvement
  • Doing architecture review: ch. 01 Overview → 02 Agent Loop → 05 Verifier → 20 Security

Then read

  • Want to reuse code? Every chapter ends with REF/ paths and line ranges
  • Want cross-cuts? Chapter 02 keeps five expandable source comparisons (prompt / compression / retry / tools / exit)
  • Want real numbers? Watch for the verbatim quotes like "250K wasted API calls per day"

Skippable for now

  • Jumping straight into source maps. Read the system profiles and trade-offs first, then dive into source
  • Reading only the system you already know. The four side-by-side is where the comparison shows up
Observe Plan Act Verify
The same minimal loop runs in all four systems. What differs is how each node is built

Deliverable check: finish with one selection record

Section titled “Deliverable check: finish with one selection record”

Turn the opening four-box card into one page. Do not leave with only “which system I like”:

  1. Primary reference system: does the failure it controls first match your highest-loss event?
  2. One borrowed mechanism: take one boundary from another system, such as transition reasons, session lanes, or memory provenance.
  3. One assumption you cannot copy: for example, “my task has no test oracle” or “external side effects cannot be rolled back.”
  4. Next chapter: enter through the most dangerous unresolved problem—Loop, Verifier, Session, Memory, or Security—rather than reading linearly.

Next experiment: fill the card for two real tasks with very different failure costs. If both still produce the same architecture, check whether framework preference replaced constraint analysis.

Open the exercises and ten review questions
  1. 🟢 Pick one: List your last 3 months of “AI agent use cases.” Sort them by failure cost. Decide which system fits, or whether you should write your own.
  2. 🟠 Read: Pick one system. Spend 30 minutes following the source entry points at the end. Find the main loop, its stop condition, and its most unusual engineering move.
  3. 🔴 Compare: Pick the two most unlike systems, such as Codex and Hermes. Compare their profiles and write five concrete examples where the same problem produced different designs.
Q1 · Concept: Are “agent harness” and “agent model” the same thing?

No. The agent model is the LLM itself (GPT-4 / Claude / Gemini: parameters + decoder). The agent harness is everything around the model: main loop, context system, tool system, sandbox, verifier, memory, observability, security.

This book takes the harness apart, not the model.

Why the harness deserves its own book: many agent failures occur around the model: missing exit signals, repeated tool calls, and stale context. The proportion depends on the workload and should be measured with a shared task set.

A badly written loop can waste tokens; a poorly designed tool protocol can trap the model in retry loops. With the same model, compare harnesses on the same task set before claiming one gap is wider than another.

The four systems have different roles: Codex is OpenAI’s engineering reference, Claude Code is an unpacked Anthropic implementation snapshot, OpenClaw is an open-source control plane, and Hermes is a research-oriented long-running agent.

Together they cover enterprise to hobbyist territory.

Source: see this chapter’s Source evidence for this choice. Follow-up: “Are LangChain / AutoGPT harnesses?” Yes, but framework-level (developer-assembly). This book covers product-level harnesses (end-user-runnable).

Q2 · Use-case selection: “Turn the internal knowledge base into a conversational agent.” How do you choose a reference from the four?

First decompose: single-user / Q&A / light tools (most knowledge bases), or multi-user / write ops / database (more like internal ops). The former points to Hermes/Claude Code, the latter to OpenClaw.

Single-user Q&A: borrow from Claude Code’s context compression + transition tags (query.ts is closest to a modern RAG agent). Do not borrow from Codex, because Codex assumes a coding repo.

Multi-user ops: borrow from OpenClaw’s session lane (one session per user/conversation), each session runs its own loop. Build memory independently (use Hermes’s memory_manager as a model).

Do not lift any single system whole-cloth. Plugin, channel, and cron code can expand the maintenance surface; extract the skeleton from the profiles, then add verification and memory deliberately.

Source: openclaw/src/config/sessions/, hermes-agent/agent/memory_manager.py, claude-code/src/services/compact/compact.ts. Follow-up: “Why not just use LangChain?” Fine for small knowledge bases. At scale its tool protocol can become hard to debug. Use the Tool System chapter when building your own.

Q3 · Architecture: All four treat the “turn” as the time unit, but turn-internal step counts differ. Why?

Standard definition: a turn is the span from one model reply (including tool calls) to the next. But “how many tools fit in one turn” varies a lot:

  • Codex: one tool per turn (serial). Each tool waits for verifier before the next. This makes the loop easier to reason about, at the cost of serial waiting.
  • Claude Code: many tool_use blocks per turn, dispatched in parallel via dispatchToolUseBlocks (Promise.all). End-of-turn stop_hooks verify globally.
  • OpenClaw: turn is an event stream; tools are events; external observers can pause at each event.
  • Hermes: one tool per turn, because the trajectory is linear; parallelism would scramble memory injection logic.

Root cause: protocol shape (Anthropic encourages multiple tool_use per turn; OpenAI is historically one-per-turn) and verifier type (hard verifiers favour serial; soft verifiers tolerate concurrency).

Source: codex/codex-rs/core/src/session/turn.rs, claude-code/src/query.ts, openclaw/src/runtime.ts, hermes-agent/run_agent.py:9333-9540. Follow-up: “What if one parallel tool fails?” Claude Code’s stop_hooks treat partial failure as a transition reason; the turn still completes but the verifier flags fail. Codex avoids this because it is serial.

Q4 · Engineering: All four use markdown as the primary protocol (not JSON). Coincidence or design?

Design. Four reasons:

  1. Format is an experiment, not a training-data claim. Markdown is convenient for people, append operations, and diffs. Compare markdown, JSON, and XML format success on the target model instead of guessing from closed training corpora.
  2. Human-readable. Looking at a system prompt while debugging, markdown is grokkable. JSON forces folding/unfolding.
  3. Append-friendly. Markdown sections (## / ###) naturally support “add one more section.” JSON requires recomputing the whole object.
  4. Diff-friendly. Prompt files in git diff nicely.

All four write the prompt in markdown (Codex one big .md, Claude Code string concatenation in constants/prompts.ts, OpenClaw buildXxxSection returns strings, Hermes SOUL.md is markdown).

But tool calls all use JSON (Anthropic tool_use / OpenAI tool_calls), because tool calling demands structured fidelity.

Source: codex/codex-rs/core/src/context/prompts/, claude-code/src/constants/prompts.ts, hermes-agent/docker/SOUL.md. Follow-up: “What about XML tags like <thinking>...</thinking>?” XML is used as section delimiter inside the prompt (Anthropic explicitly recommends it), but the surrounding shell is still markdown.

Q5 · Architecture: All four have a “tool” abstraction, but tool names / boundaries differ. How do you define a tool?

Engineering definition: a tool is a function the model can trigger, the harness actually executes, and the structured result returns to the model. All three conditions are required.

Each system draws the boundary differently:

  • Codex: apply_patch / run_shell / read_file are tools, but “how to choose the patch algorithm” lives in the prompt (model decides).
  • Claude Code: Bash / Read / Write / Grep / Glob / Edit / MultiEdit / TodoWrite and 12+ tools each as a class under src/tools/.
  • OpenClaw: tools are plugins (PluginEntry), registered via hooks. Lightest abstraction.
  • Hermes: tools are skills (skill_loader.py), one skill may contain multiple tool functions, gated by need.

Tool granularity affects prompt size and selection behaviour. Coarse tools make a shorter list but leave wider parameter semantics; fine-grained tools clarify the contract while increasing the list. Measure selection quality on the target workload.

Claude Code picks a fine-grained tool set. Whether that is more accurate is a workload-specific question, not established by this source comparison.

Source: see chapter 04 · Tool system. Follow-up: “More tools = better?” No. Longer schemas and tool lists can raise selection cost. Measure wrong-tool calls and latency on the target model before choosing a profile size.

Q6 · Engineering: All four assume the agent runs on a trusted machine. Which is easiest to retrofit for cloud multi-tenant?

OpenClaw is easiest. It already has SessionManager and plugin decoupling. Multi-tenant ≈ “one user_id maps to one session_id.” You add:

  1. Session-level permissions (onSessionStart hook checks user quota)
  2. Tool-call audit (onToolUse hook writes to db)
  3. Memory isolation (one user, one memory namespace)

Codex is hardest. codex-rs assumes single-user CLI/IDE; state lives on disk; rollout in ~/.codex/. Cloud retrofit needs: rollout in db, user-level ACLs, IPC redesign (codex_app_server is axum but defaults to single-user).

Claude Code mid-hard. query.ts has no user concept; needs a wrapping layer. Context-compression forked agents must be isolation-safe in cloud.

Hermes mid-hard. memory_manager assumes single-user home dir, but code is loosely coupled; multi-tenant retrofit is not painful.

Source: openclaw/src/agents/pi-embedded-runner/session-manager-init.ts, codex/codex-rs/app-server/, hermes-agent/agent/memory_manager.py. Follow-up: “Sandbox isolation per tenant?” Borrow from Hermes’s tirith subprocess model: every tool call subprocess + redact, safe across tenants.

Q7 · Production: You have an “AI customer support agent.” How would you add Codex-style verifiers?

Codex’s verifier idea has three pieces:

  1. goals.rs decomposes the task into N goals: customer support means splitting the user’s message into goals like “look up order / change address / refund”.
  2. Tag every step with goal-touched markers: record which goal each tool call advances (query_order → “look up order”).
  3. All goals touched → converged: once every goal status is satisfied, end.

Production wiring:

  • Use a light NLU model to decompose user messages into goal list (or have the main agent decompose with a schema constraint).
  • Add a hook in the tool layer: each tool declares which goals it can contribute (query_order → “look up order”).
  • Maintain goal_status: dict[goal_id, status]. The loop checks at end-of-turn whether all are done.
  • Fallback: escalate to human after N turns without convergence.

Do not transliterate Codex’s Rust. goals.rs assumes coding (“goal touched” = code region modified). Customer support needs different judgement (based on tool calls + reply content).

Source: codex/codex-rs/core/src/goals.rs, see also chapter 05 · Verifier. Follow-up: “Should the support agent also get TOKEN_BUDGET soft exit?” It can be a useful experiment. Start with a conservative threshold, add an “is the issue resolved?” nudge, and calibrate against support transcripts rather than copying a fixed percentage.

Q8 · Concept: What does “agent harness observability” mean? Why is it a chapter of its own?

Observability lets you answer three questions from outside:

  1. How long did this loop run / how many tokens / which tools were called? (cost / latency / tool trace)
  2. Where did this loop deviate from expectation? (transition reason / verifier output / error stack)
  3. What changed between last run and this run on the same prompt? (rollout diff / behavioural drift detection)

All four expose it differently. This Codex snapshot has many codex-otel and codex-analytics event types; Hermes uses trajectory files (JSONL per step).

OpenClaw goes through plugins (onEvent hook). Claude Code uses transition tags + token-budget logs.

Why a chapter: observability is one of the clearest differences between a demo and a long-running service. The work varies with the deployment; chapter 15 compares the four implementations and names the signals worth collecting.

Source: see chapter 15 · Observability and cost. Follow-up: “Is one log line enough?” No. Three layers minimum: step-level (one per tool call), turn-level (one per model call), session-level (one per dialogue).

Q9 · Selection: What projects should NOT use the “heavy harness” route?

Three project shapes go with the light route (official SDK + 200-line custom loop) instead of copying heavy harnesses:

  1. POC / hackathon / one-off scripts: for a narrow flow, an official SDK plus a small loop may be enough; first decide whether you need recovery and audit.
  2. Very narrow scope and ≤ 3 tools: e.g. “extract key fields from PDF, return JSON.” This is a single prompt, not an agent loop.
  3. Workflows requiring absolute determinism: financial reconciliation, etc. Should be a workflow (every step fixed) with LLM as one node, not an agent (where the model decides each step).

When to switch to a heavy harness: when recovery, cross-session state, multi-user concurrency, or audit costs exceed a small custom loop. Do not use fixed months or tool counts as the gate.

These systems have far more code and history than a small proof of concept. Their snapshot size does not predict your project’s schedule; reuse only the boundaries you need.

Source: see OpenAI’s Building Agents with Function Calling, Anthropic’s Claude Tool Use. Follow-up: “What about LangChain?” Mid-light. Good tool protocol, no verifier / memory / observability layer. Fits “medium complexity + team unwilling to roll their own harness.”

Q10 · Open-ended: If you wrote chapter 23, what would you cover?

Three candidates worth testing:

  1. Agent-to-agent communication protocols. All four have subagents (chapter 10), but inter-agent messaging differs (Codex agent.send_input, OpenClaw event bus, Hermes shared trajectory file). Compare them and abstract an A2A protocol design pattern. Fills the “multi-agent systems” gap.

  2. Model swap engineering. The book binds models per system (Codex on GPT-5, Hermes on Claude). Production often wants “main task on Claude, summary on a cheap model.” How to do model routing + cache compatibility inside a harness is a hot topic.

  3. Agent UX patterns. Chapter 14 covered entry points (CLI / IDE / Slack) but not UX. Thinking-streaming, tool-call visualization, cancel semantics. Claude Code’s ink REPL and Codex’s ratatui TUI each have an approach worth taking apart.

If I had to pick one, I would start with #1 because these four subagent designs expose unresolved questions in state isolation, recovery, and acceptance. That is a judgment from this sample, not a forecast for every agent product.

Source: see AutoGen, CrewAI for multi-agent framework evolution. Follow-up: “If you had to add one more chapter today?” Chapter 22 now covers execution-state surfaces. The next one would pull “cost” out of chapter 15 and make an Agent Economics chapter: how the four systems combine model choice, cache policy, tools, and concurrency into predictable usage cost for enterprise rollout.