If AI programs faster and faster, who takes care of quality? This article presents three autonomous feedback loops for correctness, performance and architecture and shows why human steering still matters.
Speed Alone Does Not Make Software Development Sustainable#
With agentic AI, we can now develop software at a speed that was hard to imagine a few years ago. AI agents implement features, write tests, fix bugs and create pull requests. More and more often, they can complete these tasks largely autonomously.
But speed alone does not make software development sustainable.
If we generate more and more code without keeping an eye on its long-term quality, a problem emerges: The software may work brilliantly today, but with every change it becomes harder to understand, extend and maintain.
The problem is not fundamentally new. Human developers under time pressure can accumulate technical debt as well. The difference lies in the speed at which AI can create such problems.
So the interesting question is:
Can we use agentic AI not only to develop new features, but also to continuously improve the existing software?
One interesting approach is autonomous feedback loops.
An agent observes certain quality attributes, identifies opportunities for improvement, changes the code and then checks whether its change actually brought an improvement.
Three particularly interesting examples are:
- Correctness: Systematically find and fix bugs.
- Performance: Measurably improve runtime behavior.
- Architecture: Reduce complexity and coupling to make future changes easier.
Correctness: Finding Bugs Before Users Do#
The first feedback loop tries to continuously improve the functional correctness of the software.
For that, an agent needs a way to detect bugs reliably.
One particularly interesting technique is Deterministic Simulation Testing (DST).
Deterministic Simulation Testing#
DST is used, among others, by FoundationDB and TigerBeetle. The technique is also used outside of databases: Dropbox tests its sync engine this way, MongoDB and the Ethereum network use the Antithesis platform, which was created by the FoundationDB founders.
The idea is to run the actual application code in a controlled environment in which normally unpredictable influences are simulated.
These include, for example:
- Network interruptions and delayed messages
- Crashes of individual components
- Different orderings of concurrent operations
- Errors when reading and writing data
- System time and random numbers
The decisive advantage: the simulated runs are reproducible.
If a particular combination of events triggers a bug, the same run can be executed again. An AI agent can analyze the bug, implement a fix and then check whether the bug has actually disappeared.
A very large number of different failure scenarios can be examined automatically this way.
Does Every Piece of Software Need DST?#
No. For an ordinary business application with a REST API, a database and a few background jobs, a full DST system can cause disproportionate effort.
The underlying idea is transferable, though:
The more reliably we can detect and reproduce bugs automatically, the better our test system serves as a foundation for autonomous improvements.
For business applications, the following techniques come into question, among others:
- Executable specifications, for example with Gherkin scenarios
- Integration and scenario tests
- Property-based testing
- Mutation testing to assess test effectiveness
- Static analysis and compiler checks
- Targeted simulation of failure conditions
Executable specifications are particularly important here.
After all, an agent must not only know that a test fails. It must also be able to recognize which behavior is actually expected.
The Limit: Tests Do Not Automatically Know the Requirements#
Even a perfect test system does not guarantee functionally correct software.
If a requirement is missing or has been specified incorrectly, the agent cannot reconstruct it from the test results alone.
A system can pass every test and still do exactly the wrong thing.
This is the difference between verification and validation: Verification checks whether the implementation matches its specification; validation checks whether the result actually achieves what was wanted (more on this in the article Agentic AI Is Like a Rocket).
So the validation question, what the software should do, remains separate from the verification question, whether the implementation meets these requirements.
The first feedback loop can take over verification increasingly autonomously. Validation still needs domain goals and their review.
Performance: Measurable Optimization Instead of Gut Feeling#
The second feedback loop deals with the speed and efficiency of the software.
A different approach suggests itself here: Instead of just detecting bugs, we can continuously measure performance indicators and try to improve them.
OpenTelemetry provides a technical foundation for this.
What Is OpenTelemetry?#
OpenTelemetry, often abbreviated as OTel, is an open framework for collecting and transmitting observability data from software systems.
This includes in particular:
- Metrics: Measurements such as response times, throughput, memory consumption and error rates
- Traces: The processing of a request across different components
- Logs: Recorded events and error messages
OpenTelemetry provides the instrumentation and transport of the data, not automatically the optimization itself.
An AI agent, however, can analyze this information to detect performance problems and propose targeted improvements.
Performance Hill Climbing#
An interesting approach is what is known as hill climbing.
An optimization algorithm tries to approach a better result step by step.
For an AI agent, this could look as follows:
- Measure current performance.
- Identify a possible bottleneck.
- Make a targeted code change.
- Measure performance again under comparable conditions.
- Adopt the change if it is actually better.
- Otherwise discard the change and try a different approach.
The result can be a step-by-step improvement.
Not every optimization leads to an improvement; a regression is discarded under a simple hill-climbing strategy.
An example from a typical business application:
A REST endpoint takes 800 milliseconds at the 95th percentile. OpenTelemetry traces show that a substantial part of that time comes from repeated database queries.
The agent identifies an N+1 query problem, optimizes the data access and then runs the functional tests and performance benchmarks again.
If the response time drops to 250 milliseconds without violating other quality goals, it can adopt the change.
Performance Has Several Dimensions#
An optimization is rarely as simple as “faster is better”, though.
For example, a caching layer can reduce response time but at the same time increase memory consumption and create new data consistency problems.
So this feedback loop also needs clear goals and limits.
One possible goal could be:
Minimize the P95 response time as long as memory consumption, error rate and data consistency stay within given limits.
Such goals are generally well suited to automation.
One prerequisite, however, is that the measurements are reliable and comparable. Otherwise, different load profiles or fluctuating environmental conditions can fake supposed improvements.
Architecture: Can AI Declutter Its Own Code?#
The third feedback loop is perhaps the most interesting, and at the same time the most difficult.
It is not primarily concerned with whether software works or is fast enough, but with how easily it can be changed in the future.
This is where the term deslop increasingly appears in discussions about AI-generated code.
What Does Deslop Mean?#
Slop is a derogatory term for low-quality AI-generated content, including unnecessarily complicated, redundant or poorly structured code.
Deslop accordingly refers to the attempt to remove such quality problems afterwards.
An AI agent could, for example:
- Merge duplicate implementations
- Remove unnecessary abstractions
- Reduce superfluous error handling
- Divide responsibilities between components more clearly
- Break cyclic dependencies
- Detect redundant tests
- Simplify hard-to-understand control flows
- Reduce coupling between modules
At first, this sounds like ordinary refactoring.
The difference is that such work no longer happens only as a by-product of concrete feature development, but regularly and deliberately as an improvement process in its own right.
The Problem: What Is a Good Architecture?#
While correctness and performance can be measured objectively, at least in part, assessing a software architecture is harder.
An architecture is not good merely because it has few classes or looks particularly elegant.
It is good if it serves its purpose.
One decisive purpose is to make future changes as simple, safe and inexpensive as possible.
This is exactly where an interesting new way of measuring emerges.
Token Consumption as a Maintainability Metric#
If AI agents take over a large part of our software development, we can measure their actual effort for changes.
For example:
| Metric | Hard-to-maintain code | Well-maintained code |
|---|---|---|
| Files read | 45 | 8 |
| Files changed | 17 | 3 |
| Tokens required | 180,000 | 35,000 |
| Agent iterations | 12 | 3 |
Illustrative numbers for comparable changes, not empirical results.
The basic reasoning is convincing:
If an agent has to examine 45 files and change 17 files for a small business change, that may indicate excessive coupling or unclear responsibilities.
If the same business change can be implemented with considerably less effort, that could be a sign of a better architecture.
Token consumption thus becomes a potential externally observable metric for maintainability.
High token consumption is not just a symptom here, but a problem in itself. The more context an agent has to take in, the more likely details get lost in it; LLMs work measurably less reliably in very large contexts. More tokens therefore mean:
- lower quality of results, because details get buried in the context
- higher costs under usage-based API pricing
- slower processing and longer feedback cycles
- more context compactions, in which earlier findings are lost
- a hard limit: if a change no longer fits into the context window, the agent has to split it or fails
Hard-to-maintain code thus makes exactly the work that is supposed to improve it more expensive and worse.
But Does Token Consumption Really Measure Architecture Quality?#
Not directly.
Token consumption also depends on other factors:
- Capability and behavior of the model used
- Size and preparation of the provided context
- Efficiency of the development tools used
- Difficulty of the task at hand
- Quality of the documentation
- Number of correction attempts required
An agent that checks less thoroughly may need fewer tokens and still produce worse code.
So raw token consumption would be dangerous as an optimization target.
More interesting would be the effort per successfully and verifiably correct change, measured over a sufficiently large set of comparable tasks.
Local Improvements Are Not Automatically Global Improvements#
Another difficult point is the time horizon.
Removing an abstraction can simplify the next ten changes but make the eleventh considerably harder.
Conversely, an additional abstraction can initially cause more code but simplify numerous changes in the long run.
An autonomous deslop agent often sees only a slice of the future requirements.
That is why such agents are particularly good at local improvements. Fundamental architecture decisions, on the other hand, need a broader view and, where necessary, human steering.
Three Feedback Loops, One Common Goal#
The three techniques described target different quality attributes.
What is interesting is not the choice of exactly these three areas.
What matters is the separation between software development and continuous, measurable quality improvement.
In classic software development, quality improvement often only happens when someone notices a concrete problem and schedules time to fix it.
However, the different feedback loops must not make arbitrary changes independently of each other.
A performance optimization must not violate correctness. A refactoring must not degrade performance unnoticed. And a supposed architecture improvement must not remove important business requirements.
The various quality goals therefore have to be considered together.
Which Feedback Loops Does an Application Need?#
The three examples are not a complete list, and certainly not a binding model for every piece of software.
Which attributes should be continuously optimized depends on the requirements of the respective system.
For a distributed database, simulating network failures and concurrent operations can be decisive.
For a typical business application, functional correctness, data integrity and maintainability may matter more than the last milliseconds of response time.
For a real-time system, on the other hand, latency bounds and predictability come first.
Further feedback loops are conceivable as well:
| Quality area | Possible measure | Possible optimization |
|---|---|---|
| Security | Confirmed vulnerabilities, policy violations | Fix vulnerabilities, reduce attack surface |
| Reliability | Error rates, downtime | Improve error handling and recovery |
| Resource consumption | CPU time, memory, energy demand | Use resources more efficiently |
| Testability | Mutation score, test effort | Make tests more effective and simpler |
| Maintainability | Change effort, coupling, complexity | Simplify architecture and code |
| Accessibility | Automatable accessibility checks | Improve accessibility of the user interface |
Here too: not every attribute listed can be assessed fully automatically. Often, measurements only provide indications that have to be interpreted.
It would even be conceivable to adjust the selection and weighting of the feedback loops over the course of a project.
A young product may initially need different optimization goals than a system that has been in operation for ten years.
Can Such Feedback Loops Really Work Autonomously?#
Here we have to distinguish between two things:
- Optimization within given goals
- Setting and evaluating these goals
Agentic AI can take over the first task increasingly autonomously.
The second is considerably harder.
An agent can optimize a response time. But should it double memory consumption to do so?
It can simplify a complex architecture. But may it remove extension points that will only be needed next year?
It can run every test successfully. But how does it know that the tests cover all the important requirements?
The goals, limits and acceptable risks therefore have to be set explicitly.
That does not mean every single change has to be reviewed by a human.
Rather, we can also automate the approval of optimizations based on risk.
Feedback Loops and Risk-Based Approval#
My previous approach to risk-based AI software development, the Gray Software Factory, focuses on the question under which conditions an agent may adopt changes on its own.
A natural complement emerges here.
The feedback loops produce improvements. The risk-based development process decides which of these changes can be accepted automatically.
A small refactoring that is well covered by tests could thus be adopted automatically.
A fundamental change to the module architecture, on the other hand, could require a human decision.
The goal is explicitly not to perform as many human reviews as possible. It is about applying human attention where it actually adds value.
Two different mechanisms thus complement each other:
Risk-based quality control protects against changes whose risks are not sufficiently under control.
Continuous quality improvement tries to systematically improve the codebase across many changes.
How Do We Measure Whether the Software Really Gets Better in the Long Run?#
This may be the biggest challenge.
For a single change, we can determine fairly easily whether tests pass or a benchmark measurement has improved.
But how do we recognize whether the entire codebase has actually become better after a year of autonomous development?
Classic internal metrics such as complexity, coupling, code coverage or mutation score can provide hints. However, they are not direct measures of the economic or practical value of an architecture.
It would be more interesting to also measure the externally observable consequences:
- How often do changes cause new bugs?
- How long does it take to fully implement a business change?
- How many correction attempts are required?
- How high is the compute and token effort per successfully completed change?
- How often do already completed changes have to be reworked later?
The change effort in particular could become systematically observable for the first time through agentic AI.
AI agents leave extensive machine-readable traces of their work process. We can record how many files they read, which tools they call, how many attempts they need and how much time and compute they consume.
This creates new opportunities to study the long-term maintainability of software empirically. Architecture quality would no longer be judged solely by internal code properties, but by its actual effects on future development work.
Such measurements must remain comparable, however. A project that implements increasingly demanding requirements may need more effort even though its architecture has improved.
Conclusion: Sustainable AI Software Development Needs More Than Fast Code Generation#
Agentic AI not only changes the speed of software development but also opens up new possibilities for continuous quality care.
The three feedback loops are examples of a more general principle:
Software quality should not only be checked when individual changes are accepted, but continuously improved throughout the entire lifecycle.
AI can detect, examine, implement and evaluate many opportunities for improvement. Humans, however, still have to make sure that the right goals are pursued and that essential risks are adequately taken into account.
The combination of autonomous improvement processes and risk-based approval could thus become an important foundation of sustainable AI software development.
Perhaps we should measure the success of agentic AI less by how much code it produces today, and more by how simply, reliably and efficiently that code can be developed further tomorrow.
Sources and Further Reading#
- FoundationDB: Simulation and Testing – Deterministic simulation and automated fault testing.
- TigerBeetle: Deterministic Simulation Testing – Reproducible simulations of distributed systems.
- TigerBeetle: Protocol-Aware Deterministic Simulation Testing – Further development of the DST approach.
- OpenTelemetry: Documentation – Standardized instrumentation and collection of telemetry data.
- OpenTelemetry: Signals – Metrics, traces and logs.
- Phil Eaton: What’s the big deal about Deterministic Simulation Testing? – Introduction to DST and its areas of application.
- Dropbox: Testing sync at Dropbox – Deterministic, seed-reproducible randomized tests of the Nucleus sync engine.
- Fortune: Antithesis, Jane Street, Ethereum and the FoundationDB legacy – MongoDB, Ethereum and Jane Street as users of the DST platform Antithesis.
- Nikita M. (@meln1k) on X – The post that juxtaposes DST, OTel metrics and deslop skills as three AI loops.
This article was prompted by a post on X by Nikita M. (@meln1k), which juxtaposes Deterministic Simulation Testing, OpenTelemetry metrics and so-called deslop skills as three ways of continuous AI-assisted code improvement and proposes token consumption in day-to-day changes as a measure of architecture quality. The classification and extension presented here is an independent take on that idea.
This article was translated from German with AI assistance.
