Loop Engineering, Not Loop Running: What Agent Loops Can Learn from Parcae

Loop Engineering, Not Loop Running: What Agent Loops Can Learn from Parcae

Leader ●3 ●19 ●81
calendar_today ago β€’ schedule13 min read
β€” Originally published at flamehaven.space

Translating Parcae's Stability Questions into an Agent-Level Control Loop

πŸ’‘TL;DR β€” Across three fresh seeds on the same 42-fact development benchmark, an offline-informed two-sample fallback cap moved four or five facts per seed from fail to pass under our deterministic contract verifier, with zero pass-to-fail regressions on any of the three, clearing a gate we'd committed to before we ran it.

On the two seeds with direct uncapped comparisons, sampling fell 13–21% and regressions fell from one to zero, while raw repairs also fell by two on each β€” we don't yet know whether that repair loss is caused by the smaller cap or by benchmark variance this exact set of facts has already burned us on once before.

More importantly: fitting the stopping law exposed a survivor-conditioning bug in our own evaluator before release, one that had been quietly lying to us for a while.


1. Story

1

I read the Parcae paper on a night I probably should have been doing something else, and by the second pass through the stability section I had that specific, slightly dangerous feeling of this is the missing piece β€” a feeling I've learned to be suspicious of and ignored anyway. I went looking for whatever already existed. I checked repo after repo. None of them were it, and why they weren't takes most of the next section to explain.

The paper isn't actually where this started, and I want to be honest about that rather than let it read cleaner than it was. We'd already been circling loop discipline from a different angle β€” ai-slop-detector runs a bounded, mechanical self-calibration loop over static code review, deliberately not an inference loop, because at the time we didn't trust one to hold still.

Its own published limit says as much: it doesn't catch runtime bugs, a clean structural score is not proof anything actually works. That limitation sat there, honest and slightly uncomfortable, shaped exactly like the question Parcae later gave us sharper language for β€” what state carries forward, what counts as instability, when does another recurrence stop paying for itself.

Before anyone connected any of this to a paper about residual streams, our own refinement loop already had defects we'd caught and written down. We'd documented four:

  • the orchestrator instantiated a refinement object it never called, sitting dormant with nothing downstream depending on it
  • the loop that did run called the proposer fresh every iteration and never fed the previous best answer back in, so it wasn't refining, it was re-rolling
  • the evolution layer meant to learn per-domain model weights was fed hardcoded placeholder scores, learning to fit constants instead of measurements
  • and halting was a free-form string with no enforced vocabulary, meaning in practice it meant whatever the last person to touch that code felt like.

Parcae didn't hand us a fix for any of this. It handed us sharper questions to point at a mess we already knew we had.

Here's the actual stakes, and I want to be careful how I say it. Parcae's own introduction motivates layer-looping partly as a way to buy quality without buying more parameters, citing edge deployment and memory-constrained inference as part of why that matters β€” which is convenient, because that's also our stakes.

The control logic below is now sitting inside an on-device inference stack, ported over, not yet proven there. Everything measured in this piece was measured server-side, and it's what justified spending the effort to make that port at all β€” it is not evidence any of it survives on-device latency, memory pressure, or a battery actually draining while the loop thinks. That test is running separately, right now.


2. Why Loop Running Is Not Loop Engineering

2

2.1 β€” Same Recurrence, Different State Space

3

Parcae is about recurrent-depth transformers β€” the same block of layers, passed through repeatedly, inside training.

It has nothing to do with calling an API endpoint ten times and hoping the tenth call knows something the first didn't. Every comparison from here forward, including ours, is a structural translation to a different layer of the stack, not a claim the paper itself makes.

The generic agent loop, stripped down, is:

while not done:

 response = LLM(prompt + previous_results)

 execute_tools(response)

 done = evaluator(response)

That's a repeated-execution device, not yet a stable looping system.

Vercel Labs' ralph-loop-agent documents itself, honestly, as an outer orchestration loop around generateText; its built-in safety limits are iteration count, token budget, and cost, and the semantics of "done" are delegated entirely to a user-supplied verifyCompletion function.

That's a clean abstraction. It just doesn't, on its own, supply a convergence model.


2.2 β€” Repetition Is Not Convergence

3

Repetition does exactly one of three things: real improvement, re-expression of the same error, or amplification of it, and you don't get to pick which just because you asked for more of it.

The same model, same context, same evaluator producing the second answer means that answer is conditioned on the first one's mistake, not independent of it β€” a wrong assumption produces a wrong implementation, tests get written against that wrong implementation, the tests pass, the loop reports done. It converged. Just to the wrong fixed point, and nothing in the architecture noticed the difference.

Parcae observes something that rhymes with this at a completely different layer β€” without adequate depth sampling, late recurrences make large residual jumps and never settle into a stable fixed point, producing loss spikes.

I don't want to overstate the connection: Parcae's is a vector-state training dynamic, an agent stuck on a wrong-but-verifier-satisfying answer is an evaluation-design problem. What's shared is only the underlying question, whether recurrence reduces a measured error or just moves it around.

Most agent loops also lack authoritative state. They operate on transcripts, lossy summaries, and task artifacts that can silently disagree β€” the conversation says done, the file was never touched. A scheduler-theoretic position paper describes the resulting failure modes as implicit dependencies nobody wrote down, unbounded recovery loops, and a next-action policy hidden entirely inside opaque inference.

And termination limits keep getting confused with convergence conditions. Ten calls, max. A hundred thousand tokens. Five dollars. A string match on "DONE." Every one of these is a resource cutoff, not a convergence condition, which needs something like an observable progress potential β€” call it V, over remaining defects and verification failures β€” where the ideal direction is V(s_{t+1}) < V(s_t), though in a system this non-deterministic that inequality is something you approximate through measurement rather than assume. An iteration that neither improves the retained best state nor produces new admissible evidence should count against a bounded stagnation budget, not silently trigger another identical call.


2.3 β€” "Done" Needs Evidence, and Calling Three Agents Isn't Multi-Party Verification

4

omplete: result.text.includes("DONE") is the first example in Ralph's own docs. PageAI-Pro/ralph-loop does considerably more around this β€” tests, lint, type checking, Docker sandboxing β€” genuinely more rigorous.

But the terminal signal is still a promise tag the agent writes into its own output. Proof-or-Stop names this precisely, backed by a 9,240-cell ablation reporting ten of ten scenarios with zero false-DONE β€” worth being precise that their "proof" is operational, not semantic correctness, evidence admissible under an explicit trust model.

What still holds at a smaller scale: the agent says the tests passed is a sentence; a runner executed the suite against a known commit and produced a signed receipt can change what state the loop is in, and only one of those should.

Naming one model the coder and another the reviewer doesn't manufacture independence between them if they're close enough in family that their failure modes correlate.

A survey of fifty real loop implementations draws the line between a plain loop and a genuine external loop specification β€” trigger, goal, verification, stopping rule, memory β€” and names model-as-judge fragility and reward hacking as the risks that actually bite.

Calling three agents instead of one is multi-agent invocation, not automatically multi-party verification. This is why the better-built repos in this category, PageAI-Pro/ralph-loop included, still land, correctly, as a good harness rather than a generalized loop stability engine: none establish state-transition soundness, verifier independence, or regression-free monotonicity. "It works" and "it's stable" are different sentences.


3. What We Built

Parcae recasts a looped transformer as a non-linear time-variant dynamical system over the residual stream: h_{t+1} = Δ€ h_t + BΜ„ e + RΜ„(h_t, e).

Drop the non-linear term RΜ„ and what's left is a linear time-invariant surrogate β€” Δ€, BΜ„ fixed across every step β€” whose stability is decided entirely by the spectral radius ρ(Δ€). Parcae forces ρ(Δ€) < 1 by a negative-diagonal parameterization, by construction, and separately fits a saturating test-time law, L(T) = L∞ + ZΒ·e^(-zT).

None of that applies literally to an agent β€” ρ(Δ€) is defined over a single vector-valued hidden state, and agent state is code, memory, tool output, environment, policy, evidence, non-stationary in ways a residual stream isn't. What carries over is the discipline: define the stability condition, the state transition, the convergence property, the saturation limit, before trusting a system to repeat itself.


3.1 β€” What the Control Layer ContainsThe progress-preservation row deserves the actual code, because the docstring used to overstate it:

7

The progress-preservation row deserves the actual code, because the docstring used to overstate it:

if not 0.0 <= carry_lambda < 1.0:
    raise ValueError(f"carry_lambda must be in 0, 1) for bounded EMA carry, got {carry_lambda}")

That guarantees the scalar ema_ds summary can't amplify its own prior value β€” nothing stronger. It used to say "contractive carry," which was more than the constructor actually proves; I went back and fixed it. k consecutive worsening steps still trip FORGE_DIVERGED, with the best-so-far proposal preserved rather than discarded.

The saturation row is worth being careful about, because it's easy to blur two different things:

@property

def usable(self) -> bool:
    # If global fit error is at least as large as the model's maximum
    # possible gain, the fitted curve has no practically resolvable
    # improvement signal at this scale.
    return self.fit_error < abs(self.amplitude)

Offline, we ran this against stored trajectories to derive a fixed configuration change β€” that's 3.2 below. At runtime, refine() can also accept a fitted decay curve and stop sampling a live trajectory early, or route a saturated domain to a different model β€” both built, both unit-tested, neither active in the confirmatory run below. What that run tested is a static, offline-informed cap, not live adaptive stopping.


3.2 β€” What the Experiment Actually Showed

9

Re-running the stored, uncapped three-seed benchmark passes through the new saturation-fit machinery, offline, surfaced a real bug β€” worth its own section (3.3), because it's the actual finding of this piece. The resulting fit β€” floor at 2.94, negative amplitude, negative predicted gains β€” still passed the usable check above. A fit can clear its own resolvability gate and be structurally wrong at the same time.

Fixing the collector brought the fitted floor to 0.481, closely tracking the observed unresolved-at-horizon share of 59/126 = 0.468 β€” forty-two facts, three seeds, unresolved meaning it didn't converge inside the tested sample budget, not that it never will.

That same offline pass showed every observed full-context-fallback repair, across all three stored seeds, resolving within the fallback's first two samples. That's what informed capping the fallback at two samples instead of five β€” a static configuration change, decided once, offline.

We pre-registered a confirmatory gate for that capped configuration β€” committed before running anything β€” and reran it on three fresh seeds, live, against a real model. "Repaired" means a fact that failed the pre-loop contract check and passed after; "regressed" means the reverse.

6

All three capped seeds cleared the pre-registered bar on its own terms β€” that gate never required beating the uncapped run, and it passed cleanly.

The paired comparison against uncapped, on the two seeds run under both, is messier. Samples dropped 21.1% and 12.8%. Regressions dropped from one to zero on both. But raw repair count also dropped, from six to four on seed 17 and from seven to five on seed 27, so net repair fell by one on each paired seed β€” +5 β†’ +4, +6 β†’ +5 β€” rather than improving.

With only four to seven repair events per run, a swing this size sits inside the same self-consistency variance this benchmark has already burned us on once before, in an earlier round where the whole premise of "does this loop help at all" briefly fell apart because reruns weren't reproducing each other.

I don't know, right now, whether the smaller cap cost one real repair per seed or whether it's noise. I could write a sentence that resolves that cleanly and I'm choosing not to.


3.3 β€” Where the Parcae Analogy Breaks, and What the Break Taught Us

12

Two problems showed up here that Parcae has no reason to ever run into. Both trace back to the same mistake β€” assuming things true inside a recurrent transformer are automatically true one layer up.

An LTI system can take a time-varying input without ceasing to be LTI β€” the mere fact that input changes over time doesn't by itself break anything, and I want to be precise here since I got this wrong in an earlier pass at this piece.

What actually happens in our loop is more specific than that: a short-view-to-full-view switch also moves what the verifier checks against and how much sampling budget remains, not just which text gets read. It's an intervention between two operating regimes, not one more recurrence continuing under an unchanged process β€” closer to a regime-switching process, two different operating dynamics wearing the same variable name.

Our first implementation fit one cumulative decay curve across both phases anyway, and once the regime changes, the assumption that every sample belongs to one stationary gain process stops being justified. We rewired the collection to fit curves per domain:view instead.

The second problem embarrasses me more, because it's obvious in hindsight and genuinely wasn't while I was staring at plausible-looking numbers. Parcae fits its saturation law to loss measured at every recurrence depth β€” the value exists at every T. Our outcome doesn't work that way: consensus is absorbing. Once a fact resolves, its unresolved indicator is known, with certainty, to be zero at every later iteration β€” not missing information, information we had and failed to use.

The first collector dropped resolved trajectories out of later averages instead of carrying that known zero forward, which isn't classical right-censoring β€” that description applies to runs that hit the sample budget without ever resolving, where the future is genuinely unknown.

Dropping already-resolved runs is a narrower mistake, closer to survivor conditioning. It quietly swapped the quantity being estimated: we wanted the population-level unresolved curve, U(t) = P(unresolved at iteration t), every trajectory counted at every t β€” instead, by dropping the resolved ones, the average increasingly conditioned itself on the shrinking pool of stubborn survivors, a different and more pessimistic quantity.

Neither was a failure on Parcae's part. Its recurrent block doesn't switch retrieval regimes mid-pass, and its loss observations don't disappear on an absorbing success. Both failures were entirely in our translation layer. That, more than any number above, is the actual result here.

Importing the functional form was a couple of afternoons. Finding which background assumptions quietly stopped holding, and rebuilding the collection and fitting boundaries around that instead of the equation as written, was the work.


4. Limitations and Roadmap

`4

The 42 facts underneath everything above got iterated against for weeks before these fresh-seed runs, so this is seed-held-out evidence, not task-held-out β€” the next real gate is new facts, not new seeds on the same forty-two.

The live run tested a static cap, not the adaptive saturation control described above; the runtime decay-fit stopping and cross-domain escalation both exist in code with unit tests and neither has been switched on live yet. The carry/divergence mechanism is proven against synthetic fixtures, not a live multi-arm ablation that could isolate which piece is earning which part of the result.

The paired repair-count drop is still unresolved. The saturation gate rejects fits whose maximum modeled gain is no larger than their global fit error; it does not yet compare against a null baseline or report parameter uncertainty. And everything measured sits inside one fact-repair benchmark, one small model family β€” whether any of it holds on-device is the test running right now, separately.


Conclusion

15
I don't think we solved agent-loop stability, and I'd rather say that directly than let the numbers above imply it by accident. What actually exists is a bounded carry and divergence controller checked so far only against synthetic failure; a saturation-fit machinery that, used offline, informed a smaller, cheaper sampling configuration for the repair loop later ported into an on-device stack, and that, used live, hasn't been turned on; and an escalation path that's never run outside a test fixture.

Building and dogfooding that machinery surfaced a real measurement defect in our own evaluator before it shipped, turned several previously diagnosed defects into explicit named controls, and β€” on the one configuration change the offline analysis actually informed β€” cut sampling cost on both seeds with direct paired comparisons and drove regressions to zero across all three capped seeds, at the cost of fewer raw repairs on the two paired seeds, a cost I'm reporting rather than rounding down because it's inconvenient.

That's the shape of loop engineering instead of loop running: not a system claiming to be stable, but one built to make it possible to find out precisely where it isn't β€” and one instance of it finding exactly that, inside its own evaluator, before anyone downstream had to. What Parcae is worth here was never a proof that transfers across two different kinds of system. It's a discipline that transfers, if you redo the work instead of copying the equation.

Whether this set of controls survives task-held-out facts, another model family, live adaptive stopping actually switched on, and a real on-device runtime isn't settled by anything above. That's the next gate, and I genuinely don't know yet what it says.


References

  1. Prairie, H., Novack, Z., Berg-Kirkpatrick, T., & Fu, D. Y. (2026). Parcae: Scaling Laws For Stable Looped Language Models. arXiv:2604.12946. https://arxiv.org/abs/2604.12946
  2. Huang, J., Hsia, J., Sun, J., Shi, F., Huang, W., & White, I. H. (2026). Proof-or-Stop. arXiv:2607.14890. https://arxiv.org/abs/2607.14890
  3. Wei, H. (2026). From Agent Loops to Structured Graphs. arXiv:2604.11378. https://arxiv.org/abs/2604.11378
  4. Macedo, S. (2026). Stop Hand-Holding Your Coding Agent. arXiv:2607.00038. https://arxiv.org/abs/2607.00038
  5. Vercel Labs. ralph-loop-agent. https://github.com/vercel-labs/ralph-loop-agent
  6. PageAI-Pro. ralph-loop. https://github.com/PageAI-Pro/ralph-loop
  7. Flamehaven. (2026). AI-SLOP Detector v3.5.0 and the Self-Calibration Loop. https://flamehaven.space/writing/it-gets-smarter-every-scan-ai-slop-detector-v350-and-the-self-calibration-loop/
  8. Flamehaven-LEDA repository. https://github.com/flamehaven01/LEDA-Engine
Part 4 of 4 in Equation to Artifact
πŸ”₯ Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

The Sovereign Vault β€” A Comprehensive Guide to Protocol-Driven AI

Ken W. Algerverified - Jun 4

From Subjective Narratives to Objective Data: Re-engineering the Elderly Care Communication Loop

Huifer - Jan 28

Helping Clients Move from Pilot to Production: The Agentic AI Governance Playbook

Tom Smithverified - Jun 8

From Prompts to Goals: The Rise of Outcome-Driven Development

Tom Smithverified - Apr 11

The Re-Soloing Risk: Preserving Craft in a Multi-Agent World

Tom Smithverified - Apr 14
chevron_left
4.1k Points β€’ 103 Badges
South Korea β€’ flamehaven.space
57Posts
30Comments
27Connections
Founder designing Sovereign AGI & Scientific AI systems β€” governance, reasoning models, medical/phys... Show more

Related Jobs

View all jobs β†’

Commenters (This Week)

3 comments
2 comments
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!