The hard problem is not generating code. The hard problem is ensuring that multiple autonomous agents acting in parallel reduce system error instead of amplifying it.
Author: James Phoenix | Date: February 2026
Summary
A swarm of agents producing code changes behaves like a stochastic optimizer. Each agent proposes updates that noisily estimate where loss can be reduced. Whether the swarm converges (system improves) or diverges (entropy wins) depends on five conditions: a single scalar loss function, an explicit accept/reject gate, regression memory, bounded autonomy, and decaying step size. Without all five, swarms amplify chaos no matter how “smart” the individual agents are.
What Convergence Actually Means
Convergence is not “the code compiles.” It is not “tests pass.” It is not “the agent finished.”
Convergence means three things hold simultaneously:
1. Expected loss decreases: E[L(t+1)] < E[L(t)]
2. Variance of loss decreases: Var(L(t+1)) < Var(L(t))
3. Regression rate approaches zero: d(L_reg)/dt → 0
Condition 1 means the system is getting better on average.
Condition 2 means the improvements are becoming more consistent, less noisy.
Condition 3 means old fixes stay fixed.
If loss oscillates or grows, the swarm is diverging even if output volume is high. Volume without convergence is entropy production.
Why Naive Swarms Diverge
Most agent systems fail because they violate at least one of these constraints.
No Shared Objective Function
If agents are optimizing different implicit goals:
Agent 1: "fix lint"
Agent 2: "improve style"
Agent 3: "add features"
Agent 4: "refactor architecture"
Then the system is doing vector optimization with no dominance ordering. Agent 1 reformats code that Agent 4 just restructured. Agent 3 adds features that break Agent 2’s style fixes.
Result: oscillation. Each cycle undoes part of the previous one.
No Bounded Action Space
If agents can:
- introduce new abstractions
- change architecture
- modify specs
- add dependencies
without constraint, the search space expands faster than it can be evaluated.
Loss increases purely from surface area growth. More code means more possible bugs, more possible interactions, more possible regressions.
No Memory of Prior Gradients
If agents do not know:
- what was already tried
- what failed
- what caused regressions
Then the system performs random walks around local minima. An agent “fixes” something that was already fixed and reverted. Another agent retries an approach that was proven to cause regressions.
This produces the illusion of progress without convergence.
No Regression Penalty
If regressions are not explicitly penalized, the system learns that:
- breaking things is cheap
- reintroducing errors is allowed
- only forward progress is measured
This destroys convergence even if short-term loss decreases, because fixes are impermanent.
Agents as Stochastic Gradient Estimators
Think of each agent as producing a proposed update delta_i to the system state.
The swarm produces a set of updates:
Delta = {delta_1, delta_2, ..., delta_n}
Each update has an effect on loss:
delta_L_i = L_total(after delta_i) - L_total(before)
The key observation:
Agents do not need to be correct. They need to be biased toward negative delta_L.
This mirrors stochastic gradient descent:
- Each agent samples a noisy estimate of the loss gradient
- The orchestrator aggregates these samples
- Only updates that reduce loss are applied
Individual agents can be wrong as long as the aggregate signal is right. This is why parallelism works. This is why running the same perspective 4 times catches what a single run misses.
The 5 Convergence Conditions
A swarm converges if all five hold.
Condition 1: Single Scalar Loss Function
All agents must optimize the same scalar objective:
L_total = SUM of weighted loss terms
No agent optimizes “style” unless style violations contribute to L_total. No hidden goals. No implicit optimization targets.
Why this matters: Multiple objectives without a dominance ordering create Pareto fronts, not solutions. Agents will trade off between objectives forever, oscillating without converging.
Implementation: Define L_total explicitly. Make it visible to all agents via the CLAUDE.md or task specification.
Condition 2: Explicit Accept/Reject Gate
Every proposed change must pass through a gate:
Apply delta_i if and only if:
L_total(after delta_i) <= L_total(before)
Optionally allow small temporary increases if compensated elsewhere, but this must be explicit, time-bounded, and tracked.
Why this matters: Without a gate, every change is applied. Bad changes accumulate. The system drifts without any selective pressure.
Implementation: Quality gates serve as the accept/reject mechanism. If type checking, linting, and tests all pass, delta_L is likely negative. If any fail, reject the change.
Condition 3: Regression Memory
The system must remember:
- past issues and their resolutions
- past regressions and their causes
- which changes caused which failures
If an agent reintroduces a known regression, the penalty must be higher than the original fix benefit.
penalty(regression) > benefit(original_fix)
This enforces hysteresis: once something is fixed, it stays fixed. The system cannot oscillate back through known-bad states.
Implementation: Maintain a regression log. Include it in agent context. Use regression tests to make reintroduction mechanically impossible.
Condition 4: Bounded Autonomy
Agents are constrained by:
- specs (what to build)
- architectural rules (where things go)
- type systems (what is valid)
- lint invariants (what patterns are allowed)
These constraints reduce the dimensionality of the search space. Lower-dimensional optimization converges faster.
Unconstrained agent: searches in N dimensions
Constrained agent: searches in M dimensions (M << N)
Convergence speed: proportional to 1/dimensions
Why this matters: An unconstrained agent in a large codebase has millions of possible changes. Most are neutral or harmful. Constraints eliminate the harmful ones before the agent even considers them.
Implementation: Define constraints first. Use types, lint rules, and architectural boundaries to shrink the action space.
Condition 5: Decaying Step Size
Early on, agents can make large changes:
- introduce new modules
- restructure directories
- change API contracts
Over time:
- scope narrows
- changes become local
- refactors become incremental
- diffs get smaller
Early cycles: large diffs, architectural changes, new abstractions
Late cycles: small diffs, local fixes, test additions, documentation
This mirrors learning rate decay in ML. Without it, systems oscillate forever because agents keep making large changes that disrupt previous improvements.
Implementation: Use explicit phase switching. Growth phase allows large changes. Polish phase restricts to local, small changes only.
Why Specs Pin the Loss Surface
Specs act as fixed reference surfaces. They define what “correct” means independently of the current code state.
Without specs:
- the loss landscape shifts every cycle
- agents optimize against a moving target
- convergence is mathematically impossible
With specs: L is a function of (code vs spec) → fixed target
Without specs: L is a function of (code vs vibes) → moving target
This is why “vibe-based” agent coding fails at scale. You can get lucky on small projects. On large systems, without specs, the swarm will wander.
Specs do not need to be formal or exhaustive. They need to be:
- written down (not in someone’s head)
- specific enough to verify against
- stable across cycles (not rewritten every iteration)
Observable Signals
Converging Swarm
- Issue count decreases monotonically
- Regressions become rare
- Diff sizes shrink over time
- Architecture stabilizes (same modules, stable boundaries)
- Agents repeat themselves more (running out of things to fix)
- Loss curve shows smooth decay then plateau
Diverging Swarm
- Issue count plateaus or oscillates
- Same bugs reappear across cycles
- Diffs get larger each cycle
- New abstractions appear constantly
- Human intervention increases over time
- Agents keep touching the same files without resolution
- Loss curve shows sawtooth or monotonic rise
The Human Role
Humans are not replaced by this framework. Humans:
| Human Role | What It Means |
|---|---|
| Define the loss function | Decide what matters and how much |
| Define constraints | Set the boundaries of valid solutions |
| Adjust weights | Shift priorities as the project evolves |
| Detect Goodharting | Notice when metrics improve but the system doesn’t |
| Design the energy landscape | Agents do gradient descent, you define the terrain |
The agents are the optimizer. You are the one who decides what gets optimized.
Key Insight
Agent swarms do not converge because they are “smart.” They converge because loss is explicit, constraints are hard, regressions are punished, memory is persistent, and autonomy is bounded. Without these, swarms amplify entropy. With them, they behave like a noisy but powerful optimizer.
Related
- Synthetic Loss Functions – The formal loss function this theory optimizes
- Agent Swarm Patterns – Practical swarm patterns (this article explains why they work)
- Quality Gates as Information Filters – Gates as the accept/reject mechanism
- Constraint-First Development – Constraints that reduce the search space
- Goodharting Prevention – When convergence signals are misleading
- Growth vs Polish Phases – Implementing decaying step size via phase switching
- Test-Based Regression Patching – Building regression memory into the codebase
- Learning Loops – How the system learns from failures

