Lesson 31 of 36
The line learns nothing unless a second loop runs
On this page
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.
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.
| Condition | Executor fixes the work | Outer loop fixes the procedure |
|---|---|---|
| Recurs weekly, correction attributable to one procedure step | Pays the same correction every week; the fix leaves with the run | Wins: one reviewed diff removes the weekly cost |
| Recurs once | Wins: fix it and move on | Loses: the review costs more than the mistake |
| Recurs weekly, but nobody records why it was corrected | Pays every week, but claims nothing it cannot support | Loses today: the proposal would be a guess; capture the reason first |
| Task recurs, procedure lives in someone's head | Pays every week | Cannot run: no file to propose against |
The decision tree is short enough to run on a single correction.
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.
Class Agent Runs a week Human corrections a week Where captured Attributable? Needs-info vs ready triage 120 10 label-change events yes, one step Style nits review 40 11 dismissals resolve button no reason given Page drift docs 15 2 nowhere unknown (none recurring) spec, implement 30, 25 0 n/a n/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.
- 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.
- 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.
- 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
failedRunThresholdconfigurable 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. - 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:
Loop map: triage routing
| Loop | Agent | Reads | Writes | Trigger | Reviewed by |
|---|---|---|---|---|---|
| Executing | triage | new issue thread; skills/triage-routing/SKILL.md | label ready or needs-info, plus a one-line reason in the run record | issue opened | nobody per run; sampled by the scorer |
| Improving | triage-improver | rerouted issues since the last collection; run records for those issues; the maintainer's reason | one pull request changing only skills/triage-routing/SKILL.md, listing the run ids behind each change | 5 uncollected rerouted issues, or the oldest is 14 days old | the maintainer who re-routes, never the improver |
Signals the improving loop may read
- A human changed the label the agent set (label-change event, actor is human).
- The maintainer's reason, written as
rerouted: <label> - <why>. - 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.
Week Corrections Fix minutes What the loop did Review minutes 1 10 40 Proposal 1 replays correctly on 6 of 8 held-out cases; reviewer rejects one over-broad clause and merges the rest 15 2 4 16 Under the count and the age: nothing runs 0 3 5 20 Count fires; proposal 2 covers reports with steps in a linked file; reviewer drops one case where the maintainer's own re-route was wrong 10 4 2 8 Nothing runs 0 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:
| Loop | Agent | Reads | Writes | Trigger | Reviewed by |
|---|---|---|---|---|---|
| Improving | review-improver | ? | one pull request changing only skills/review-style/SKILL.md | 5 uncollected dismissals | the 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
- Warp: factories overview shows the default agents and the rule that the factory never merges for you.
- Warp: self-improvement documents the failure trigger, the reviewer types and the follow-up pull request.
- Warp: scorers explains classification-based evaluation and sample rates, the other signal an improving loop can read.
- Warp: factory as code shows how a definition goes through pull request review like any other code.
- Agent Skills specification defines the
SKILL.mdfile the improving loop writes against.
Exercises
- 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 themfor one agent class in your own factory, using the last four weeks of human corrections as the first collection. - 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.
- 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