{"slug": "loop-engineering-a-deep-technical-explanation-with-realistic-examples", "title": "Loop Engineering — a deep technical explanation with realistic examples", "summary": "Loop engineering is a deterministic control loop around an AI coding agent — schedule, durable state, and verification — that lets developers move up from prompting to designing the machine. Boris Cherny, Head of Claude Code at Anthropic, said: \"I don't prompt Claude anymore. I have loops running that prompt Claude and figure out what to do. My job is to write loops.\" The key principle is that a loop is only as trustworthy as the parts of its verification the agent cannot fake.", "body_md": "The idea is often credited to Boris Cherny (Head of Claude Code at Anthropic),\nwho put it bluntly: *\"I don't prompt Claude anymore. I have loops running that\nprompt Claude and figure out what to do. My job is to write loops.\"*\n\nThis document goes past the slogan into the mechanisms: the control-theory framing, the exact algorithms that make a loop safe, the concurrency internals, the cost math, and the epistemics of why an agent cannot be trusted to check itself.\n\n**Loop engineering is building a deterministic control loop around an AI coding\nagent — schedule + durable state + verification — so the agent drives the\nmoment-to-moment cycle and you move up to designing the machine.**\n\nThe single load-bearing principle:\n\nA loop is only as trustworthy as the parts of its verification the agent\n\ncannot fake. \"Am I stuck?\" and \"is this correct?\" must be decided by deterministic code or a genuinely independent checker —neverthe agent's own self-report.\n\nEverything below is a consequence of that sentence.\n\nA control system regulates a process toward a **setpoint** using feedback:\n\n```\n        setpoint (goal)\n            │\n            ▼\n   ┌──────────────┐   command   ┌──────────────┐\n   │  controller  │ ──────────► │   process    │\n   │ (your loop)  │             │(agent + repo)│\n   └──────────────┘             └──────────────┘\n            ▲                           │\n            │      measurement          │\n            └───────────  sensor  ◄─────┘\n                     (verifier / tests / metrics)\n```\n\n**Setpoint**= the goal (\"open PRs stay green\", \"no failing CI on main\").** Process**= the agent acting on the repo.** Sensor**= the verifier / test suite / numeric check — how you*measure*the gap between reality and setpoint.**Controller**= the loop logic that turns the measured gap into the next command.\n\nThe critical distinction from control theory:\n\n| Open-loop | Closed-loop | |\n|---|---|---|\n| Definition | Act, never measure the result | Act, measure, correct |\n| Agent analogy | \"Prompt → hope\" | \"Prompt → verify → decide → repeat\" |\n| Failure mode | Drifts arbitrarily far from goal | Bounded by sensor quality |\n\n**A raw agent call is open-loop.** You prompt, it acts, and nothing measures\nwhether the result matched intent — *you* do, manually. Loop engineering closes\nthe loop by making the sensor (verification) and the controller (decide/escalate)\npart of the automated system.\n\nThe corollary that governs everything: **a closed loop is only as good as its\nsensor.** A control loop with a broken thermometer will happily drive the room to\n1000°C while reporting \"72°F, all good.\" That broken thermometer is exactly what\nan LLM asked to grade its own work is (see §4).\n\nThree nested scopes. The jump from harness → loop is defined by adding\n**schedule + state + verification**.\n\n```\nContext engineering   →  what goes in ONE prompt              (\"one move\")\nHarness engineering   →  ONE agent's environment: tools,      (\"one game\")\n                         permissions, rules — a single session\nLoop engineering      →  harness + SCHEDULE + STATE +          (\"the tournament\")\n                         VERIFICATION, running over TIME\n```\n\n- Miss the\n**schedule**→ it's a one-off script (open-loop, runs once). - Miss the\n**state**→ the agent is amnesiac every run and re-tries failed things forever (no integral term — no memory of accumulated error). - Miss the\n**verification**→ the sensor is missing; the loop is \"closed\" only in appearance.\n\nThree properties of language models make the naive \"just let it run\" approach fail. The loop machinery exists to counter each one.\n\n-\n**Statelessness across sessions.** A model has no memory between separate runs. Whatever isn't written to durable storage is gone. → Requires**external state**(§5A). -\n**Uncalibrated self-assessment.** A model's confidence is not a reliable estimate of its correctness. The same reasoning that produced a bug produces the sincere belief that the bug is correct. Confidence and correctness are drawn from*correlated*distributions, not independent ones. → Requires an**independent sensor**(§4). -\n**Autoregressive momentum / no natural stop.** Given \"keep trying until CI is green,\" a model will keep generating attempts — including plausible-looking non-fixes — indefinitely, because \"produce the next token\" has no built-in notion of \"this is hopeless, stop.\" → Requires an**external circuit breaker**(§5B).\n\nLoop engineering is, precisely, the set of external mechanisms that supply the memory, the sensor, and the stop condition that the model lacks.\n\nThis is the load-bearing wall. Everything else is plumbing.\n\nLet `M`\n\nbe the maker (produces a solution) and `V`\n\nthe verifier (judges it).\nVerification adds information **only if V's errors are independent of M's\nerrors.** If\n\n`V = M`\n\n(same model, same context, same prompt lineage), then any\nmistake `M`\n\nis blind to, `V`\n\nis *equally*blind to. The verification is a rubber stamp — it multiplies confidence without adding evidence.\n\nThis is why \"run the tests once and mark it done\" is not verification if the same session wrote the tests and the code: a weak test written to pass weak code confirms nothing.\n\nLoops lean on a hopeful asymmetry: **checking a solution is often cheaper and\nmore reliable than producing one** (it's easy to verify a returned sort is\nordered; harder to write the sort). When this holds, an independent checker is a\ncheap, strong sensor.\n\n**But the asymmetry inverts when the artifact under review is itself the\ndistortion.** The canonical case:\n\nSomeone ran a hedge fund as a fully autonomous loop with an\n\nLLM verifier judging backtests. It failed because a strategy's failure mode isoverfitting— the strategy looks brilliant on historical data precisely because it was (accidentally) shaped to fit that exact history. A second LLM reading the backtestcannotcatch the curve-fit, because the backtest it's reading isalreadythe overfit artifact. The lie and the evidence-of-the-lie are the same document.\n\nThe fix was to replace the LLM verifier with a **numerical, non-overridable**\ncheck that measures something the maker structurally cannot fabricate:\n\n| Test | Sharpe | Verdict |\n|---|---|---|\n| In-sample (training data) | +2.54 | looks like a winner |\n| Out-of-sample (held out) | −4.33 | collapses |\n| Numerical checker | — | REJECT — no trade |\n\nThe +2.54 is exactly the number that would make a human — or an LLM verifier —\nship it. The out-of-sample split is data the maker *never touched*, so it cannot\nhave been fit to. **That untouchable measurement is the entire product.**\n\nThe maker/checker split is worthless unless the checker measures something the maker cannot fake. In code, that's an independent re-derivation of correctness (a real test run, a type check, a compile, an\n\n`EXPLAIN`\n\n); in statistics, it's out-of-sample, cost-aware, multiple-testing-penalized numbers — never a second model's vibe.\n\n| Layer | Mechanism | What it makes unfakeable |\n|---|---|---|\nAm I stuck? |\nDeterministic circuit breaker (§5B) | The agent can't claim \"progress\" — the numbers decide |\nIs it correct? |\nSeparate verifier sub-agent, default REJECT | The maker can't approve its own diff |\nIs it real? |\nNon-LLM checks: tests run, EXPLAIN, compile, OOS split | The maker can't fabricate the measurement |\n\n```\n   read STATE  ─►  TRIAGE  ─►  IMPLEMENT (maker sub-agent, isolated worktree)\n   (situation?)   (worth            │\n        ▲          doing?)          ▼\n        │                      VERIFY (checker sub-agent / numeric check)\n        │                           │\n   persist STATE ◄─ gate/escalate ◄─┘\n   (write down)   (safe? or human?)\n```\n\nState is a `STATE.md`\n\n(or DB row / ticket board) answering exactly three\nquestions — and deliberately nothing more, to avoid rot:\n\n- What are we working on now?\n- What did we try last time, and what was the outcome?\n- What is waiting on a human?\n\nIn control terms this is the **integral term**: it accumulates the history of\nerror so the controller can act on *trends*, not just the latest instant. Without\nit, the loop is memoryless and will re-attempt the same failed fix on every run.\n\n**State rot** is the dominant failure here: the file references merged PRs,\nclosed tickets, or dead branches, and the loop acts on ghosts. Mitigations: a\nprune step every run, a `Last run`\n\ntimestamp, validating IDs against the live API,\nand one state file per loop pattern (no shared unstructured file).\n\nThis is the most technically interesting component. It answers \"is this agent\nstuck?\" with **pure code — no LLM in the decision path**, so it's cheap to run\nevery iteration and impossible for the agent to argue past.\n\n**Data model:**\n\n```\ninterface Attempt {\n  iteration: number;\n  action: string;       // short description of what was tried\n  outcome: 'success' | 'failure' | 'noop';\n  error?: string;       // raw error / stack trace if failed\n  tokensUsed?: number;\n}\ninterface Ledger { goal: string; attempts: Attempt[]; }  // oldest → newest\n```\n\n**Step 1 — normalize errors to a stable signature.** Raw errors differ every run\neven when they're \"the same\" failure:\n\n```\n\"Error at db.ts:42 connection refused (0x7ff8a2)\"   ← attempt 1\n\"Error at db.ts:88 connection refused (0x3aa10b)\"   ← attempt 2\n```\n\n`errorSignature()`\n\nstrips the volatile parts so the same failure maps to the same\nkey:\n\n```\nISO timestamps   → <ts>\n0x…  hex addrs   → <addr>\nabsolute paths   → basename only\n:line:col        → removed\nany other digits → #\ncollapse spaces\n```\n\nBoth examples above collapse to `Error at db.ts connection refused`\n\n— **identical\nsignatures.** This is the crux: without normalization the loop would think every\nretry is a \"new\" error and never notice it's stuck.\n\n**Step 2 — measure similarity with character trigrams (Jaccard).** For actions\nand near-miss errors, exact-match isn't enough, so it uses set overlap of\noverlapping 3-character substrings:\n\n```\nJaccard(A, B) = |trigrams(A) ∩ trigrams(B)| / |trigrams(A) ∪ trigrams(B)|\n              → 0.0 (disjoint) … 1.0 (identical)\ndefault threshold ≈ 0.85 counts as \"the same\"\n```\n\nTrigrams are robust to trivial rewording (\"cannot connect\" vs \"can not connect\") in a way exact string compare is not, and cheap enough to run every iteration.\n\n**Step 3 — check triggers, cheapest & most-actionable first.** It walks the\n**trailing run of failures** (consecutive failures since the last non-failure)\nand returns the *first* condition that holds, so the reported reason is the most\nuseful one:\n\n| Order | Trigger | Fires when | Why this order |\n|---|---|---|---|\n| 1 | `stagnation` |\nsame error signature ≥ 3× in a row | most specific, most fixable |\n| 2 | `frustration` |\nnear-identical action repeated ≥ 3× in a row |\nsemantic looping |\n| 3 | `no-progress` |\n≥ 5 consecutive failures, no success between | broad \"going nowhere\" |\n| 4 | `token-budget` |\ncumulative tokens ≥ cap | cost ceiling |\n| 5 | `max-iterations` |\n≥ 10 iterations | absolute backstop |\n\nThe ordering is deliberate: stagnation (\"you keep hitting the *same* wall\")\ngives a human the most actionable escalation message; the iteration cap is a\ndumb backstop of last resort.\n\n**Step 4 — prune + inject.** Before the next iteration it builds a compact\ncontext block to prepend to the prompt so the agent doesn't repeat itself:\n\n```\n## Loop Context (managed)\n**Goal:** <goal>\n**Progress:** iteration 7 · 0 ok · 7 failed · 340k tokens\n\n**Already tried (do NOT repeat):**\n- bump pg driver to 8.11\n- add retry wrapper around connect()\n\n**Failure patterns:**\n- (5×) Error at db.ts connection refused\n\n**Most recent error (pruned):**   ← stack trace truncated to N lines\n...\n> Circuit breaker: OK (7/10 iterations used).\n```\n\nPruning keeps only the last N attempts, truncates stack traces to a few lines,\nand **collapses repeated identical failures into one entry with a repeated\ncount** — so a 40-line log of the same error becomes one line, keeping the\nnext prompt cheap and focused.\n\nSeparate from the breaker. The breaker knows *run history*; the gate knows\n*static policy* — and the two are deliberately kept apart (single responsibility;\nhistory logic lives in exactly one place).\n\nConfig (`gate.yaml`\n\n):\n\n```\nversion: 1\ndenylist:            # globs that must never be touched without a human\n  - \"**/secrets/**\"\n  - \"infra/prod/**\"\n  - \"**/*_key*\"\nmaxFiles: 20         # more than this in one change → escalate\nautoMergeAllowlist:  # for auto-merge, EVERY path must match one of these\n  - \"docs/**\"\n  - \"**/*.test.ts\"\n```\n\n`checkGate(action, paths)`\n\nruns three checks, most-severe first:\n\n**denylist**— any changed path matches a forbidden glob → BLOCK.** file-count**— more paths than`maxFiles`\n\n→ BLOCK (a huge diff is a red flag regardless of content).**allowlist**(auto-merge only) — any path*not*on the allowlist → BLOCK.\n\n**Subtle but important:** glob matching uses `dot: true`\n\n. Without it, `*`\n\nwon't\nmatch a path segment starting with `.`\n\n, so `**/secrets/**`\n\nwould silently miss\n`.secrets/prod.json`\n\nand `**/*_key*`\n\nwould miss `.aws_key`\n\n— exactly the hidden\nfiles a denylist most needs to catch. This is the kind of one-character bug that\nturns a safety control into security theater.\n\nWhen multiple agents run in parallel, two editing the same file is merge hell.\nEach agent gets its own **git worktree** (shares history, separate working tree).\nOn top of that sits an **advisory file-lock** system so two agents don't grab\noverlapping paths:\n\n- Each owner writes\n`.loop/locks/<owner>.json`\n\n=`{ paths, lockedAt, expiresAt? }`\n\n. **Cross-process atomicity** for the check-then-write critical section uses an exclusive-create mutex file:`open(path, 'wx')`\n\nfails if the file exists and is atomic on POSIX and Windows. Without this, two`lock`\n\ncalls racing could both pass the \"is it free?\" check before either writes — the exact collision the feature exists to prevent.**Path overlap** is a deliberately-simple segment-by-segment glob compare (`src/**`\n\ncovers`src/a/b.ts`\n\n; a wildcard segment matches anything). Advisory, not a full glob engine.**TTL / expiry**: locks can auto-expire so a crashed agent doesn't wedge the system forever; a sweep reclaims expired locks.** Deadlock detection**: waiting agents write`.wait.json`\n\nentries recording who they're blocked on. Before waiting, the system runs**DFS cycle detection** over the wait-for graph and throws`Deadlock detected: A → B → A`\n\ninstead of hanging forever. (Classic OS deadlock avoidance, applied to agents.)\n\nWhen the breaker trips or the gate blocks, the loop must **stop and notify** — not\nsilently retry. The failure mode here is \"escalation only writes to a state file\nno one reads.\" Real escalation pings a human through a connector (Slack, a Linear\ncomment) and parks the item in a `Waiting on human`\n\nsection, ideally with an\nalert if it sits there > 24h.\n\n```\nruns_per_day        = 86,400,000 ms/day ÷ interval_ms\ntokens_per_day      = runs_per_day × tokens_per_run\nblast_radius_per_day ∝ runs_per_day × P(bad action) × mean_damage\n```\n\nSo going from a 1-day to a 5-minute cadence is **288× the runs — and 288× the\ncost and 288× the blast radius.** A one-off agent making a bad edit is annoying;\na loop making it 288×/day unattended and merging it is an incident.\n\nNot every run costs the same. A realistic model weights three outcome types:\n\n```\ncost_per_run = P(noop)  × tokens_noop      (nothing to do — cheapest)\n             + P(report)× tokens_report    (found something, described it)\n             + P(action)× tokens_action    (ran maker + verifier — most expensive)\n```\n\nThe mix shifts with autonomy level (more autonomy → more actions → higher cost):\n\n```\nL1 ≈ {noop .6, report .4, action  0 }\nL2 ≈ {noop .5, report .3, action .2}\nL3 ≈ {noop .4, report .35,action .25}\n```\n\nTriage cheaply first. Spawn expensive maker+verifier sub-agents\n\nonlywhen state says there's something actionable. Empty watchlist → exit in <5k tokens.\n\nA loop that runs the full sub-agent chain on every empty tick is the #1 way to turn a 5-minute cadence into a runaway bill.\n\n\"Why We Killed Our CI Sweeper After Day 4\": ran every 5 min on a broken branch →\n**8M tokens in 48h**, proposed 11 fixes, 3 were fake symptom-fixes, **1 broke prod\nconfig**. Root causes: no report-only phase, verifier in the *same session* as the\nmaker, no budget cap, no branch allowlist. Every one of those is a missing\nmechanism from §5.\n\nAutonomy is earned incrementally, each rung adding a mechanism and proving it before the next:\n\n```\nL1  REPORT ONLY      looks + triages, takes NO action. Run 1–2 weeks.\n                     Measure: is the triage even accurate?\n      ↓  add: separate verifier, worktree, attempt cap, human-approved merge\nL2  ASSISTED FIXES   proposes changes; human approves merges.\n      ↓  add: path denylist, token budget, metrics, human gates on risk\nL3  UNATTENDED       acts alone within hard, machine-enforced limits.\n```\n\nA readiness scorer can encode this as a **gate, not a suggestion**: it scans the\nproject for ~35 signals (state file? verifier skill? `gate.yaml`\n\n? budget doc? run\nlog? evidence of real runs in git history?), sums weighted points to a 0–100\nscore, and maps score → level (roughly L1 ≥ 38, L2 ≥ 58, L3 ≥ 78). Crucially, an\nL3 score is **capped back to L2 unless** it *also* finds: a verifier, a budget\nfile, a run log, AND git evidence you actually ran the loop. **You cannot score\nyour way to \"unattended\" without proof you earned it.**\n\n| # | Primitive | Supplies | Counters (from §3) |\n|---|---|---|---|\n| 1 | Scheduling |\nthe heartbeat (cron, `/loop 5m` , CI on a timer) |\n— (makes it a loop) |\n| 2 | Worktrees |\nparallel isolation + locks (§5D) | orchestration collisions |\n| 3 | Skills |\nwritten-down intent: conventions, build cmds | intent debt / statelessness |\n| 4 | Connectors (MCP) |\nreach real tools: GitHub, Jira, Slack, DBs | — (makes it useful) |\n| 5 | Sub-agents (maker/checker) |\nindependent verification (§4) | uncalibrated self-assessment |\n| 6 | Memory / State |\nthe durable spine (§5A) | statelessness |\n\nBuild the **minimum viable loop first**: schedule + one triage skill + a state\nfile, report-only. Add each further primitive *only after* the previous version\nproved its value and revealed its failure modes. Worktrees when you start making\nchanges; the verifier when you start acting autonomously; write-scoped connectors\nlast.\n\n**Goal:** keep open PRs green and reviewed without a human polling GitHub.\n\n```\ncadence:  10–15m during work hours\nstate:    pr-babysitter-state.md  (row per PR: last SHA, attempts, status)\n\nloop turn:\n  1. TRIAGE (cheap):  gh pr list --json number,headRefOid,statusCheckRollup\n     → PRs whose checks are RED and whose SHA changed since last run\n  2. if none actionable → exit in <5k tokens                  # §6.3 early exit\n  3. for each actionable PR:\n       acquire worktree lock on that PR's paths                # §5D no collision\n       MAKER  sub-agent: smallest diff to fix the failing check\n       CHECKER sub-agent (stronger model, \"find reasons to REJECT\"):\n            actually RUN  npm ci && npm test  and report output # §4 real sensor\n       BREAKER: 3rd attempt on same failing check → STOP, escalate (§5B/5E)\n       GATE:    checkGate('commit', changedPaths) before pushing (§5C)\n  4. persist STATE + append loop-run-log.md\n```\n\nGuardrails doing real work: attempt cap kills infinite-fix loops; verifier\n*runs* tests (kills \"verifier theater\"); worktree lock kills parallel collisions;\ngate kills over-reach into denylisted paths.\n\nWatches a text-to-SQL service and self-heals bad generated SQL — with a checker\nthe LLM **cannot** fake (directly applies §4.2).\n\n```\ntrigger:  event = \"generated SQL failed / returned suspicious result\"\nMAKER:    LLM regenerates SQL from the question + schema + prior errors\nCHECKER:  NON-LLM, non-overridable:\n            - EXPLAIN parses without error          (syntax/plan valid)\n            - runs on a READ-ONLY replica with LIMIT (bounded, safe)\n            - row count / column types sane vs the question's expected shape\n            - planner cost estimate < threshold      (no full scan on a 2B-row fact)\nBREAKER:  same SQL-error signature 3× → escalate to a human analyst (§5B)\nSTATE:    questions that repeatedly fail → surfaces schema / prompt gaps\n```\n\nWhy it fits the root: an LLM asked \"does this SQL look right?\" is verifier\ntheater. `EXPLAIN`\n\n+ a bounded run on a real replica measures something the\ngenerator **cannot** fabricate — the same lesson as the quant backtest, in SQL.\n\n```\ncadence:  6h–1d\nscope:    PATCH + low-risk CVE only for the first 30 days   # blast-radius control\nMAKER:    bump one dependency → one PR\nCHECKER:  full  npm ci && npm test  IN A WORKTREE            # real, not \"looks fine\"\nGATE:     majors + denylisted packages → human, never auto (§5C allowlist)\ncadence:  1d, weekdays, via CI on a timer\nskill:    triage-only — structured output, ONE line per item + suggested action\naction:   NONE. Writes findings to STATE.md; human reviews weekly.\ncost:     ~50k tokens/day (one light run)\npurpose:  the report-only rung — prove the triage is accurate before ANY autonomy\n```\n\n| Failure | Symptom | Root cause | Prevented by |\n|---|---|---|---|\n| Infinite fix loop | same PR \"fixed\" 5+ times, never converges | no attempt cap; weak verifier | circuit breaker (§5B) + separate verifier |\n| Verifier theater | \"looks good\" but CI red | same model/context; vague prompt | independent checker that runs tests (§4) |\n| State rot | acts on merged PRs / dead branches | no prune; unread state | prune step + `Last run` + ID validation (§5A) |\n| Token burn | bill spikes on empty ticks | full chain on every run | cheap triage + early exit + budget (§6.3) |\n| Over-reach | edits unrelated / forbidden paths | permissive skill; no denylist | gate.yaml denylist + smallest-diff (§5C) |\n| Parallel collision | two agents edit same file | no isolation | worktree + advisory lock (§5D) |\n| Escalation failure | stuck loop, human never told | max-attempts unimplemented; silent state | breaker + connector ping (§5E) |\n| Comprehension debt | ships faster than anyone can read | human stopped reading | mandatory review + weekly digest |\n| Cognitive surrender | \"the loop handles it,\" no opinions | success metric = volume | human gates + metric = quality-held |\n\n**Intent debt**— the agent's cold-start ignorance of your conventions. Fix: skills, written once, read every run.** Comprehension debt**— the loop ships code faster than you can read it, so you stop understanding your own repo. Fix: mandatory human review of non-trivial diffs; a weekly loop digest.**Cognitive surrender**— you stop having opinions on correctness. The knife's edge:*designing loops with judgment is the cure; using loops to avoid thinking is the accelerant — same action, opposite outcome.***Orchestration tax**— the human cost of coordinating N parallel agents. Worktrees remove the mechanical collisions, but** you remain the ceiling**on how many loops you can actually absorb and review.\n\n- The thing that decides \"done/correct\" is\n**not** the thing that produced the work, and measures something the producer can't fabricate. - There is a\n**hard, machine-enforced** cap on iterations, tokens, and repeated failures — the loop escalates instead of spinning. - Every run\n**reads and writes durable state**; nothing important lives only in a model's transient context. - High-risk paths are on a\n**denylist enforced in code**, not in a prompt's good intentions. - Parallel workers are\n**isolated** and cannot silently clobber each other. - Autonomy is\n**earned up a ladder**, each rung proven before the next. - A human is\n**pinged on escalation** through a channel they actually read.\n\nThe harness ships every primitive natively, so you rarely need bespoke CLIs — you\nneed the *discipline*:\n\n| Loop primitive | Claude Code equivalent |\n|---|---|\n| Scheduling | cron / scheduled tasks / `/loop` |\n| Worktrees | `isolation: \"worktree\"` on sub-agents |\n| Skills | Skills / `SKILL.md` |\n| Connectors | MCP servers |\n| Maker/checker | sub-agents (Agent tool), a stronger verifier |\n| Circuit breaker / budget | Workflow token `budget` + loop-until conditions |\n| Memory / state | file memory / a committed `STATE.md` |\n\n**Bottom line:** treat the agent as an unreliable actuator inside a control loop\nyou own, where every trust boundary is decided by deterministic code or a\ngenuinely independent checker — build it like someone who intends to stay the\nengineer, not just the person who presses go.", "url": "https://wpnews.pro/news/loop-engineering-a-deep-technical-explanation-with-realistic-examples", "canonical_source": "https://gist.github.com/eshwarvijay/2adc5abdb9bb2d0b89c5b11b29a02afa", "published_at": "2026-07-23 16:55:36+00:00", "updated_at": "2026-07-23 17:29:06.458218+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-agents", "ai-safety", "developer-tools", "large-language-models"], "entities": ["Boris Cherny", "Anthropic", "Claude Code"], "alternates": {"html": "https://wpnews.pro/news/loop-engineering-a-deep-technical-explanation-with-realistic-examples", "markdown": "https://wpnews.pro/news/loop-engineering-a-deep-technical-explanation-with-realistic-examples.md", "text": "https://wpnews.pro/news/loop-engineering-a-deep-technical-explanation-with-realistic-examples.txt", "jsonld": "https://wpnews.pro/news/loop-engineering-a-deep-technical-explanation-with-realistic-examples.jsonld"}}