"Harness Engineering: A Design Guide to Claude Code" — agentway.dev (2026-04-01)
Why this is in the vault
This 100+ page book is a source-level teardown of the leaked Claude Code runtime, distilled into nine chapters of portable design principles for any agent harness. It is literally about the substrate Ray IS. Where most "agent harness" content circling the vault (IndyDevDan, Addy Osmani, Akshay Pachaar, Thariq, Garry Tan) is one-video or one-essay long, this is the consolidated reference. Many patterns RDCO has already adopted via individual feedback memories — layered CLAUDE.md, MEMORY.md as index, sub-agent fan-out for context isolation, /distinguish-decision-from-action, /fresh-eyes-subagent for self-review, no-secrets-on-disk, PR-only workflow as Bash-class restraint — turn out to be derivable from a coherent skeleton. The book also surfaces concrete gaps Ray has NOT closed yet (notably: explicit recovery-path circuit breakers, three-valued permission semantics, verification-as-independent-worker discipline, and an Errors&Corrections section in session memory).
This is a once-a-quarter calibration artifact. Re-read when designing any new sub-agent skill, when CLAUDE.md feels like it's drifting toward "bulletin board," or when a recovery failure mode shows up in production.
The 6-chapter argument (compressed)
Chapter 1 — Why Harness Engineering Matters. Five harness layers stack: (1) constrained conversation system; (2) continuous loop with cross-iteration state; (3) tool calls under scheduling discipline; (4) high-risk tools (Bash) under high-density constraint; (5) errors as first-class main-path concern. Load-bearing claim: "the key capability of an agent system is constrained execution." Models are unstable components, not teammates. Order is preserved through structure, not smartness.
Chapter 2 — Prompt Is Not Personality, Prompt Is the Control Plane. Claude Code's system prompt is not a persona blob; it's a layered assembly of behavioral blocks with explicit precedence: override > coordinator > agent > custom > default, with appendSystemPrompt always last. Users can override but cannot bypass the layering. Prompt is connected to memory (CLAUDE.md, MEMORY.md) and to cache discipline (cacheable vs DANGEROUS_uncached sections). Load-bearing claim: "prompt is valuable only when it is integrated into explicit control structure" — it's constitution, not dialogue.
Chapter 3 — Query Loop is the Heartbeat. queryLoop() maintains one cross-iteration State object (messages, toolUseContext, autoCompactTracking, maxOutputTokensRecoveryCount, hasAttemptedReactiveCompact, pendingToolUseSummary, stopHookActive, turnCount, transition). The first duty is input governance BEFORE model invocation — memory prefetch, skill prefetch, message slicing, tool result budget, history snip, microcompact, context collapse, autocompact, in that order. Model output is consumed as an event stream (text, tool_use, usage updates, stop reasons, API errors), not as a synchronous completion. Stop conditions are multi-valued — {completion, failure, recovery, continuation} must be distinguished; failure and completion cannot collapse. Load-bearing claim: "the core capability of an agent system is maintaining a recoverable execution loop."
Chapter 4 — Tools, Permissions, and Interrupts. Tools are managed execution interfaces, not extensions of model capability. runTools() batches by concurrency safety (isConcurrencySafe()); parallel safe, serial otherwise; even in parallel, contextModifier callbacks buffer and replay in original block order — concurrency must not break causality. Permission is three-valued: allow / deny / ask — boolean shortcuts are forbidden. StreamingToolExecutor makes interrupt first-class semantics; every issued tool_use MUST have a paired tool_result (synthetic if interrupted) — the ledger must close. Bash is treated as a risk amplifier with its own prompt + permission classifier + subcommand-count cap. Load-bearing claim: "model proposes, runtime authorizes."
Chapter 5 — Context Governance. Context is not a warehouse; it's an inflation-prone budget. Four layers: (1) CLAUDE.md for stable long-lived instructions with layered loading; (2) MEMORY.md as index, not diary with hard caps MAX_ENTRYPOINT_LINES=200, MAX_ENTRYPOINT_BYTES=25_000; (3) Session memory with a fixed template — Current State, Task spec, Files and Functions, Workflow, Errors & Corrections, Codebase docs, Learnings, Key results, Worklog — under MAX_SECTION_LENGTH=2_000, MAX_TOTAL=12_000 tokens; (4) Autocompact reserves MAX_OUTPUT_TOKENS_FOR_SUMMARY=20_000 and AUTOCOMPACT_BUFFER_TOKENS=13_000, with circuit breaker MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES=3. compactConversation() is controlled reboot — clears stale readFileState, regenerates file attachments, reinjects plan/skill/MCP attachments, runs session-start and post-compact hooks, writes compact-boundary messages with pre-compact token counts. Load-bearing claim: "context is working memory; governance exists to keep the system able to continue work."
Chapter 6 — Errors and Recovery. "Under normal conditions" is the least trustworthy phrase in engineering. prompt_too_long is seasonal, not exceptional. Recovery is layered by cost: first flush staged context collapse, then reactive compact, then surface. hasAttemptedReactiveCompact prevents self-loop — if compact didn't help once, repeating it just replays the failure. max_output_tokens recovery prefers continuation over polite recap — append a meta user message saying "continue directly; no apology; no recap" rather than burning budget on social politeness. Auto-compact has its own circuit breaker. truncateHeadForPTLRetry() handles the case where compact itself hits prompt-too-long — survival over elegance. Abort semantics are recovery, not UX — interruption requires correct ledger closure. Load-bearing claim: "an agent system shows its reliability by maintaining explainable, bounded, and resumable execution order after failure."
Chapter 7 — Multi-Agent and Verification. Forked agents must preserve CacheSafeParams (systemPrompt, userContext, systemContext, toolUseContext, forkContextMessages) — fork is runtime-controlled branching, not a fresh chat window; if cache discipline breaks, parallelism is just parallel waste. createSubagentContext() isolates mutable state by default; sharing requires explicit opt-in. Coordinator mode demands "Always synthesize" — research workers explore, synthesis worker recompresses, implementation worker edits, verification worker is independent and skeptical (run tests, investigate errors, do not rubber-stamp). Subagents are lifecycle objects with SubagentStart/SubagentStop hooks; parent abort propagates to child; cleanup handlers must unregister. Verification applies to memory too — when memory conflicts with current reality, trust reality. Load-bearing claim: "multi-agent really solves uncertainty partitioning" — different uncertainties in different containers, then recombined by a coordinator.
Chapter 8 — Team Adoption. (Less load-bearing for solo RDCO but worth holding.) The rollout order is: (1) define acceptable usage scope, (2) standardize verification definition, (3) THEN add skills, (4) only after baseline is stable add hooks. CLAUDE.md should be stable, layered, low-dispute — foundation, not bulletin board. Approval should be tiered by risk (read / write / irreversible) rather than tool name. Hooks belong later. Replayability layered: baseline first (Git, PR, CI), advanced audit (transcripts, hook events, subagent state transitions) only when scale/compliance justifies.
Mapping against Ray Data Co — what we already have
| Chapter principle | RDCO embodiment |
|---|---|
| Ch 1: constrained execution > smart execution | feedback_no_em_dashes, feedback_no_autonomous_external_email, feedback_pr_only_workflow, feedback_listen_and_injection_caution — all are explicit constraint structures, not "trust the model" |
| Ch 1: Bash needs high-density constraint | feedback_pr_only_workflow (never commit/push directly to main), feedback_no_secrets_on_disk (1Password wrapper, no .env), [[~/rdco-vault/06-reference/2026-05-11-indy-dev-dan-delete-bash-tool-agentic-security]] active mitigation |
| Ch 2: prompt is layered, not monolithic | ~/CLAUDE.md (project) + ~/.claude/projects/-Users-ray/memory/MEMORY.md (auto-memory index) + per-skill SKILL.md + per-session working-context. Layering exists; precedence is implicit |
| Ch 2: prompt is connected to memory | MEMORY.md IS an index pattern — uses one-line wikilinks to per-topic feedback memory files, not a single text dump. Already correctly implemented |
| Ch 3: query loop with cross-iteration state | Mac Mini always-on agent + tmux + daily 4am restart ([[~/.claude/projects/-Users-ray/memory/project_channels_agent_setup]]) is the literal heartbeat. ~/.claude/state/working-context.md is the cross-iteration State object |
| Ch 3: input governance before model invocation | /check-board, /process-inbox, /morning-prep skills prime context BEFORE Ray reasons. The date-first hard rule is input governance for time |
| Ch 3: stop conditions are multi-valued | feedback_distinguish_decision_from_action separates "completion" (executed reversible work) from "needs founder judgment" — explicit two-valued stop semantics in skill reports |
| Ch 4: model proposes, runtime authorizes | feedback_mcp_install_security_review_default (security review BEFORE install), feedback_no_autonomous_external_email (Ray drafts, founder sends), allowlist policy in iMessage/Discord channels |
| Ch 5: CLAUDE.md is stable, low-dispute | feedback_no_claudemd_state_drift — explicit memory rule: workspace state lives in state files / vault, NOT CLAUDE.md. Already adopted |
| Ch 5: MEMORY.md is index, not diary | Already correctly implemented — every entry is a one-line wikilink to a separate feedback_*.md file |
| Ch 5: session memory continuity | ~/.claude/state/working-context.md + bridge-notes hooks (PreCompact write → SessionStart:compact read), per [[~/rdco-vault/06-reference/2026-04-15-thariq-claude-code-session-management-1m-context]] |
| Ch 6: route long artifacts through subagents | CLAUDE.md hard rule #4 (route artifacts >5KB through subagents) is literally a Ch 6 + Ch 7 principle implemented — context rot mitigation via sub-agent fan-out |
| Ch 7: independent verification, not self-endorsement | feedback_fresh_eyes_subagent_for_own_artifacts — formalized as /design-critic and /video-critic. This is Ch 7.5 verbatim |
| Ch 7: subagents are managed lifecycle objects | /loop, ScheduleWakeup, CronCreate primitives — durable steps with explicit start/stop |
| Ch 8: tiered approval by risk | feedback_auto_mode_signal_to_noise + feedback_distinguish_decision_from_action + feedback_pr_only_workflow_hq_carveout — reversible work auto-runs; irreversible work gated |
| Ch 8: stable instructions, low-dispute | feedback_no_claudemd_state_drift enforces this directly |
Mapping against Ray Data Co — what we're missing
| Chapter principle | RDCO gap |
|---|---|
| Ch 2: explicit prompt precedence chain | Our prompt layering (CLAUDE.md / MEMORY.md / SKILL.md / working-context) has no documented precedence order. When CLAUDE.md and a skill SKILL.md disagree, which wins? When working-context drifts from CLAUDE.md, which wins? Currently informal; the book argues this MUST be explicit (override > coordinator > agent > custom > default). Recommended action: add a ## Prompt precedence section to CLAUDE.md. |
| Ch 3: cross-iteration state has named fields | Claude Code's State object has named fields (messages, toolUseContext, autoCompactTracking, maxOutputTokensRecoveryCount, hasAttemptedReactiveCompact, pendingToolUseSummary, turnCount, transition). Our working-context.md is freeform text. We've benefitted from this informally but it's untyped; failure modes don't have explicit field names. |
| Ch 4: permission is three-valued (allow/deny/ask), not boolean | Our skill execution is implicitly two-valued (run / don't run). There's no formal ask state where Ray surfaces a permission ask to founder mid-skill. The hook-based PreToolUse verifier (feedback_no_em_dashes → mechanical rule corpus) is closer to deny-than-ask. Bigger gap: no formalization of which actions require ask vs allow vs deny. |
| Ch 4: every tool_use must have a paired tool_result (ledger closure) | When Ray sub-agents abort mid-skill (founder interrupts via iMessage, /loop gets killed, session compacts unexpectedly), there's no guarantee of synthetic-result-emission for in-flight work. We have working-context.md updates but no explicit "ledger close" discipline. Mac Mini daily 4am restart papers over this. |
| Ch 5: Errors & Corrections section in session memory | Our working-context.md doesn't have a dedicated Errors & Corrections section. Claude Code session-memory template explicitly elevates this above Current State priority on condensation. Founder corrections (the most expensive thing to re-learn, per CLAUDE.md summary instructions) deserve their own bucket in the state file. This is the most actionable single gap. |
| Ch 5: autocompact circuit breaker | We have no equivalent of MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES=3. If compactConversation() (or our bridge-notes equivalent) keeps failing, Ray could burn cycles indefinitely. The daily 4am restart is a coarse mitigation, not a circuit breaker. |
| Ch 5: explicit budget reservations | We have no documented token budget for any artifact — CLAUDE.md, working-context.md, per-skill SKILL.md, per-feedback-memory file are all freeform. Claude Code's hard caps (200 lines / 25KB for MEMORY.md, 2K/12K for session memory) are useful guardrails. Without caps, files drift toward "encyclopedia" failure mode that Ch 8.3 warns about for CLAUDE.md specifically. |
| Ch 6: recovery layered by cost | When a skill fails (e.g., process-newsletter chokes on a 400KB email), there's no formal cost-ordered recovery escalation. Currently it's mostly "retry / give up." Layered recovery (cheap-first, escalate only on failure) is not codified. |
| Ch 6: continuation > recap on truncation | When sub-agents return long output and parent compacts, the resumption pattern is implicit. No "continue from truncation point; no apology; no recap" instruction codified in skills that produce long artifacts. |
| Ch 7: CacheSafeParams discipline for sub-agents | Our sub-agent dispatch (Task tool, /research style fan-out) doesn't formally preserve cache-safe params. Each sub-agent likely re-burns parent context. This is an Anthropic cost issue more than a correctness issue but is real. |
| Ch 7: coordinator must synthesize, not forward | When Ray dispatches multi-agent fan-out (e.g., process-newsletter batch mode, /research multi-question), the parent COO synthesizes. But we don't have an explicit "Always synthesize" instruction in any skill — risk that under load, parent forwards raw sub-agent verdicts to founder instead of synthesizing. |
| Ch 7: verification independent of implementation | We have /design-critic and /video-critic for visual surfaces. We do NOT have an equivalent for vault writes, decisions, or strategic outputs. When Ray writes a thesis doc or makes a sub-agent dispatch decision, who verifies? Currently nobody until founder reads it. |
| Ch 7: verification applies to memory | Our feedback memory files can become stale. CLAUDE.md hard rule #4 (route artifacts >5KB) was added 2026-04-15 — has any feedback memory contradicted it since? Nobody checks. No memory-validation discipline; Ch 7.7 explicitly warns this is a primary failure mode. |
Ch 8: explicit ask tier in skill design |
Skills don't formally declare risk tier (read / write / irreversible). When founder reviews a new skill, the tier is implicit from the description. |
Recommended additions to synthesis-queue or /improve
Add
## Errors & Correctionssection to working-context.md template — the highest-leverage Ch 5 gap. Single concrete edit to~/.claude/state/working-context.mdschema + bridge-notes hooks + CLAUDE.md summary-instructions list. Codify the most expensive thing to re-learn (per CLAUDE.md) into dedicated state structure rather than narrative. (Direct /improve candidate; small surface area, high leverage.)Synthesis essay: "Constraint structure as competitive advantage for a solo-founder COO agent" — the book's load-bearing argument ("preserve order through structure, not smartness") maps onto RDCO's L4→L5 thesis ([[
/.claude/projects/-Users-ray/memory/project_l5_north_star_strategic_direction]]). Most agent-harness content treats constraint as overhead; this book treats it as the product. The synthesis: every RDCO feedback memory is a constraint, and the constraint density IS the moat. Cross-reference: [[/rdco-vault/06-reference/2026-04-11-garry-tan-thin-harness-fat-skills]] (thin harness / fat skills inverts this framing in an interesting way — surface the tension). Inputs converge: CLAUDE.md, all~/.claude/projects/-Users-ray/memory/feedback_*.mdfiles, [[~/rdco-vault/06-reference/2026-05-10-addy-osmani-agent-harness-engineering]]./improve candidate: explicit prompt precedence chain in CLAUDE.md — add a
## Prompt precedence (when documents conflict)section. Five-line spec:working-context.md > active SKILL.md > MEMORY.md feedback files > CLAUDE.md > model default. Or whatever the right order is — founder should pick. Currently this is folklore and the book's Ch 2 argument is that folklore is exactly where the harness breaks.
Related
- [[~/CLAUDE.md]] — RDCO project rules; the book validates the layered structure + memory-as-index design and surfaces the precedence-chain gap
- [[~/.claude/projects/-Users-ray/memory/MEMORY.md]] — already correctly implements the "index, not diary" pattern from Ch 5.3
- [[~/.claude/projects/-Users-ray/memory/feedback_fresh_eyes_subagent_for_own_artifacts]] — Ch 7.5 verbatim
- [[~/.claude/projects/-Users-ray/memory/feedback_distinguish_decision_from_action]] — Ch 3.7 multi-valued stop conditions
- [[~/.claude/projects/-Users-ray/memory/feedback_no_claudemd_state_drift]] — Ch 8.3 "CLAUDE.md is foundation, not bulletin board"
- [[~/.claude/projects/-Users-ray/memory/feedback_mcp_install_security_review_default]] — Ch 4 "permission before capability"
- [[~/rdco-vault/06-reference/2026-04-15-thariq-claude-code-session-management-1m-context]] — Anthropic-internal voice on Ch 3 + Ch 5 themes; today's implementation-notes SOP is the parent
- [[~/rdco-vault/06-reference/2026-04-07-claude-code-architecture-teardown]] — Rohit Krishnan's earlier teardown of the same source leak (lower-density)
- [[~/rdco-vault/06-reference/2026-05-10-addy-osmani-agent-harness-engineering]] — same vocabulary, shorter form
- [[~/rdco-vault/06-reference/2026-04-10-akshay-pachaar-agent-harness-anatomy]] — diagram-first version of Ch 3 query loop
- [[~/rdco-vault/06-reference/2026-04-11-garry-tan-thin-harness-fat-skills]] — interesting tension: "thin harness" inverts the book's "harness IS the substrate" framing
- [[~/rdco-vault/06-reference/2026-05-11-indy-dev-dan-delete-bash-tool-agentic-security]] — Ch 4.7 Bash-as-most-suspect, RDCO's current mitigation
- [[~/rdco-vault/06-reference/2026-05-18-awrigh01-agentic-capital-markets]] — today's Wright agentic-capital-markets reference; harness-engineering is the technical substrate that makes Wright's L5/L6 economic abstraction operable