Chapter 05 · Section I · 11 min read
5.1 A complete loop: the batteries-included version
The same triage-and-PR job, built with an agent tool where trigger, sandbox, tools, and verifier already come wired together. Fastest path to a working loop.
To make the six-part model concrete, let’s walk one job — a morning code-review loop that ends in a pull request — through a batteries-included tool. Then in 5.2 we’ll walk the same job assembled from scratch. The point of the pair is that the shape of the loop is the same at both ends; only the commands change.
The job
Every morning at 6am, look at the open pull requests in the team’s repo. For any PR that:
- Is more than 24 hours old
- Has passing CI
- Has no reviews yet
…run a review pass, post comments, and mark the PR as reviewed by the loop. If the PR needs anything that isn’t purely stylistic — architecture concerns, security issues, unclear intent — escalate to a human by tagging the on-call engineer instead of leaving comments.
Mapping the job to the six parts
| Part | For this job |
|---|---|
| Trigger | Scheduled — every day at 6am. |
| Sandbox | A fresh git worktree per PR, one per cycle. |
| Reusable knowledge | The team’s code-review checklist (.review.md) and the repo’s CLAUDE.md. |
| Tools | read_file, run_shell_command (for tests), list_open_prs, post_pr_comment, tag_user, mark_pr_reviewed. |
| Do-and-verify | Reviewer subagent produces comments; a separate verifier subagent checks each comment against the checklist before posting. |
| Memory | JSON log: {cycle_id, prs_reviewed: [PR#], prs_escalated: [PR#], notes}. Read at start; written at end. |
That table is the design. Everything else is filling in the shape.
Building it batteries-included
Batteries-included tools ship most of the plumbing. You configure the six parts rather than write them from scratch.
Trigger. The tool has a “run this workflow on a schedule” feature. You give it a cron expression (0 6 * * *) and a command to run. The scheduler lives on the tool’s servers; your laptop can be off.
Sandbox. The tool creates a fresh worktree for each cycle automatically. When the cycle finishes, the worktree is deleted. You don’t manage this.
Reusable knowledge. The tool has a convention for a memory file in the repo (CLAUDE.md, AGENT.md, or similar). You put the review checklist there. Loaded on every cycle without any explicit code.
Tools. The tool ships built-in ones for file I/O, shell, and git. For the PR-specific ones (list_open_prs, post_pr_comment, tag_user), you install a plug-in — probably a GitHub connector — that adds those verbs to the model’s toolbox.
Do-and-verify. The tool supports subagents. You define a pr-reviewer subagent that produces comments and a review-verifier subagent that grades them against the checklist. The main loop calls one, then the other, then decides.
Memory. For simple loops, you can lean on the tool’s built-in “memory” features — a scratchpad it maintains across sessions. For a serious loop, you write a small file to the repo (.loop-state.json) that both cycles read and update.
What the day-1 configuration looks like
Rough shape:
# .loop/morning-review.yaml
schedule: "0 6 * * *"
workspace: worktree
reusable_knowledge:
- .review.md
- CLAUDE.md
subagents:
- pr-reviewer
- review-verifier
plugins:
- github
memory: .loop-state.json
budget:
max_prs_per_cycle: 10
max_tokens_per_pr: 30000
…plus the two subagent definitions and the small verifier checklist. On a good day, a person familiar with the tool can have this running by lunch.
Where this version shines
- Time to first run. Hours, not days.
- Handling of the boring parts. Logs, retries, error messages, per-cycle isolation — all handled for you.
- Ecosystem. Someone else has already written the GitHub plugin, the Slack plugin, the Google Sheets plugin. You wire them together.
Where this version hurts
- You’re stuck with the tool’s abstractions. If the tool thinks of a “cycle” as one session and you want the cycle to span multiple sessions, that’s a rewrite or a fight.
- Debugging when it goes wrong. The plumbing is opaque. When the scheduler doesn’t fire, you’re deep inside someone else’s system.
- Cost model isn’t yours. You pay the tool’s markup on model calls. Fine at small scale; can matter at large.
Escalation and human gates
Even a batteries-included loop should have explicit escalation. In this job, the trigger for a human tag is:
- The verifier rejected the reviewer’s comments (couldn’t confidently ship them).
- The reviewer flagged an architectural or security concern.
- The PR touches a path from a designated “sensitive” list (auth, payments, permissions).
For any of these, the loop does not post comments. It tags the on-call engineer with a one-line summary of why it’s escalating. Human takes it from there.
Preview of the assemble-your-own version
In 5.2 we take the same table (trigger, sandbox, knowledge, tools, do-and-verify, memory) and implement each one directly — cron + a Python script + a couple of GitHub API calls + a simple file-based state store. Same six parts, no tool doing them for you.
Check your understanding
Quick check
—