How We Used a Grounded Coding Agent to Accelerate a Commerce-Platform Migration
A large commerce migration is a coordination problem before it is a coding problem. Here is how we replaced cross-team handoffs with a spec-driven, pattern-classifying coding agent — and the validation scaffolding that kept it from hallucinating its way into production.
By LegalZoom Engineering · · 7 min read
We recently set out to move our commerce stack. Not one service: the whole surface. A portfolio of distinct products, each touching orders and catalog, subscriptions, the customer dashboard, business profiles, fulfillment, and entitlements, all needing to move from a legacy commerce platform to a new one. The work spanned roughly a dozen repositories and several domain teams.
No single change was hard. Creating an offer, wiring a checkout step, consuming an order event: each was routine. The difficulty was that every product required dozens of these changes, in the right order, across systems owned by different teams, with enough product-specific variance that you could not just copy the last one. Different checkout and questionnaire layouts. Different jurisdiction-specific fee and location handling. Different fulfillment patterns. Each product became a weeks-long relay of handoffs, and handoffs are exactly where work stalls.
So we made one decision, and almost everything else in this post is a consequence of it: we let a coding agent draft the cross-system changes for each product. The rest is the scaffolding we built because of what that decision puts at risk, and the things it bought us that we did not expect.
What the decision could have meant, and what we refused
The naive reading of “let an agent draft the changes” is to point a capable coding agent at the repos and ask it to do the migration. We refused that version, because the failure modes are well understood. Generated migration code has a recognizable set of ways to go wrong: fabricated database columns that look plausible but do not exist, references to offers that were never created, broken foreign-key ordering, billing config that does not match the catalog, and the most dangerous one, mock or placeholder data leaking into a customer-facing surface on a real account.
A migration that ships fast but wrong is worse than a slow one. So the decision came with a constraint attached. The agent would draft, but it would not improvise, and it would not be trusted. We built the accelerator as a knowledge orchestrator rather than a code generator: a coding-agent “skill” grounded on a curated corpus, with validation doing the work that trust would otherwise have to do.
Consequence one: drafting becomes classification
The first thing the decision forced was a question of how the agent decides what to write. We refused to let it work out how to migrate a product from first principles. Every migration became a constrained classification: pick one of a few named patterns, crossed with a product shape (transactional, subscription, concierge).
The patterns form a small, ordered ladder:
- Pattern A — no fulfillment-side filing-endpoint changes. Filings stay on the legacy platform while entitlements live elsewhere. The lightest touch.
- Pattern B — Pattern A plus a customer-facing filing endpoint and the fulfillment scaffolding behind it.
- Pattern C — Pattern B plus a new workflow-engine launcher and a new fulfillment workflow module, for products that have no existing launcher to reuse.
Because pattern selection is driven by product type and fulfillment needs rather than the model’s mood, it is auditable and repeatable. “Why did this product get Pattern C?” has an answer you can point at in a playbook, not a paragraph of post-hoc rationalization. That auditability is a direct payoff of constraining the draft.
A single YAML spec describes each product, the one source of truth for every parameter the migration needs. The skill reads that spec, the pattern playbooks, and literal per-repo reference implementations, then works in phases:
Phase 0 Discovery scan a fixed set of repos for existing references
to the product → decide net-new vs modify, per repo
Phase 1 Classify select pattern (A/B/C) × shape from the spec
Phase 2 Generate emit a per-repo bundle of diffs from the spec +
matching reference implementation
Phase 3 Validate SQL checks, billing-consistency assertion,
UNVERIFIED manifest → only then surface diffs
The grounding is deliberately literal. Rather than asking the model to invent the shape of a change, we hand it a real reference implementation for that repo and that pattern and ask it to parameterize from the spec. The corpus follows a portable skill contract, so it runs across more than one coding-agent harness: we did not want the durable asset tied to a single vendor’s tool.
A typical run touches catalog and offers (create products, families, offers, and fee config in the new platform), entitlements for subscription products, the purchase flow and universal checkout, downstream fulfillment APIs triggered after questionnaire completion, order-event consumers, document generation moving to the target docgen system, and notifications moving to the target notification platform. Every run writes a dated bundle of diffs, and the spec that produced it is checked in alongside the bundle, so any change is reproducible and auditable months later.
Consequence two: every draft is assumed wrong until proven
The decision to let a model draft pricing-touching, customer-facing code is only defensible if you build the checks to catch the model’s specific mistakes. This is where most of the engineering lives. We assume the generated code is wrong until checks say otherwise.
For generated SQL, an automated layer verifies uniqueness and foreign-key ordering, and runs a billing-consistency assertion: it reads the price keys from the new platform’s database, calls the billing system’s API, and asserts a one-to-one match at the correct amount and billing period, emitting a pass/fail report. A pricing mismatch is the kind of bug that is invisible in code review and very visible on a customer’s invoice, so we made a machine responsible for catching it. Behind that sits a manual fallback checklist aimed at the same failure class: no fabricated columns, referenced offers actually exist, no empty IN clauses, correct foreign-key order.
The agent is also fenced in on what it is allowed to do, which is the other half of letting it draft safely. It never opens a PR or pushes to a remote without an explicit instruction. It is blocked from side-effecting external systems, with ticket and wiki write tools denied, so it cannot quietly mutate the world while it reasons. And it emits a manifest of UNVERIFIED items and human decisions, which is the most honest thing the tool does: it tells you what it could not confirm.
Catalog and product-config changes go through a two-phase approval gate, moving from NOT_APPROVED to APPROVED with a named reviewer and date, so a config change is a controlled promotion rather than a direct mutation.
The application code the agent authors flows through layered review. An initial automated reviewer catches correctness and safety defects; a second layer classifies severity and blocks merge on critical findings; and a reconciliation pass tracks every prior finding through to resolved before approval. This is not theater. In one review the gates surfaced a critical safety defect where fabricated mock data could appear in a customer-facing context on a real account. The fix gated that mock data outside production, and the reconciliation pass confirmed the resolution before the change merged. That is the exact failure mode we were most afraid of when we made the decision, caught by the scaffolding we built to catch it.
End-to-end correctness gets checked with generated synthetic tests that drive full purchase flows and assert on downstream outcomes: filing records, processing-order IDs, order stage, active subscriptions, entitlements.
Consequence three: the costs the decision carries
Grounding is not free, and the decision to ground rather than improvise has a maintenance bill. The reference implementations and playbooks are an asset you have to maintain, and when foundational work was still open or got superseded, an agent’s earlier exploration could be wrong for a later product. We had to manage that reference-instability risk actively. Constraining the agent to named patterns also means a genuinely novel product needs a human to extend the playbook before the accelerator is useful. We accepted that ceiling on purpose, because the alternative is improvisation we cannot audit. The validation layers add latency to every run, too. That is the right trade for a system that mutates pricing and customer-facing surfaces.
Humans keep the judgment-heavy calls: finance and revenue-recognition sign-off, platform-gap prioritization, questionnaire UX design, and the launch-ramp and feature-flag go-live risk calls. The accelerator is good at the coordinated, mechanical breadth of a migration. It is not good at deciding what should be true.
What the decision actually bought us
Here is the part we did not predict. The biggest drag on this work was never code generation. It was cross-team provisioning and coordination friction. The win from letting an agent draft came less from the agent typing faster and more from a reorganization the agent enabled: collapsing per-domain-team handoffs into a single platform-owned, end-to-end team driven by the skill. That shift, more than any prompt, is what materially compressed the time to migrate each product.
The second thing we learned is how fragile the savings are. Brittle generated PRs erode them instantly. One bad bundle that wastes a reviewer’s afternoon undoes the speed of ten good ones. The skill only became trustworthy after we hardened it iteratively against multiple real migrations. The durable asset is the codified, grounded skill, not any single PR it emits.
We have run multiple products through the accelerator now, which is what gives us confidence that the playbook-driven, spec-to-multi-repo-bundle approach generalizes. From here, the direction is to widen the pattern catalog as new product shapes appear, push more of the UNVERIFIED manifest into automated checks, and keep treating the agent as a fast, fenced-in colleague rather than an oracle. The headline is not “AI wrote our migration.” It is that the one decision to let an agent draft cross-system changes only paid off because we wrapped it in classification, grounding, validation, and human gates. That structure, not the model, is the thing we are proud of.
We're building this — want in?
If shipping pragmatic, AI-native systems at the scale of millions of small businesses sounds like your kind of problem, we'd love to talk.
See open rolesMore in AI for Platform Migrations
Rewriting Document Generation Without the Big-Bang Risk
How we replaced a legacy, vendor-backed document engine that touches every product line — turning a high-stakes rewrite into a per-template routing decision that was always one flag flip away from rollback.
LegalZoom Engineering · · 7 min read
Unifying Feature Entitlements Across a Commerce Platform Without Breaking It Mid-Flight
Entitlements are the load-bearing glue between a purchase and what a customer can actually do. Here is how we consolidated two generations of that glue into one authoritative store, migrated hundreds of thousands of historical records idempotently, and never once risked a paid order without its grant.
LegalZoom Engineering · · 8 min read