A Framework for Continuous Refactoring With AI Agents
Deliberate refactoring as an enabler for autonomous refactoring.
Why Continuous Refactoring matters more with AI
AI agents struggle with writing good software in bad codebases. Continuous refactoring is the practice that structurally addresses this challenge. The discipline is not new. Kent Beck and Martin Fowler championed it as an ongoing practice in the late 1990s. What changes with AI is the value of consistency and the cost of maintaining it.
The value of consistency increases. A codebase is the largest and most persistent context an AI agent reads. Consistent patterns produce consistent output; inconsistent patterns amplify into low-quality output. Drift in an AI-driven codebase accumulates faster than under human-only construction. More code is written, while supervision decreases.
The cost of maintenance decreases. Refactoring used to require sustained human attention, which made it expensive enough to defer. Most of it is pattern recognition: drift from a template, repeated structures, deviations from convention. Agents do this kind of work well, and they do it continuously and cheaply. The historical excuse for letting drift accumulate is gone.
Together, the two shifts raise the value and the feasibility of continuous refactoring at the same time. This optional discipline is now ready to become the operational baseline.
What is Continuous Refactoring?
Much of an agent’s effectiveness depends on harness engineering (Böckeler, 2026): the controls around the model that keep its output reliable. Harness engineering operates at the depth of a single codebase; continuous refactoring follows the structural consistency thread of the harness across many repositories over time. It zooms in on the part that brings the codebase to a standard and keeps it there as agents reshape the code; split into two distinct workstreams:
Deliberate refactoring is human-led structural work that makes the codebase AI-friendly. It produces the conditions autonomous refactoring needs to operate cheaply, captured in the prerequisites below. This spans two jobs: refactoring the existing landscape to meet the standards, and codifying them as templates so new work starts compliant.
Autonomous refactoring is agent-led ongoing work that targets structural drift: the repository deviating from the standards, caught statically. It runs as two practices, divided by whether the standard is already codified. Systematic refactoring enforces the standards the template already captures. Opportunistic refactoring uses the agent’s judgment to catch deviations the template has not captured yet. Two further elements close the loop around them. Reflection promotes a recurring finding from either practice into a codified standard. Template fan-out then propagates that standard across every repository, where systematic refactoring enforces it.
In harness terms the above are guides (templates and skills) and sensors (the two refactoring practices), and both run inside the agent loop to get things right the first time, not only to catch drift after.
A second kind of deviation, quality drift, is the running system missing its declared targets at runtime: performance, reliability, availability. We intend to fold it into the framework, but for now it stays out of scope.
Prerequisites: build the AI-friendly codebase first
Autonomous refactoring is only economical on a codebase that has been made AI-friendly. Otherwise the agent surfaces more drift than the team can remediate; autonomous refactoring degrades into manual effort with extra steps. Not every codebase is equally amenable to this control, something which Böckeler calls harnessability.
At the core, deliberate refactoring revolves around defining standards and forcing your codebase into the standardized shape. The more drift between the standard and reality, the more active role is required in the refactoring effort. This is organized into three layers:
- Code: what you write. A standardized solution structure with clear separation of concerns, plus documented coding standards.
- Stack: what you build on and can transfer. A simple, consolidated tech stack, plus shared concerns centralized in versioned packages.
- Operations: how you provision and run the code. Infrastructure as code, plus build and deployment through CI/CD pipelines.
In order to make the leap into agentic engineering, the refactoring effort also needs to encompass:
Specification. Contracts reverse-engineered at every boundary, with tests that enforce them, and the existing business logic documented. This is what lets an agent change structure without changing behavior.
Architecture. Decomposition into small, well-bounded services, each sized in a way that its full context fits in an agent’s working window.
The soft prerequisites are organizational. Refactoring is ongoing work that doesn’t immediately translate to feature delivery. The organization must be ready to embrace continuous refactoring as part of the organizational culture. Most organizations adopting AI agents do not have these prerequisites established yet. Going straight to autonomous refactoring without the deliberate work is the dominant failure mode and the most expensive one.
Example: out-of-process tests. One of the key prerequisites for agentic engineering is the ability to deploy freely. To keep control over autonomously generated code, out-of-process tests become more important than ever. These tests need more provisioning, a deployed system, and governed access according to company standards. Due to their increased value they are a perfect candidate for deliberate refactoring. Every codebase would benefit from such a test hardening. This is typically not the prettiest part of your repository. There is much boilerplate code needed to execute the tests. We could decide to let the agent vibecode these tests easily. However, there are many different ways to implement it, and due to the required access it is critical that we exert a strong measure of control to ensure security standards remain met. This makes it a perfect use case to standardize.
How to codify standards into a template
A template consists of four parts: the skill, sample, package, migration. These are packaged as a vertical slice that spans the Code, Stack, and Operations layers. It is the single source each repository draws its standards from, and the unit that template fan-out propagates.
Prefer packages over samples. Prefer samples over skills. The reason is determinism. A package can be deterministically implemented. A sample is a fixed artifact that can be copied over and adjusted where needed. A skill leaves most room for interpretation. Everything mechanical must be templated, so the skill is left holding nothing but the judgment.
The migration is how a version change reaches the consumers that already adopted the previous one. It follows the same determinism order as the parts it updates. A package change is mechanical, so its migration is a codemod script. The sample and the skill are judgment-based, so there the migration is an interpreted note: a versioned description of what changed and how to adapt, which the agent reads to perform the merge.
template-repository/
├── AGENTS.md
├── lib/
│ ├── pipelines/
│ └── src/
├── migrations/
├── plugin.json
└── skill/
├── sample/
│ ├── infra/
│ ├── pipelines/
│ └── src/
└── SKILL.md
How to implement autonomous refactoring
Autonomous refactoring becomes feasible when the repository resembles the defined templates. Drift is small enough that refactors can run on auto-pilot, with limited supervision. It runs as two practices, divided by whether the standard is codified, backed up by the mechanism that propagates new standards across the codebase.
Systematic refactoring enforces the standards the template already captures. Its reference is fixed and explicit: the templates and skills. If the template says shared concerns must come from a specific versioned package within a declared range, the check fails when a repository diverges. Practical examples: project structure conforms to the template, required IaC and pipeline files are present and valid, E2E tests follow the established pattern. During refinement and implementation this is applied to increase the first-time-right score. As quality gates, review agents fix or block pull requests when drift is detected. As continuous scanning, they surface drift between template and source code on a recurring schedule.
Opportunistic refactoring catches structural drift the template has not captured yet, where the agent’s judgment substitutes for an experienced engineer’s instinct: naming inconsistencies, duplicated structures that could be consolidated, static security or performance anti-patterns. It is opportunistic in the original sense (boyscout principle): the agent refactors what it notices in the code, beyond the codified rules. These uncodified findings, when they recur across repositories, are also the candidates for promotion into the template. This is the easiest of the three to adopt, and the only one that already has plug-and-play products: judgment-based reviewers such as GitHub Copilot and Cursor Bugbot already flag exactly this class of finding.
Reflection is the least mature part of this loop. Today the engineer owns it: spotting that the same finding repeats across repositories, then judging whether it earns a place in the template. Automating the signal, empowering the engineer to make the judgment call, is the next problem to take on.
Setting up Template fan-out
Template fan-out is the mechanism that scales the refactoring practices across the codebase. Triggered by a new template version release rather than by repository drift, it propagates a codified standard to every consuming repository. This is a two-layered setup derived from established Continuous Delivery practices:
- Pin propagation: Each consumer commits a
plugin-lock.json(referenced inAGENTS.md) that records, per consumed plugin, the exact resolved version of the payload it was generated from. When a new version ships, fan-out scans theplugin-lock.jsonacross every repository and flags the ones whose locked version trails the release.
{
"nanoservice-template": "1.2.0"
}
- Agentic merge. Each flagged repository gets a cloud agent, which fits the new version into whatever the repository has changed locally and opens a pull request, bumping the lock as part of that change. The scan and the trigger are deterministic; the reconciliation is the agent’s judgment, and we take that non-determinism as the acknowledged gap. An agent picks up the interpretable part of the template change and decides how to implement it based on the semantic versioning. This will apply for changes in the skill, and likely also for part of the changes in the sample. Where possible it applies the codemod to handle package version changes. A successful update rewrites the lock to the new version and hash, which both records the bump and resets for the next comparison.
The whole is wrapped in a Continuous Delivery harness: Rings, Canary, Roll-back. The harness gives us trust to run the agent autonomously or under supervision within the guardrails we have set. Rollout moves in rings, relevance-selected canaries first and then widening waves. Each wave is gated on a real post-deploy signal rather than a successful deploy. A failed canary halts the wave, reverts, and potentially even feeds the fix back into the template. The same loop that carries a promoted finding outward, now runs in reverse.
Client-side Plugin versioning. The plugin ecosystem lacks a consumer lockfile. It is needed to structurally provide control over the non-deterministic template fan-out. The plugin-lock.json is the cruft/copier .cruft.json/.copier-answers.yml pattern, brought to the agent-plugin ecosystem. In its current setup the lock is a convention you build and police yourself. There is no compiler or static check that confirms the agent merged it correctly; the out-of-process tests and the canary are the only proof. Fan-out is exactly as safe as that test coverage.
Continuous refactoring in relation to nanoservices architecture
Nanoservices architecture and continuous refactoring are two halves of the same lifecycle. Where nanoservices is the construction practice, continuous refactoring is the maintenance practice.
Deliberate refactoring produces three artifacts: a specification, an architecture, and a template (the Code, Stack, and Operations layers consolidated). These are exactly what autonomous refactoring consumes, and they are the same three an engineer produces when designing nanoservices. The Code, Stack, and Operations layers are the nanoservice template itself. The relationship is not shared prerequisites; it is the same work approached from the maintenance side.
This makes deliberate refactoring the path to the nanoservice template. It is how you arrive at a place where nanoservices are operationally feasible. Autonomous refactoring is the maintenance regime that keeps the nanoservices alive. Without it, hundreds of nanoservices accumulate drift over many iterations.
Any codebase benefits from deliberate work toward AI-friendliness, and any sufficiently consistent codebase benefits from autonomous maintenance. With nanoservices this discipline stops being optional.
Conclusion
Continuous refactoring has been around for decades. However, with agentic engineering it stops being cleanup and becomes the operating discipline. It splits into two workstreams that must run separately. Deliberate refactoring is a prerequisite for enabling the use of AI agents. Autonomous refactoring prevents drift once these prerequisites have been met.
Its two practices feed a loop. Opportunistic refactoring surfaces an uncodified finding that recurs across repositories; systematic refactoring exposes the codified rules that no longer hold. Reflection promotes those signals into the template, and fan-out propagates the new version into every repository’s systematic checks. The set of codified standards grows over time as best practices stabilize.
Opus 4.8 was used to support analysis and formulation. The framework, ideas, and editorial decisions are my own.