Refactor Legacy Code with a Coding Agent, Step by Step
Choose one awkward function, not the whole application
Legacy code is difficult because its real contract often lives in production behavior rather than documentation. A coding agent can help uncover that contract, but asking it to modernize an entire application creates too many opportunities for accidental change.
Start with a small example: an invoice calculation function that mixes discounts, tax, rounding, and receipt formatting. Your first refactor will separate calculation from formatting without changing any result. Leave new features, dependency upgrades, and performance improvements outside this task.
Ask the agent to inspect the function and its direct callers, then explain the current behavior without editing anything. Request a short list of uncertainties. This turns the first interaction into a bounded investigation rather than an expensive rewrite.
Set a spending limit before the agent investigates
Choose an amount you are comfortable spending on this session, then divide the work into inspection, tests, and one implementation pass. Reserve some of that amount for reviewing failures rather than spending everything on the initial attempt.
MyRelay gives an individual developer one key and one pay-as-you-go budget across supported models, with visibility into each request’s tokens and cost. Create a MyRelay account if you want to track those costs while working through this process.
Start with a lower-cost model for a narrow explanation or test draft, and move to a more capable model only when the task needs deeper reasoning. Check current prices before choosing. Avoid repeatedly sending the entire repository; provide the relevant function, callers, and test context first.
Record existing behavior before improving the structure
Before changing the invoice function, establish a clean version-control checkpoint and run the existing relevant tests. Record any failures that already exist so they do not get confused with regressions.
Next, ask the agent to propose characterization tests. These capture what the code currently does, including behavior that looks surprising. Useful invoice cases might include an empty order, a discounted item, a rounding boundary, and a tax-exempt customer.
Review expected results yourself. An agent can accidentally write tests for the behavior it thinks the application should have. If the current function rounds in an unusual order, preserve that behavior for now and record the concern separately. Refactoring and correcting business rules should be separate changes.
Agree on a small transformation before allowing edits
Once the tests pass, ask for a plan that names the responsibilities to separate and explains how compatibility will be preserved. For this example, the plan might extract receipt formatting while leaving calculation order and the public interface untouched.
Tell the agent explicitly to avoid unrelated cleanup, new dependencies, and changes to stored data. Also ask it to stop and report if it discovers that the proposed boundary cannot be separated safely.
Approve only one transformation at a time. A short plan is cheaper to challenge than a large patch, and it gives you a concrete standard for reviewing the result.
Inspect the first patch before requesting another
Let the agent make the agreed change, then read the diff before accepting its summary. Check whether it moved behavior or quietly changed it. Pay particular attention to rounding, error handling, mutable state, and the order of operations.
Run the focused tests again, followed by the broader relevant suite. Ask the agent to report which checks actually ran and which were unavailable. A confident explanation is not evidence that a test passed.
If something fails, provide the failure output and request a diagnosis before another edit. Avoid letting the agent repeatedly rewrite the function without explaining the cause. When the patch grows beyond the agreed boundary, revert it and narrow the task.
Finish with a verified checkpoint and a clear stopping point
Compare representative invoice outputs before and after the refactor. Confirm that callers still use the same interface and that no unrelated files changed. Then commit the small, verified result with a message explaining the structural change.
Review the session’s request costs in MyRelay alongside the outcome. Did broad exploration consume the budget, or did repeated repair attempts dominate? Use that evidence to scope the next session more tightly.
Stop when the chosen boundary is cleaner and the checks support unchanged behavior. A successful agent-assisted refactor does not need to transform the whole system. It needs to leave one part easier to understand, with evidence that it still works.