A small team migrated 100+ GraphQL fetchers by turning Jira tickets into behavioral specs that AI agents could execute against.

We recently migrated 100+ GraphQL fetchers from a legacy gateway service to a newer platform layer. We managed to do this with 5 developers completing around 2 quarters worth of work in a week, splitting the work up into parallel batches.

Jira was the system of record that made this workflow possible, from humans reviewing the plan to AI agents executing the work. Better-structured intent is what collapsed the timeline.

This blog covers the role Jira played, why well defined tickets are the missing ingredient in most AI-assisted engineering workflows, and what we learned about context rot, agent execution, and verification at scale.


What is spec-driven AI migration?

Spec-driven AI migration is an engineering approach where every unit of work is defined as a structured behavioral specification before any code is generated. Instead of feeding AI agents a vague prompt or a raw codebase, you give them a durable, human-reviewed contract: what the system does, what it depends on, what “done” looks like. The AI executes against the spec. Humans review the spec, not the generated output line by line.

The approach is especially effective for migrations where behavior is already known and needs to be preserved, not invented, in a new context.


What makes a migration a good candidate for AI

We had a legacy gateway service that handled GraphQL logic across hundreds of fields. It worked reliably, but it was implemented in a legacy tech stack and different from our standardised stack, which meant every change required context-switching between two codebases and two mental models. Consolidating onto one stack would reduce maintenance surface and simplify onboarding, but the migration scope had never justified the effort manually.

What made it a candidate for AI-assisted migration was that the existing service was a verifiable source of truth at the API level. Instead of designing new systems we were translating known behavior into a new stack.


How does Jira make AI-assisted engineering workflows scale?

Most teams use Jira to track that work exists. We used it to capture what the work means. That distinction turned out to be the difference between a workflow that could scale with AI and one that couldn’t.

Jira as a store of truth: reviewable by humans and agents

Each migration ticket was a structured behavioral specification that captured everything needed to understand and reproduce what a fetcher did:

  • The GraphQL schema being served: the exact types, fields, and nullability contracts the consumer depended on
  • The upstream APIs and data sources: where the data came from, including service calls, database lookups, and cached values
  • Transformations and renames: how raw data was reshaped before being returned (field mappings, type coercions, computed values)
  • Business rules and edge cases: conditional logic, fallback behavior, permission checks, and error handling
  • Explicit acceptance criteria: what “done” looked like in verifiable terms

This built a full picture of what each data fetcher did: not just what it touched, but what it intended. Because it lived in Jira, engineers could audit the spec before any code was generated. Agents could read the same spec and produce implementations against it.

The spec was the contract between human intent and machine execution.

How do you prevent AI agents from losing context between sessions?

Context degrades across handoffs. You explain something in a prompt, an agent generates code, you come back the next day and the thread is stale. You start over. Multiply that across 100+ fields and you’ve recreated the manual effort you were trying to avoid.

Jira solved this because each ticket was a persistent, self-contained unit of intent. It didn’t matter whether execution happened in a single session or across multiple days, by one engineer or handed to another, in one agent thread or fanned out across sub-agents. The ticket held the truth so context wasn’t lost between sessions. No tribal knowledge lived only in someone’s head or a Slack thread.

A well-specced Jira ticket is the best possible prompt for an agent. It carries structured intent, bounded scope, and verifiable acceptance criteria in a format that doesn’t decay. That’s what separates using AI as a chatbot from using it as an execution system.


How to run a spec-driven AI migration

1. Generate specs with AI, review them as humans

We used AI to generate the initial specification for each ticket by reading the existing source code and producing a structured summary of behavior. Engineers reviewed and corrected each spec before any code was generated. The goal: front-load human judgment into the spec so downstream execution could be higher-confidence and lower-touch.

2. Implement from specs, not from scratch

With a verified spec in Jira, AI agents generated migration code with high accuracy. The quality of output was directly proportional to the quality of the spec.

Engineers shifted from writing repetitive migration code to curating prompt patterns, managing batch boundaries, and handling edge cases.

3. Verify through parity, not line-by-line review

We didn’t want code review to become the new bottleneck. Output parity was the primary confidence signal:

  • Compare API responses between old and new implementations
  • Use AI to verify generated code against the spec’s acceptance criteria
  • Run automated scripts for repeatable validation

The workflow only scaled because generation and verification both accelerated. Speed up implementation while validation stays manual, and you haven’t changed the economics.


How do you trust AI-generated code? Verify it in layers

Generating large amounts of code from specifications with AI is useful, but validating your changes to ensure they work as expected is even more important. We accomplished this in several ways throughout the lifecycle.

1. Acceptance Criteria for the Agent

The first validation set is stored in the ticket as acceptance criteria, guiding the implementing agent to verify their work meets expectations.

2. Pre Review Verification

After the agent finished, we used another validation agent in the repository to test the generated code against the live service. It extracted the schema from the ticket, tested the local code version against the live service, and flagged any output differences. The feedback could then guide the implementation agent to correct its mistakes.

3. Live Traffic Validation

Testing locally alone doesn’t guarantee success, so we built a shadow traffic framework in the old service to forward requests to the new platform and compare responses. This ensures consistency between services, boosts confidence during traffic switchovers, and helps us fix implementation errors before customers ever notice.


Jira as agent infrastructure

What we built is repeatable. Structured work management is the backbone of AI-assisted engineering, and Jira is where that structure lives.

Atlassian’s Teamwork Graph connects people, work, and knowledge across tools in a permissions-aware knowledge graph. When Jira tickets are well-structured, they become nodes in that graph, carrying context that agents can traverse, reference, and act on without losing fidelity.

The fundamental challenge of agentic workflows is context delivery. Agents are only as good as the context they start with. A well-specced Jira ticket delivers:

  • Bounded scope: the agent knows exactly what to do and when to stop
  • Structured intent: not a rambling prompt, but a machine-readable contract
  • Persistent memory: context that doesn’t degrade across threads, sessions, or handoffs
  • Human-reviewable checkpoints: engineers can audit what the agent will attempt before it attempts it

In our case, each Jira ticket was a durable prompt that could be picked up by any agent, at any time, with zero context loss. That’s what made parallelism possible: we could fan out across dozens of tickets simultaneously because each one was self-contained.


What spec-driven AI migration taught us about agentic workflows

1. The spec is the product

The most important work was creating reliable specs. A weak or ambiguous spec meant everything downstream suffered. A clear spec made implementation almost mechanical. Invest here first.

2. Jira tickets are agent memory

Traditional prompts are ephemeral. Jira tickets are persistent, structured, and reviewable. For any workflow that spans multiple sessions or multiple agents, the ticket is the memory layer.

3. The review layer matters as much as the generation layer

Most teams invest in prompting and generation. Few invest equally in verification. The teams that scaled this fastest were the ones who designed their review process before they started generating code.

4. Verification needs as much design as generation

Generated code is only credible if you trust the process that checks it. Output parity, automated scripts, and targeted human review made the workflow defensible at scale.

5. Engineering roles shift up, not out

The work became less about typing migration code and more about defining behavior, shaping context, reviewing patterns, and managing confidence.


Put this to work on your own migration backlog

Every engineering organization has work like this: known migrations, agreed-upon deprecations, cleanup projects that sit in the backlog because the effort-to-value ratio never quite justifies starting them.

The economics change when you define behavior as structured specs in Jira, treat tickets as the system of record for agent execution, batch work into clean repeatable units, and invest in verification systems alongside generation.

For the right class of problem (translating known behavior, not inventing new systems), spec-driven development with AI can turn years of deferred migration into a week of focused execution.

The accompanying Loom walks through the workflow in detail, including how we structured tickets, batched work, and approached verification.