Adding Agentic Loops to Exponential

exponentialaisoftware-engineeringbuilding-in-public

Every coding session on Exponential followed the same script. I’d pick a story from the backlog, ask the agent to prep a spec for me to review. Approve it, ask it to transition the story to DOING, create a branch, start building. When the code was done, ask for a walkthrough so I could follow along the diff. Review, send corrections, review again, mark it DONE. Next story.

The workflow rules in AGENTS.md spelled it out explicitly: check the backlog, start the task, implement, present a walkthrough, get approval, mark done. Every agent followed them. And I found myself typing the same prompts to kick off each phase, in the same order, every single time.

This worked. Really well, actually. Short feedback loops, me sitting in front of the IDE and terminal, tight control over what got built and how. The AiSE process kept the quality high. The specs kept the agents from drifting. I could review a diff in context, catch the gaps, course-correct in real time. For focused deep-work sessions, this was exactly right.

But I wanted more. I wanted stories to get done while I shower. While I pick up the kids from school. While I’m at the grocery store or asleep. The feedback loop was tight, but it was still tethered to me being there, typing the next prompt, reading the next diff.

Automation through Agentic Loops

Geoffrey Huntley’s Ralph Wiggum loop is the simplest version of the answer. A bash loop. while :; do cat PROMPT.md | claude-code ; done. The agent runs, does some work, exits. The loop feeds it the same prompt again. Repeat until done. Named after Ralph Wiggum from The Simpsons: oblivious, persistent, eventually getting somewhere through sheer repetition. As Huntley puts it, “deterministically bad in an undeterministic world.” It works surprisingly well for greenfield projects where “done” can be defined by tests passing and builds succeeding.

Andrej Karpathy drew the sharper line at Sequoia Ascent in April. Vibe coding raises the floor. Agentic engineering raises the ceiling. The agentic engineer doesn’t blindly accept generated code. They design specs, supervise plans, inspect diffs. The developer becomes an orchestrator of agents, delegating macro actions like “implement this feature” while maintaining oversight of the architectural decisions underneath. Specs before code. Supervision over autonomy.

Boris Cherny, who built Claude Code, took it further: “I don’t prompt Claude anymore. I have loops running that prompt Claude.” The unit of effort shifts from writing a good prompt to designing a loop that keeps the agent on track until the goal is met. His loop engineering architecture separates the work into automations, worktrees, skills, plugins, and sub-agents, with the critical insight that the code-writer shouldn’t grade its own work.

All three ideas pointed at the same thing from different angles. Huntley showed that iteration beats perfection. Karpathy showed that structured supervision beats blind autonomy. Cherny showed that the loop itself is the thing you engineer, not the prompt inside it.

Guided, not unguided

The vanilla Ralph loop is powerful, but it’s also unguided. The agent figures out what to do, does it, checks if it’s done, and tries again. For a well-scoped greenfield task with clear pass/fail criteria, that’s enough. For ongoing product work on a growing codebase with accumulated design decisions, patterns, and constraints, it’s the vibe coding trap in a bash wrapper. The agent still rolls dice at every branch point.

The AiSE process exists precisely to prevent that. Specs before code. Decisions captured at branch points. A knowledge corpus that compounds. The question became: how do you wire that process into a loop that runs without me?

The shape of the loop

The implementation landed as xpo drive. You point it at an issue (or let it pick the next planned story from the backlog), and it runs the full execution track autonomously. Under the hood there are two agents and a Go orchestrator that manages the process.

The Orchestrator is the DriveIssue() function in Go. It owns the lifecycle: transitions the story to DOING, creates the working branch, attaches the spec and walkthrough as artifacts, runs the tests, and either merges on success or marks the issue BLOCKED on failure. The agents never touch workflow transitions directly. The coder prompt explicitly says “Do NOT manage issue lifecycle.” This separation matters because the process logic is deterministic. The agents handle the creative work. The orchestrator handles the plumbing.

The Supervisor is an LLM agent that wears three hats. First, it evaluates the spec: reads the story and decides whether the spec is solid enough to build from. Second, it gathers context: examines the repository and identifies the relevant files, architectural patterns, and the right test command. Third, after the coder builds and tests run, it evaluates the result: reads the diff against the spec and decides whether the implementation meets the goal. If it doesn’t, it writes feedback explaining what needs to change.

The Coder is the agent that writes code. It receives the spec, the implementation context, the relevant files, the branch name, and the test command. If this isn’t the first attempt, it also receives the supervisor’s feedback from the previous round. It implements, runs tests, commits when they pass.

The loop is straightforward. The coder builds. Tests run. The supervisor evaluates the diff against the spec: done, or not done with feedback. If not done, the feedback goes back to the coder for another attempt. This repeats up to a configurable retry limit (three by default). If the retries run out, the orchestrator marks the issue BLOCKED, attaches the last feedback as a comment, and prints recovery hints so a human can pick up where the loop stopped.

Lessons Learned

The spec quality effect surprised me most. When I was the reviewer, a vague spec was something I could compensate for in the moment. I’d notice the gap, tell the agent what I meant, move on. When the supervisor evaluates a vague spec, it either passes it (bad) or sends vague feedback (also bad). The loop surfaces spec quality problems that my human flexibility was masking.

Stories with precise specs converge in one or two attempts. Stories with weak specs burn through all three retries and land in BLOCKED. The loop is a forcing function for better specs. That wasn’t the goal, but it might be the most valuable outcome.

The escalation path, marking issues BLOCKED with the full feedback trail, turned out to be more useful than I expected. The blocked issues are a record of where the process breaks down. Sometimes it’s a genuinely ambiguous spec. Sometimes it’s a case the coder can’t figure out on its own. Every blocked issue points to a gap I can fill: a missing pattern to document, an edge case to specify, a decision to make explicit. The failures are the curriculum for improving the process.

What it looks like in practice

xpo drive picks up a story, specs it, builds it, reviews it, and either merges or escalates. The output feeds into the same event log, the same timeline, the same agent identity system. When I open the board in the morning, I see which stories completed overnight, which ones got blocked, and the feedback trail for each.

Huntley’s Ralph loop showed that you can let agents iterate until the work is done. Karpathy showed that the iteration needs structure and supervision. Cherny showed that the loop itself is what you design. What I added is the process inside the loop: a supervisor that knows the spec-build-review workflow, a coder that stays in its lane, and an orchestrator that handles the lifecycle so neither agent has to. It’s not fancy. Two agents, a retry counter, and a Go function that manages the plumbing. But it runs while I sleep, and the stories it completes are the same quality as the ones I drive manually. That’s the whole point.

Where it goes from here

The current loop is working well in practice, but we’re not stopping here. A few ideas on taking it to the next level.

Convergence detection. Right now the loop is a fixed retry counter. Three attempts, then BLOCKED. But not all failures are equal. Sometimes the coder and supervisor are genuinely converging: each round fixes real issues and the feedback gets more specific. Other times they’re going in circles, the same feedback appearing in consecutive rounds with no real progress. Tracking whether feedback is converging or diverging would let the loop make smarter decisions about when to keep going and when to stop, instead of treating every failure the same way.

Knowledge corpus integration. The supervisor currently examines the repository generically when gathering context. It doesn’t know about the .aise/ directory structure, the ADRs, the accumulated patterns and decisions from previous stories. Wiring the supervisor into the knowledge corpus directly would give it the same accumulated context that makes manual sessions faster over time. The compounding effect I described in earlier posts should apply to the loop too, but right now it doesn’t.

Feedback classification. The supervisor’s evaluation is binary: done or not done. When it’s not done, the feedback is a single free-text string. In manual reviews I naturally distinguish between things that are blocking (the spec says handle empty input and you didn’t) and things that are observations (this could be cleaner but it works). Teaching the supervisor to make that distinction would let the loop focus on what actually matters and avoid burning retries on style preferences.

Splitting the supervisor’s hats. The supervisor currently handles spec evaluation, context gathering, and implementation review. That’s a lot of responsibility for one prompt. As the loop takes on more complex stories, separating those into specialized sub-agents with focused instructions might produce better judgments. The trade-off is token overhead and context passing. I started with one agent because it was simpler and I wanted to see where the real bottlenecks were. Now I’m starting to see them.