Lesson 31 of 36

The line learns nothing unless a second loop runs

ReadFree to read · saving needs Core20 min · Slice → Gate → Run → Wrap → Prove · Updated 2026-10-29
You end this lesson with: factory/improve/loop-map.md — the executing loop and the improving loop on one page: the signal each reads, the artifact each writes, and the trigger between them
view

Take a triage agent on the issue queue of a busy repository. Every week the same kind of report, a bug whose reproduction steps sit in the second paragraph, gets routed needs info instead of ready. The agent replies asking the reporter for steps they already gave. A senior maintainer notices, flips the label by hand, and apologizes to the user. The fix takes four minutes and happens ten times a week. Nobody records that it happened, so Monday's run makes the same mistake on the same kind of report. That is forty minutes a week of the most expensive attention on the team, plus a growing pile of threads where a user was asked for something they had already supplied. The signal that would stop this was never missing. It was a thumbs-down here, a one-line reply from an employee there, a label flipped by hand. All of it sat in the system and no process spent it. Decide now: after a maintainer corrects the agent, where does that correction go, and who reads it before the next run?

The deliverable is factory/improve/loop-map.md — the executing loop and the improving loop on one page: the signal each reads, the artifact each writes, and the trigger between them. It serves the Prove stage of this course's loop (Slice → Gate → Run → Wrap → Prove): Prove decides whether the line earned autonomy, and the loop map is where that evidence gets spent on changing the line itself, with two agents, one signal and one artifact each.

What is actually going on

A skill is a procedure. In the Agent Skills specification (first-party, observed 2026-10-29) it is a SKILL.md file: YAML frontmatter with a name and a description, then a Markdown body with no format restrictions. The specification requires no version field, so the file's history is whatever your version control keeps. Warp's documentation describes skills the same way, as "repeatable, version-controlled procedures" (Warp docs, first-party, observed 2026-10-29).

A run produces two things. The first is the work item: a label, a spec, a pull request. The second is evidence: the transcript, the tool calls, and what people did afterwards, such as a thumbs-down, a one-line reply or a label flipped by hand. The executing agent's context ends with the run. It never sees the hand correction, because that arrives hours later, after the run is over and its context is gone. Anything the run noticed about itself dies the same way.

The improving loop is a second agent on a different clock. It reads run outputs and human corrections across many runs, and it writes one thing: a proposal against the procedure file, which is a diff. It does not write better behaviour. Behaviour changes only after a person approves the diff and the file changes. Warp's self-improvement feature has this shape: "Turn on Self-improvement for a Scorer to turn its repeated failures into follow-up pull requests you review" (Warp docs, first-party, observed 2026-10-29).

In the diagram, count the arrows that enter the procedure file; there is one, and it is dotted.

diagram
drawing
Two loops share one procedure file, and only a reviewed proposal changes it.

The diagram showed two agents that never write each other's output: the inner agent reads the procedure and writes work, the outer agent reads evidence and writes proposals. The only edge that closes the loop passes through a review.

That structure explains why the executor cannot be its own improver. Its context ends with the run, so it has no history to compare against. It has no distance: it judges the mistake with the same reading that made it. And it would be editing the file it is judged by, so every doubt becomes a procedure change with no reviewer in between.

The rule and its condition

Run the second loop when three things hold: (a) the task recurs, (b) the procedure is a file, and (c) a correction signal is captured somewhere you can query. Otherwise fix the work inline and write nothing.

Each condition protects against a specific waste. Without (a), the diff costs more review than the one-off fix it prevents. Without (b), there is nothing to diff; write the procedure down first. Without (c), the improving agent has only its own guesses to read. A tagged label change or a logged dismissal counts as capture. A chat message to a colleague does not.

You can test the condition on your own history today. Pull the last three times a human corrected an agent's output. If two or more fall in one class and each left a trace you can query, the second loop has material. If they are three unrelated fixes, nothing recurs yet.

ConditionExecutor fixes the workOuter loop fixes the procedure
Recurs weekly, correction attributable to one procedure stepPays the same correction every week; the fix leaves with the runWins: one reviewed diff removes the weekly cost
Recurs onceWins: fix it and move onLoses: the review costs more than the mistake
Recurs weekly, but nobody records why it was correctedPays every week, but claims nothing it cannot supportLoses today: the proposal would be a guess; capture the reason first
Task recurs, procedure lives in someone's headPays every weekCannot run: no file to propose against

The decision tree is short enough to run on a single correction.

diagram
drawing
Three questions decide whether a correction earns a second loop.

Worked case

A factory has five agents on one repository: triage, spec, implement, review and docs. A factory is "a team of cloud agents connected to your repositories" that routes work through triage, planning, implementation and review (Warp docs, first-party, observed 2026-10-29); the docs agent is this factory's own addition. You have the capacity to build one second loop this month. One maintainer reviews procedure changes, and procedures live in skills/<name>/SKILL.md.

Illustrative composite. Every number in the opening, in this table and in the weeks that follow is modeled, not measured.

ClassAgentRuns a weekHuman corrections a weekWhere capturedAttributable?
Needs-info vs readytriage12010label-change eventsyes, one step
Style nitsreview4011 dismissalsresolve buttonno reason given
Page driftdocs152nowhereunknown
(none recurring)spec, implement30, 250n/an/a

You have two ways to improve the triage class. Option 1: the triage agent edits its own skill at the end of any run where it doubts itself. Option 2: a separate agent, on a trigger, reads collected corrections and opens a pull request against the skill.

Decide now: which class gets the second loop, and does the triage agent or a separate agent write the procedure file?

Triage gets it, and a separate agent writes the file. The reasoning goes in four steps.

  1. Score the classes against the three conditions. Triage recurs 120 times a week, its procedure is a file, and every hand re-route is already a label-change event in the issue history. Style nits have a signal but no reasons; that is the faded case. Page drift has two corrections and no capture, so you fix it inline.
  2. Reject self-editing. The correction has not happened when the run ends, so the agent can only edit toward its own doubt, the judgment that was wrong. With 120 runs a week the file can change up to 120 times, on the schedule of doubts rather than evidence, with no reviewer and no record of why a clause exists. When the next run gets worse you cannot tell which edit did it. A mistake is fixed when the procedure changes, not when the label does.
  3. Set the trigger between the loops. Warp's default is "after an agent has 25 distinct unreviewed failures, or when its oldest unreviewed failure is seven days old", with failedRunThreshold configurable from 1 to 50 (Warp docs, first-party, observed 2026-10-29). At 10 corrections a week the 25-count takes two and a half weeks, so the age clause would fire first. Your map chooses 5 uncollected corrections or 14 days, whichever comes first.
  4. Separate the reviewer and hold out cases. The improver never merges its own proposal (Lesson 04, The Author Never Holds the Merge Key), and the file it edits is a governing file (Lesson 06, Protect the Files That Govern the Agent). It drafts from 8 of every 10 corrections and replays the draft on the 2 it did not see (Lesson 05, Holdouts Need Exact Figures).

This is the page you commit:

markdown

Loop map: triage routing

LoopAgentReadsWritesTriggerReviewed by
Executingtriagenew issue thread; skills/triage-routing/SKILL.mdlabel ready or needs-info, plus a one-line reason in the run recordissue openednobody per run; sampled by the scorer
Improvingtriage-improverrerouted issues since the last collection; run records for those issues; the maintainer's reasonone pull request changing only skills/triage-routing/SKILL.md, listing the run ids behind each change5 uncollected rerouted issues, or the oldest is 14 days oldthe maintainer who re-routes, never the improver

Signals the improving loop may read

  1. A human changed the label the agent set (label-change event, actor is human).
  2. The maintainer's reason, written as rerouted: <label> - <why>.
  3. Run records for those issues. Nothing else.

Artifact

One pull request per trigger. Each changed line cites the run ids that justify it. Two of every ten collected cases stay out of the draft and are used to replay it.

Trigger between the loops

Count or age, whichever fires first. Under the count and younger than the age: do nothing.

Out of bounds

The improver cannot merge, cannot write outside skills/triage-routing/, and cannot edit this file or any scorer.

The four weeks after that look like this.

Illustrative composite. Modeled, not measured. The 28-day backlog of 40 re-route events is the first collection; 32 draft the change, 8 are held out.

WeekCorrectionsFix minutesWhat the loop didReview minutes
11040Proposal 1 replays correctly on 6 of 8 held-out cases; reviewer rejects one over-broad clause and merges the rest15
2416Under the count and the age: nothing runs0
3520Count fires; proposal 2 covers reports with steps in a linked file; reviewer drops one case where the maintainer's own re-route was wrong10
428Nothing runs0

Total 109 minutes against 160 at the old rate, before the cost of the improver's own runs.

The rejected option fails on cost, not taste: the week-3 wrong correction would have been written into the procedure with nobody positioned to catch it.

Faded case

Skip to the open case if this is familiar.

Same repository, a different class: the review agent's style nits. The three-condition test is the one you already ran.

Illustrative composite. The review agent posts 14 style comments a week. Authors dismiss 11 of them with the resolve button and no text. Procedure: skills/review-style/SKILL.md. Modeled, not measured.

The task recurs weekly and the procedure is a file. A correction signal is captured, because every dismissal is logged. The platform shows who dismissed a comment and when, but not why. The same maintainer would review any procedure change. Dismissals cluster on a few authors, and the log cannot tell a wrong nit from a nit the author simply disliked. A teammate has drafted the improving row and left one cell open:

LoopAgentReadsWritesTriggerReviewed by
Improvingreview-improver?one pull request changing only skills/review-style/SKILL.md5 uncollected dismissalsthe maintainer

Your decision: is that signal strong enough to justify a second loop now, or does it fail the rule on some other ground? Say what goes in the "Reads" cell, or why the row stays empty. Give the cost of the option you reject, as the worked case did.

Open case

A support-triage agent receives about 15 tickets a week that rota agents re-route by hand, and every re-route is tagged rerouted in the helpdesk with a one-line reason, because the rota lead insisted on it last quarter. A docs agent opens pull requests against the product documentation that merge without edits, and when someone fixes a page weeks later nobody records whether the docs agent's text was the cause; a teammate proposes one nightly job that reads yesterday's runs from both agents, decides what each should have done differently, and rewrites both procedures directly. You have an afternoon to turn that proposal into something you would actually schedule. Say what runs, for which agent, how often, what it writes, who reviews it, and what you leave out.

Where this breaks

Self-grading. If the improving agent also picks the measure that says its change worked, it optimizes the measure. The cheapest way to drive rerouted tags to zero is to make people stop tagging, or to route everything ready until maintainers stop looking. Keep the measure outside the improver's write scope: a locked scorer, in the terms of Loop Engineering, and a held-out replay set. A scorer "assigns a classification, not a numeric grade" (Warp docs, first-party, observed 2026-10-29), and the improver must not be able to edit it.

Wrong corrections and untrusted text. A hurried maintainer re-routes an issue that really needed information, and the improver learns the wrong rule. The reviewer's job is to read the run ids behind each changed line, not the summary. Free-text reasons and user replies also reach the improver, so treat them as data it reads and never as instructions it follows, and keep its write access to one path.

Scope drift and loop-worthiness. Given a loose brief, the improver begins fixing neighbours: another skill, a scorer, its own instructions. A path allowlist enforced by a pull request check makes that fail loudly. And not every recurring task passes the four-test screen for loop-worthiness in Loop Engineering; when yours fails, the second loop costs reviewer attention and returns nothing. Review throughput is the ceiling, as Agent Fleets argues, so every proposal you add competes with real work.

Key Takeaways

  • Capture every human correction of an agent where a second agent can query it.
  • Run the second loop only when the task recurs, the procedure is a file, and a signal exists.
  • Write the improving loop's output as a diff against the procedure file, never as changed behaviour.
  • Lock the scorer and the held-out replay set outside the improver's write scope.
  • Hold the line: A mistake is fixed when the procedure changes, not when the label does.
  • Skip the second loop for one-off tasks and fix them inline.

What You Have Now

factory/improve/loop-map.md — the executing loop and the improving loop on one page: the signal each reads, the artifact each writes, and the trigger between them is committed in your factory definition, next to the skills it governs. It serves the Prove stage of the loop (Slice → Gate → Run → Wrap → Prove): the evidence that earned a line its autonomy now also decides which procedure gets a proposal, who reads it and when. You hold a map of one class, a trigger that is neither a calendar nor a hunch, and a rule for refusing the classes that fail the three conditions.

Further Reading

Exercises

  1. Write factory/improve/loop-map.md — the executing loop and the improving loop on one page: the signal each reads, the artifact each writes, and the trigger between them for one agent class in your own factory, using the last four weeks of human corrections as the first collection.
  2. Pull your last three human corrections of an agent's output and run the three-condition test on each. Write one sentence per correction naming the branch of the decision tree it lands on.
  3. Design the guard around your improver: the path allowlist, the held-out replay, and what you check first if corrections fall to zero in one week.

Not savedReading every lesson is free; you only pay to save progress and do the labs.See plansSign in

Check your understanding


Not savedReading every lesson is free; you only pay to save progress and do the labs.See plansSign in