The cost does not disappear, it moves: development in the age of agents
With agents, development cost moves from producing code to specifying and verifying it. What changes in the pipeline, in professional roles and in becoming a senior developer?

Writing code is becoming cheap. Specifying and verifying it is not. That is the whole argument: with agents, language models that autonomously use editors, terminals and tests rather than only generating text, development cost does not disappear. It moves from producing lines of code to what really matters: precisely stating what must be built and demonstrating that what was built is correct.
These are working notes on where I think the centre of gravity is moving, and what I have seen by trying it in practice.
The development cycle we know
For years, upstream phases were compressed and cost concentrated on implementation, at the expense of testing and validation. Agents reverse the balance.
| Phase | Today | With agentic development |
|---|---|---|
| 1. Product and functional requirements | Compressed | Main investment: rigorous specifications and Definition of Done (DoD) criteria |
| 2. Technical analysis and decomposition | Compressed | Strengthened: explicit architectural constraints |
| 3. Development | Long and expensive | Delegated to agents |
| 4. Unit and static testing | Eroded by development | Separate testing agent and mutation testing |
| 5. Review | High effort | Moves upstream and follows risk |
| 6. Integration and end-to-end tests | Intrusive or absent | Lean and specification-driven |
| 7. Validation and release | Weak | Shift-right: feature flags, canaries and observability |
An honest qualification: compressing phases 1 and 2 was not purely a business choice. Requirements often emerge through using the product, which is partly why agile shortened these phases.
The argument: the bottleneck moves
Producing code becomes cheap. Value concentrates upstream, in specification, and downstream, in verification.
The pipeline becomes iterative specification, independent acceptance tests, agentic implementation, automatic gates, targeted design review and progressive delivery, controlled incremental release through canaries, flags and cohorts with fast rollback.
This is not a return to waterfall. The specification is a living artefact refined in short cycles. Prototyping with agents is cheap, so it can help discover the specification as well as implement it.
Small specifications, strong constraints
One well-defined specification per feature or fix, with strict DoD criteria. Architectural constraints live outside individual specifications and are executable.
- Small scope: one specification per feature or correction, rather than global documents.
- Risk: strong local specifications can still add up to an incoherent system.
- Shared context: Architecture Decision Records (ADRs), short versioned notes explaining architectural choices, and agent context files such as AGENTS.md defining conventions, constraints and instructions, referenced by every specification.
- Executable constraints: custom lint, static checks for errors and convention violations, plus architecture tests enforcing structural dependency rules, using tools such as Java’s ArchUnit or JavaScript/TypeScript’s dependency-cruiser.
An agent will eventually violate a constraint written in prose. One that fails the pipeline is a different matter.
Who writes the specification
The Product Manager (PM) writes the user story, the developer turns it into a specification, and the PM validates the behavioural criteria.
- PM: user story and acceptance criteria in business terms.
- Developer: specification with technical constraints, DoD and acceptance tests.
- PM: validates the behavioural part so the developer does not close the loop alone, writing the specification and checking output against their own interpretation.
This is effectively three amigos, the practice of business, development and quality assurance jointly defining a story before coding. QA becomes supervision of the testing agent. Developers consequently need more PM skills, a significant professional change.
Implementation with opposing agents
Test-Driven Development (TDD) with two separate agents: one writes the strongest tests it can from the specification; the other writes code to pass them.
The references are classic TDD’s ping-pong pairing, alternating between writing a failing test and the implementation, and AgentCoder, which separates programmer and test designer agents.
Risks and mitigations
| Risk | What happens | Mitigation |
|---|---|---|
| Goodhart’s law, a measure stops being useful when it becomes the target, and overfitting, fitting known cases without generalising | The coder optimises for the tests, potentially special-casing them | Give the coder the specification, not test source; keep hidden test sets |
| Correlated errors | Two agents using the same model share blind spots | Different models for tester and coder |
| Weak tests | Many tests, few truly probative | Mutation testing to assess the tester |
Mutation testing in brief: a tool makes small code changes, such as > to >=, && to ||, or a return to null, then checks that at least one test fails. The mutation score, killed mutants divided by total mutants, measures test quality better than coverage, which only measures executed code; branch coverage measures exercised alternatives. Tools include Stryker for JS/TS and C#, PIT for Java, Infection for PHP and mutmut for Python. In CI, run it only on the pull request diff and read survivors before the score, as the case below illustrates.
A concrete case. I tried this on two features in Taita, my FastAPI side project: handwritten specifications, one agent writing tests without seeing the implementation, another writing code without being allowed to write tests, followed by coverage and mutmut.
| Pure function | Database plus mocks, substitutes isolating dependencies in tests | |
|---|---|---|
| Branch coverage | 100% | 97% |
| Mutation score, first round | 93.5% | 85.6% |
| Real gaps against specification, round 1 → 2 | 1 → 0 | 0 → 0 |
Three points change how this should be read:
- 100% coverage hid a blind test. A green, covered test named
test_default_max_length_is_oneused data for which an incorrect default produced the same result. Only a mutant revealed it. Given the survivor report, the agent closed the gap in one round. - The raw score is a poor gate. The drop from 93.5% to 85.6% was entirely noise: log text, equivalent mutants that do not change observable behaviour and cannot be killed, and unrequested code. A fixed threshold would have rejected a suite with no specification gaps. Classify survivors before reading the number.
- The greatest risk is code nobody requested. The implementation agent added defensive handling outside the specification, which specification-derived tests did not cover. That is a process issue rather than a testing issue.
The limitations are serious: two small features, precise specifications, and the same model for both agents, so the mitigation above was absent. I later continued more systematically, with more nuanced conclusions. Separating agents alone does not prove the argument, and the strongest signal came from somewhere else entirely. Full data, protocol and limitations are in Agent-written tests and mutation testing: an argument not yet proven.
Review changes shape
Review does not disappear. It moves upstream and concentrates on risk.
- Review specifications and acceptance tests before code exists. This is the most valuable review.
- Automatic gates: type checking, lint, Static Application Security Testing (SAST), architecture tests, mutation score on the diff and dependency checks.
- A separate reviewer agent using a specification-derived checklist.
- Self-documenting PRs: every DoD point mapped to its test, non-obvious decisions explained.
- Risk-based human review: CODEOWNERS, assigning mandatory reviewers by repository path, for authentication, database migrations, public APIs and payments; sampling elsewhere.
- Ownership: whoever signs the specification must be able to explain what reaches production.
The risk needs naming: more generated code means more code to understand. Without review, comprehension debt accumulates: code that works but nobody fully understands.
Validation and release: shift-right
After rigorous DoD tests, the real safety net is in production: feature flags, canaries releasing to small traffic or user groups, observability through metrics, logs and traces, and fast rollback.
This closes the loop: the specification defines production signals as well as tests. If the DoD requires “p95 latency below 300 ms”, the threshold containing 95% of requests, or “no increase in 5xx errors”, server error responses, those criteria become rollback alarms. The specification written at the beginning also determines what makes us turn back at the end.
Shift-right does not replace shift-left, testing as early as possible. Using it as an excuse for fewer earlier tests means testing on users.
Practical AWS implementation through ECS canaries and tenant rollout is in the second article: Shift-right on AWS: canaries by revision and tenant.
What this means for people
Reluctance towards agents is not one single thing. Seniority moves from code towards judgement about specifications, constraints and evidence.
Three kinds of reluctance
- Resistance to change: a management issue.
- Well-founded scepticism: in 2025, METR, a nonprofit studying AI capabilities, measured experienced developers working 19% slower with AI while believing they were faster. A 2026 follow-up suggested acceleration, but METR considered it unreliable because many refused to work without AI. The perception-measurement gap remains.
- Professional identity: many chose this career to write code, rather than specifications.
Tomorrow’s senior developer
- Understanding 100% of the code becomes less important; deep understanding concentrates on boundaries, APIs, data, authentication, integrations and critical paths.
- Judges evidence more than code: specifications, tests, observability and traces.
- Understands architecture better than today’s senior developer.
The cost of waiting accumulates
- Ephemeral knowledge: current prompts and tools expire quickly.
- Structural knowledge: how large language models (LLMs) fail, how to evaluate stochastic systems and design an agent’s context. Waiting mainly costs this knowledge, along with historical experience that prevents repeated mistakes.
- Counterweight: historical experience becomes baggage when anchored to outdated judgements, such as “agents did not work in 2024”.
Closing: tomorrow’s senior developers
An uncomfortable question remains: if juniors no longer learn through writing and debugging code, how will they become seniors?
One possibility I find plausible is that the path itself changes. Tomorrow’s senior may develop by learning to turn a user story into a safe, testable result consistent with an architecture they designed, rather than by writing thousands of lines. Deep code understanding would remain, concentrated where it matters: boundaries, data and critical paths.
This is uncertain. It is difficult to know whether judgement can develop without going through code. But if it can, seniority will depend on how well you specify, constrain and verify. Those who do not keep learning may discover they are less senior than they think.
References
- METR, Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity (arXiv:2507.09089).
- METR, We are Changing our Developer Productivity Experiment Design (via Conffab).
- Capital & Compute: AI Programming in 2026.
- Reuters via Yahoo, AI slows down some experienced software developers.