Use coding agents to characterize, test, and incrementally migrate the system nobody wants to touch — without a big-bang rewrite.
Every large organization carries a system that is business-critical, poorly understood, sparsely tested, and written in something the current team does not know. The traditional options are both bad: leave it, or fund a multi-year rewrite with a well-documented failure rate. Coding agents change the economics of a third option that was previously too labor-intensive to attempt — incremental strangulation, where you characterize the existing behavior with tests, extract capability by capability, and retire the legacy system in slices. The agent's real contribution is not writing the new code; it is the enormous, tedious, previously-unfundable work of reading a million lines nobody has read in a decade and generating the characterization tests that make any change safe. Teams that point an agent at a rewrite get a plausible-looking system with unknown behavioral differences. Teams that point it at comprehension and test generation first get a migration that actually lands.
Point the agent at the codebase to produce artifacts nobody has time to write by hand: a dependency map, an inventory of external integrations, a catalogue of business rules found in the code, and a list of dead paths. Have the engineers who know the system best review this output — it will be partly wrong, and the corrections are themselves valuable documentation. This phase alone often justifies the program.
This is the load-bearing step. Characterization tests capture what the system does today — including the bugs — rather than what a specification says it should do. Agents are unusually good at this because it is high-volume pattern work over code they can read. Run generated tests against the live legacy system and treat every failure as a test defect until proven otherwise. Coverage on the paths you intend to migrate is the gate for everything downstream.
Choose a capability that is well-bounded, has clear inputs and outputs, is not on the most critical path, and has real business value on the other side. Resist starting with the hardest or most interesting subsystem. The first slice is proving the migration pattern and building organizational confidence, not demonstrating engineering ambition.
Standard strangler-fig mechanics. All calls to the target capability go through a routing layer that can send traffic to legacy or new. This is what makes the migration reversible, and reversibility is what makes it approvable.
The agent implements the new capability against the characterization tests. Human engineers review every change — this is where the discipline holds or fails. Agentic edits are fluent and confident, which makes them harder to review than junior-developer code, not easier. Treat review capacity as the actual constraint on migration speed and staff accordingly.
Route production traffic to both implementations, serve the legacy response, and diff the outputs. Every difference is either a bug in the new implementation or an undocumented behavior in the old one, and you need to know which before customers do. Run this for a full business cycle including month-end and any periodic processing.
Move traffic, monitor, keep the rollback available for an agreed period, then actually remove the legacy code. Migrations that leave both paths alive permanently have doubled the maintenance surface and delivered nothing — deletion is the step that realizes the value, and it is the step organizations skip.
Use these templates as-is or customize for your business.
You are analyzing a legacy codebase for a migration program. Produce a factual report. Where you are uncertain, say UNCERTAIN and state what you would need to read to resolve it. Do not speculate about intent. 1. ENTRY POINTS — every way execution enters this system (HTTP routes, scheduled jobs, message consumers, CLI, database triggers). 2. EXTERNAL DEPENDENCIES — every outbound integration: system, protocol, what data crosses, and what happens on failure. 3. DATA STORES — every table, file, or store written to, and by which paths. 4. BUSINESS RULES — every conditional that encodes a business decision rather than a technical one. Quote the code location for each. 5. DEAD CODE — paths with no reachable caller. State your confidence. 6. IMPLICIT CONTRACTS — behaviors other systems likely depend on that are not documented anywhere (response shapes, ordering guarantees, timing, side effects, error formats). 7. RISK CONCENTRATIONS — where a change is most likely to break something far away, and why. Output as structured markdown with file and line references throughout. Every claim must be traceable to code.
Characterization tests capture what the system DOES, not what it SHOULD do. RULES: 1. If current behavior is a bug, the test asserts the bug. Add a linked ticket. Do not fix it during migration — fixing behavior and moving code at the same time makes every diff unattributable. 2. Generate from real production inputs where you can obtain them safely. Synthetic inputs miss the shapes that actually occur. 3. Cover the boring paths. The rare path is where the interesting bugs are, but the common path is where the expensive regressions are. 4. Assert on observable outputs AND side effects: return value, database writes, messages emitted, files written, external calls made. 5. A generated test that fails against the legacy system is a defective test until an engineer proves otherwise. 6. Coverage gate: no slice is migrated until characterization coverage on its code paths meets the agreed threshold. No exceptions for schedule. SANITIZE PRODUCTION DATA BEFORE IT ENTERS A TEST FIXTURE OR A PROMPT.
SLICE: [capability name] BEFORE [ ] Capability boundary documented — inputs, outputs, side effects [ ] Characterization tests written and passing against legacy [ ] Coverage threshold met on the slice's code paths [ ] Facade in place, routing configurable per-slice [ ] Rollback procedure written and rehearsed [ ] Owner named for the migrated capability DURING [ ] New implementation passes all characterization tests [ ] Every agent-authored change human-reviewed (no exceptions) [ ] Non-functional parity checked: latency, throughput, resource use [ ] Observability parity: same metrics, logs, and alerts as legacy SHADOW [ ] Both paths running, legacy serving, outputs diffed [ ] Full business cycle covered, including month-end and periodic jobs [ ] Every diff explained — bug in new, or undocumented legacy behavior [ ] Diff rate at zero (or every remaining diff explicitly accepted in writing) CUTOVER [ ] Traffic moved, monitored through a full cycle [ ] Rollback available for the agreed window [ ] LEGACY CODE DELETED — this step is the value; do not skip it [ ] Documentation and runbooks updated
Get a new AI workflow every week. Prompts, tool stacks, and ROI math included.
Single agent with function-calling: one LLM with a defined toolbox (CRM, calendar, knowledge base) decides which tool to invoke at each turn. Easiest to debug; appropriate for most well-scoped business workflows.
Learn the agentic glossary →Where this workflow tends to break in production — and what to put in place before you ship it.
Agent-generated rewrite looks correct but differs behaviorally
Mitigation: Characterization tests generated and passing against legacy before any migration; shadow-run output diffing across a full business cycle.
Characterization tests encode the specification instead of actual behavior
Mitigation: Explicit rule that current bugs are asserted, not fixed; generated tests failing against legacy are treated as defective tests.
Review capacity becomes the bottleneck and reviews degrade to rubber-stamping
Mitigation: Migration pace is set by review capacity, not agent throughput; slice size bounded so review stays meaningful.
Both implementations left running permanently
Mitigation: Legacy deletion is an explicit checklist gate; a slice is not done until the old path is removed.
Production data reaches prompts or test fixtures unsanitized
Mitigation: Sanitization required before any production-derived data enters a fixture or a model context.
Skip this if the legacy system is genuinely stable, rarely changed, and not blocking anything — "nobody understands it" is not on its own a business case, and the correct action is to document it and leave it alone. Skip it if you cannot fund the review capacity, because agent-authored changes to a critical system without human review is the fastest way to convert a slow problem into an outage. Do not use agents for a big-bang rewrite under any circumstances; the failure mode is a plausible-looking system with unknown behavioral differences from the original, which is strictly worse than the legacy system you started with. And do not let production data reach a prompt or a test fixture without sanitization.
A phased approach to get this workflow running and delivering ROI.
Days 1–30
Foundation
Days 31–60
Optimization
Days 61–90
Scale
Most enterprises do not have an AI adoption problem. They have an AI inventory problem — and the first honest count is usually three to five times what anyone predicted.
Four vendors, four incompatible pricing models, and one arithmetic trap that doubles your bill without anyone telling you.
The general-purpose voice agent and the trades-specific one cost about the same. One of them books more jobs. The difference is not model quality — it is everything around the model.
One practical AI workflow per week. No fluff.
Get the full guide with step-by-step setup, workflow templates, and copy-paste assets.