Building AI-Native Workflows
Agents, prompts, RAG and code transformation in production
Agent loops and tool calling
After this you can design a reliable agent loop for a coding task.
An agent that can edit code is a loop with a kill switch, not a magic box.
Every coding agent - Cursor's included - runs the same skeleton. The model proposes an action, a tool executes it, the result feeds back and the model decides whether to continue or stop. When you build an AI-native workflow for a customer, you own that skeleton, so you have to know exactly where it breaks.
- 1Plan. The model reads the task plus current context and decides the next concrete action.
- 2Call a tool. It invokes one tool - read a file, edit a file, run tests, search the repo - with structured arguments.
- 3Observe. The tool returns a result the model can actually parse: a diff, a test summary, an error.
- 4Re-plan. The model updates its plan against what just happened, not against what it assumed would happen.
- 5Stop. A condition fires - task verified, budget hit or no progress - and the loop ends deliberately.
Interactive diagram. Tab through its regions; each focused region shows its detail in the panel below.
The verify step is the gate: nothing counts as done until a tool - not the model - confirms it.
Where loops actually failthe two failure modes you will demo
The model retries the same edit, re-reads the same file or oscillates between two wrong fixes.
Symptom: step count climbs, the diff stops changing in any meaningful way.
The loop keeps calling the biggest model on a growing context with no ceiling.
Symptom: token spend per task has no upper bound you can name before you run it.
Tool design for code tasksthe contracts that make a loop debuggable
The tools matter more than the prompt. A loop with sharp, observable tools recovers from a confused model; a loop with vague tools fails even when the model is right.
- Tool
- read_file
- Make it idempotent by
- Returning the same content for the same path + revision
- Make it observable by
- Including line numbers and the resolved path it actually read
- Tool
- edit_file
- Make it idempotent by
- Applying an anchored patch, not a blind overwrite
- Make it observable by
- Returning the exact diff that landed, not just “ok”
- Tool
- run_tests
- Make it idempotent by
- Running the same suite the same way every call
- Make it observable by
- Returning pass/fail counts and the first failing assertion
- Tool
- search
- Make it idempotent by
- Deterministic ordering for the same query
- Make it observable by
- Returning ranked hits with file + line, not a blob
| Tool | Make it idempotent by | Make it observable by |
|---|---|---|
| read_file | Returning the same content for the same path + revision | Including line numbers and the resolved path it actually read |
| edit_file | Applying an anchored patch, not a blind overwrite | Returning the exact diff that landed, not just “ok” |
| run_tests | Running the same suite the same way every call | Returning pass/fail counts and the first failing assertion |
| search | Deterministic ordering for the same query | Returning ranked hits with file + line, not a blob |
Idempotent tools let you retry safely. Observable tools give the model a real signal to re-plan on.
def run_agent(task, *, max_steps=12, cost_ceiling_usd=2.0):
state = init_state(task)
spent = 0.0
for step in range(max_steps):
action, usage = model.plan(state) # propose ONE tool call
spent += usage.cost_usd
if spent > cost_ceiling_usd:
return stop("cost_ceiling", state)
result = tools.invoke(action) # idempotent + observable
state = state.observe(action, result) # feed the real result back
if state.task_verified(): # tests green, types clean
return stop("verified", state)
if state.no_progress(window=3): # diff unchanged 3 steps
return escalate_to_human(state)
return escalate_to_human(state) # hit step budgetStop conditions and budgetsthe part interviewers probe hardest
- Max steps caps the worst case so a stuck loop can’t run forever.
- Cost ceiling is a dollar/token budget checked before each model call, not after the bill arrives.
- Progress detection watches whether the diff or test state is actually moving; if it stalls for N steps, the loop is stuck even though steps remain.
- Success check is the only happy stop - tests pass and the type-checker is clean, verified by a tool, not asserted by the model.
“The model says it’s done” is not a stop condition. The model is the least reliable judge of its own output.
Tie the success stop to a tool result a customer would trust: a green suite, a clean type-check, a passing lint gate.
Recovering from bad tool callsvalidation, retries and the human fallback
- Malformed tool args
- Validate against a schema before executing; return the validation error so the model can self-correct.
- Tool throws / times out
- Retry with backoff a bounded number of times, then surface the failure into the loop as an observation.
- Edit doesn’t apply
- Re-read the file, re-anchor the patch; never force a blind overwrite that loses local edits.
- Repeated failure
- Fall back to a human with the state, the last error and a concrete suggested next step.
When asked to “build an agent for X,” resist sketching prompts. Draw the loop, name the four tools and state your two budgets and three stop conditions out loud.
That ordering signals you’ve shipped one in production, where the prompt is the easy part.
Cursor Agent is this pattern made concrete. It reads and edits across files, runs the terminal, searches the indexed codebase and asks for approval on actions that touch the outside world. When you deploy a workflow on top of it for a customer, you’re tuning these same knobs - which tools it can reach, when it pauses for a human and what counts as done.
One loop, many loops: parallel orchestrationhow the single loop scales in Cursor
The single loop is the unit; production work runs many of them at once. Cursor exposes two ways to fan out. Sub-agents (shipped in Cursor 2.5) let a parent loop spawn children for independent sub-tasks - each gets its own isolated context window, writes its findings to a file and hands only that file back, so the parent re-plans on a summary instead of swallowing every child’s tokens. In one demo the parent spun up two sub-agents and summarized while staying at roughly 16% of its own window. Multitask modeSending one prompt that fans out into several agents working on independent tasks at the same time. spins up multiple full agents from one prompt (e.g. a backend 429 rate-limit change and a frontend dashboard in parallel), each doing its own codebase understanding, with effectively no hard limit on how many run at once.
If task B is unrelated to task A, start a new chat - don’t pollute one loop’s context with another’s.
If B and C both depend on A’s output but are unrelated to each other, spawn them as sub-agents so each runs in isolated context and the parent only re-plans on the returned files.
Three sub-agents are built in - explore, bash and browser - and you can pin a different model per child (e.g. a cheap parent spawning an Opus-class auditor).
Each model has limited context attention, like a person. Spend that attention on planning, then break focused sub-tasks off to a model trained for that exact job, and each one uses its window most advantageously.
This is the mechanism under the whole loop: a frontier model reasons out the plan, then a cheaper, faster coding model executes the to-dos - you don’t keep paying the expensive reasoning model once the plan exists.
Two foreground agents editing the same file used to block each other - the old multi-tab collision problem.
Sub-agents with isolated context sidestep it: parallelize independent slices, and keep work that touches the same file in a single loop.
Takeaway. An agent loop is a controlled cycle of plan → act → observe with a hard stop - the design work is in the stop conditions and the tool contracts, not the prompt.
Self-check
QA coding agent loop has run 6 of its 12 allowed steps. The model keeps proposing edits but the diff and test results haven’t changed for the last three steps. What should the loop do?
Prompt and context engineering for codebases
After this you can construct context that makes a model reliably edit real code.
The model didn’t fail your refactor. Your context did.
On a real codebase, output quality tracks context quality far more than prompt wording. The job is to assemble the smallest set of artifacts that fully specifies the change, then encode the customer’s standards so the model edits the way their team would.
What to include, what to leave outcuration, not collection
The files the change lives in, plus their direct call sites.
Type definitions and interfaces the edit must satisfy.
A failing test or the exact error - the tightest spec there is.
The relevant conventions (naming, error handling, imports).
Generated files, lockfiles, vendored code.
Distant modules the change never touches.
Whole-repo dumps “just in case.”
Stale comments and dead code that mislead the model.
Encode the team’s standardsrules / .cursorrules as a workflow artifact
A customer’s conventions are part of the spec, not a nice-to-have. Cursor lets you commit rules (the .cursorrules lineage) so every agent run inherits the team’s standards without you restating them in each prompt.
# Stack & conventions - Backend: Python 3.12, FastAPI. Frontend: TypeScript, React. - Use the repo's `Result` type for fallible calls; never raise across module boundaries. - All new endpoints get a pytest test and an OpenAPI entry. # Editing rules - Match existing import ordering; do not reformat untouched lines. - Prefer small, anchored edits over rewriting whole files. - If a public type changes, update its callers in the same change.
Conventions in a committed rules file are reviewable, diff-able and shared across the whole team’s agent runs.
That turns “the model keeps using the wrong logger” from a recurring prompt fix into a one-line PR.
Pin behavior with golden examplesmaking prompts evaluable
A few in-context examples of a correct edit do more than paragraphs of instruction. They also make the workflow measurable: when behavior is pinned by concrete examples, you can build an eval set around those same cases and detect regressions.
- Show one or two golden examples: input code, the exact edit you’d accept and why.
- Keep examples close to the real task distribution, not toy snippets.
- Hold the temperature low for code edits so the same context yields stable output you can evaluate.
Dumping the whole repo doesn’t add safety; it dilutes attention and invites edits to files you never meant to touch.
If you can’t name why a file is in context, it shouldn’t be there.
The cost of richer contextbudget it deliberately
More context usually means better edits, but every token added is latency and money on every call in the loop. Decide the context budget per workflow before production, the same way you’d decide a memory budget - not as an afterthought when the bill lands.
Mind the context window: the 50-65% rulethe most quantified craft rule
Output quality drops steeply as the window fills - noticeably by 70-80%, badly before 90%. The working guidance converges on staying under roughly 60-65%, and several heavy users start a fresh agent at ~50%. The bottom-right fullness indicator shows how full the window is and its makeup: the system prompt should stay small and the conversation should dominate. If you’re already 50% full before you send a prompt, that’s a warning sign you’ve loaded too many tools or plugins.
Exceed the limit and Cursor compacts - it compresses prior context. The trap: a compacted run can behave like it never had that context at all, while you still pay for all the tokens.
Don’t ride the window to the edge. Start a fresh agent for any logically new feature, and when a long run nears full, ask the agent to summarize what it’s done and hand that small summary to a new agent - the codebase and commits, not the chat back-and-forth, are the real source of truth.
Vague (“what color is the badge?”) forces the agent to search the whole app. @-mentioning the exact file guarantees it lands in context instead of relying on semantic search - the model reads that file, finds the definition and returns the right hex code. Night-and-day efficiency and accuracy.
@ isn’t limited to files: link docs, and reference a past chat to inherit its summary (Cursor summarizes the prior transcript) without carrying all of that context forward.
The anti-pattern: “make the app better” on the biggest modelvague + expensive = a compounding cost loop
The canonical thing not to do is a vague prompt on the most expensive model. With no clear context the agent makes blind, random edits, burns tokens, then burns more reading and fixing the bad code it just wrote - a compounding cycle. Vague prompts cost more and lower quality; specific, file-referenced prompts cost less and produce better output.
“Make the app better.” - on a frontier reasoning model.
No surface, no change, no constraints.
Blind edits → read/fix → more tokens, on repeat.
“Under the shop page, add an in-stock filter next to the existing tag and sort controls.”
“Preserve the URL query params and update tests if needed.”
Names the surface, the exact change and the constraints.
“I’d start from the failing test and the two files it exercises, @-mention them so they’re guaranteed in context, attach the team’s rules file for conventions and add type defs only where the edit crosses an interface. I keep the window under ~60-65% - if quality is still short, I add context one artifact at a time and watch the eval, rather than dumping the package up front and triggering compaction.”
Takeaway. Context is the lever: a curated set of the right files, types, tests and conventions beats a giant dump that drowns the signal.
Self-check
RAG and code-context retrieval
After this you can ground an agent in a large codebase via retrieval.
You can’t fit a million-line repo in the context window, so you retrieve the slice that matters.
Retrieval-augmented generation for code is how an agent stays grounded in a codebase too large to read whole. The pieces are an index, a retrieval step that pulls relevant code and the generation that edits it. The quality of the second piece sets the ceiling for the third.
Indexing a repochunking, embeddings, freshness
- 1Chunk along structure. Split on functions, classes and symbols, not arbitrary character counts that cut a function in half.
- 2Embed each chunk. Turn chunks into vectors so semantically related code is findable even without a keyword match.
- 3Store with metadata. Keep file path, symbol name and line range alongside each vector so a hit is actionable.
- 4Keep it fresh. Re-index changed files on save or commit; a stale index quietly retrieves code that no longer exists.
If the index lags the working tree, the agent edits against code that moved or was deleted and the failure is silent.
Tie re-indexing to file changes and treat index freshness as a metric you can watch.
Retrieval that respects code structurebeyond text similarity
Plain text similarity finds code that reads alike. Code retrieval needs more: the function that calls this one, the type this signature depends on, the imports a change must update. Blend semantic search with structural signals from the symbol graph.
- Signal
- Embedding similarity
- Finds
- Code that’s semantically related to the query
- Misses on its own
- Exact call sites and import edges
- Signal
- Symbol / keyword search
- Finds
- Exact references to a function or type name
- Misses on its own
- Conceptually related but differently named code
- Signal
- Call graph / imports
- Finds
- Direct callers and dependents that must change together
- Misses on its own
- Distant-but-relevant logic
| Signal | Finds | Misses on its own |
|---|---|---|
| Embedding similarity | Code that’s semantically related to the query | Exact call sites and import edges |
| Symbol / keyword search | Exact references to a function or type name | Conceptually related but differently named code |
| Call graph / imports | Direct callers and dependents that must change together | Distant-but-relevant logic |
Production code retrieval combines these; any one alone leaves blind spots.
When RAG helps vs. when it doesn’tmatch the strategy to the task
Large repo, change is local.
Question spans scattered files.
Best default for big codebases.
Edit is confined to one or two files.
Files fit comfortably in budget.
Skip retrieval; just attach them.
Repo is small.
Change touches everything.
Cheaper to include than to retrieve.
Evaluate retrieval on its owndon’t blame the model for a bad fetch
If you only measure final edits, you can’t tell whether a bad result came from the model or from never giving it the right file. Score retrieval independently before you judge generation.
- Build a set of queries with the chunks a human says should come back.
- Measure recall: did the must-have files land in the top-k results?
- Track precision so you’re not flooding the window with near-misses that cost tokens.
- When generation is wrong, check the retrieved set first - often the file the model needed simply wasn’t there.
Cursor indexes the codebase so the editor and Agent can pull relevant files into context automatically.
When you deploy a workflow, you’re building on that retrieval layer, so “did we retrieve the right code” is a question you can answer with its index, not one you reinvent.
If a design question reaches “the agent gives wrong answers on a big repo,” split the problem out loud: is retrieval missing the file or is generation fumbling a file it had?
Proposing a retrieval eval before touching the prompt reads as production experience.
Takeaway. Retrieval over code works when it respects structure - symbols, imports, call graphs - and when you evaluate the retrieval step on its own, separate from generation.
Self-check
QYour agent keeps producing incorrect edits on a large repo. Before you touch the prompt or swap models, what should you check first and why?
Streaming, latency and cost engineering
After this you can make model-backed workflows fast and affordable enough to adopt.
A workflow nobody waits for and nobody can afford never gets adopted, no matter how good the output is.
Senior customer engineers adopt tools that feel fast and have a defensible bill. That makes streaming, model selection and token budgeting part of the engineering, not polish you add later.
Interactive diagram. Tab through its regions; each focused region shows its detail in the panel below.
Map each workflow on cost vs. quality, then commit to a model tier - there is no corner that wins all three.
Streaming and backpressuremake partial results usable
- Stream tokens as they generate so the user sees motion in hundreds of milliseconds instead of waiting for the whole response.
- Make partial output usable: render the diff as it forms so a reviewer can start reading before it finishes.
- Apply backpressure when the consumer is slower than the stream, so a fast model can’t flood a slow UI or a downstream tool.
async def stream_edit(req):
async for token in model.stream(req): # tokens as they arrive
await ui.send(token) # render incrementally
if ui.buffer_full(): # consumer can't keep up
await ui.drain() # wait before pulling moreMatch the model to the taskdon’t reach for the biggest by reflex
Always using the largest model is the most common waste in production LLM systems. Route by difficulty: a small model handles the easy bulk, a large model handles the hard tail.
- Task
- Rename a symbol, format, mechanical edit
- Tier
- Small / fast
- Why
- Deterministic enough that a small model nails it cheaply.
- Task
- Localized bug fix with a failing test
- Tier
- Mid
- Why
- Needs reasoning but is well-scoped by the test.
- Task
- Cross-cutting refactor or migration plan
- Tier
- Large
- Why
- Wide context and harder reasoning justify the cost.
| Task | Tier | Why |
|---|---|---|
| Rename a symbol, format, mechanical edit | Small / fast | Deterministic enough that a small model nails it cheaply. |
| Localized bug fix with a failing test | Mid | Needs reasoning but is well-scoped by the test. |
| Cross-cutting refactor or migration plan | Large | Wide context and harder reasoning justify the cost. |
Tiering by task is the single biggest cost lever in most workflows.
Caching, batching, prompt reusecut cost and latency together
- Prompt / prefix caching
- Reuse the cached prefix (rules, system prompt, stable context) so repeated runs only pay for the new tokens.
- Result caching
- Identical input + revision returns the prior result instead of re-calling the model.
- Batching
- Group independent calls (e.g. one per file in a refactor) to amortize overhead and raise throughput.
Token budgetingmeasure before you ship
You can’t defend a cost you never measured. Instrument tokens per task during the build, then set a ceiling so a pathological input can’t quietly 10x the bill in production.
Log input and output tokens per task and watch the p50 and p95, not just the average.
Set a per-task ceiling that aborts or downgrades the model before spend runs away, the same way you cap steps in the loop.
Optimize for the right tokens, not the fewesttrue efficiency = efficiency × quality
Cheapest-per-token is the wrong target. A token-cheap model that needs 100 re-prompts isn’t efficient, and a model that one-shots a trivial feature while burning a billion tokens isn’t either. Tokens map straight to dollars - each model has distinct input/output/cached rates - so small inefficiencies compound at scale, but the goal is good hygiene that happens to produce cost efficiency and a better experience. Don’t penny-pinch the per-prompt cost; spend the right tokens on the right step.
The flagship loop: use your smartest thinking modelA reasoning model (shown with a brain icon in Cursor's picker) that spends extra compute before answering; reach for it on complex, nuanced work and a standard model for fast, simple tasks. (Opus, GPT-5.5, Codex 5.3) in Plan modeA mode that makes no edits: it researches the codebase and produces an editable plan you review before any code changes. to generate and validate a plan, then hand the to-dos to a cheaper, faster coding model (ComposerCursor's own fast coding model, tuned for the editor and priced well below frontier models; the recommended day-to-day model for executing a plan.) to execute.
Letting the frontier reasoning model write all the code burns the token budget fast - you don’t need it once the plan exists. Planning is itself token-efficient because the frontier model only reasons, it doesn’t output the whole implementation.
Cursor isn’t a desktop app piping your prompt straight to the provider. A proprietary cloud harness does optimization, context enrichment, caching and compaction, tuned per frontier model.
Via dynamic context discoveryThe agent pulling only the relevant parts of files, tools and MCP servers into context as needed, instead of loading everything up front. plus caching, the harness reduces agent tokens by roughly 47% - even on other vendors’ models - so the same model can perform better here than in a thinner harness. When you cost a workflow, that reduction is already baked in.
The quality / latency / cost trianglepick two, on purpose
Big model, rich context, streamed.
You pay for it.
Fits a high-stakes interactive edit.
Big model, batched, run offline.
Slower per item.
Fits an overnight migration.
Small model, tight context.
Lower ceiling on quality.
Fits high-volume mechanical edits.
When a system-design question asks you to make a workflow “fast and cheap,” name the triangle and pick two on purpose for that specific workflow.
Then defend the third: “for an overnight migration I trade latency for quality and cost, batched on a large model, because nobody is watching the clock at 3am.”
Takeaway. Pick two of quality, latency and cost per workflow and defend it; stream output, match model tier to task and set a token ceiling before production.
Self-check
Large-scale code transformation
After this you can plan a safe automated refactor or migration across a big codebase.
Automating a 4,000-file migration is easy. Automating it without breaking production is the actual job.
Large-scale transformation - a framework migration, a language upgrade, an API swap - is where an FDE earns trust or loses it. The model can generate the edits; you own the safety. The plan, the gates and the metrics are the deliverable.
Big-bang vs. incrementalalmost always incremental
- Approach
- Big-bang (one PR)
- Blast radius
- Entire codebase at once - hard to review, hard to revert cleanly
- When it’s defensible
- Tiny repos or a mechanical change with full test coverage
- Approach
- Incremental (file-by-file / module-by-module)
- Blast radius
- One slice per change - each independently reviewable and revertible
- When it’s defensible
- The default for any serious codebase
| Approach | Blast radius | When it’s defensible |
|---|---|---|
| Big-bang (one PR) | Entire codebase at once - hard to review, hard to revert cleanly | Tiny repos or a mechanical change with full test coverage |
| Incremental (file-by-file / module-by-module) | One slice per change - each independently reviewable and revertible | The default for any serious codebase |
- 1Pilot on one slice. Migrate a representative module by hand or supervised and capture the exact recipe.
- 2Encode the recipe. Turn it into the agent’s instructions plus a rules entry so every batch follows the same pattern.
- 3Roll out in batches. Process a bounded set of files per change so a reviewer can actually read the diff.
- 4Gate every batch. No batch merges until it passes the verification gates below.
- 5Track and report. Update the metrics after each batch so the customer sees progress and risk in real time.
Interactive diagram. Tab through its regions; each focused region shows its detail in the panel below.
Each batch is a separate revertible PR; the verification gate is the product, not a formality.
AST-aware vs. free-text editsknow when each is safe
Edits the parse tree, so output is syntactically valid by construction.
Best for mechanical, structural changes: rename an API, change a call signature.
Deterministic and reviewable; pair with the model to decide where to apply it.
The model rewrites code as text - flexible but can produce subtly invalid output.
Best where judgment is needed: idiomatic rewrites, restructuring logic.
Always gate behind compile/type/test checks; never trust the diff on faith.
Interactive diagram. Tab through its regions; each focused region shows its detail in the panel below.
Many migrations use both - AST for the structural skeleton, the model for the parts that need taste.
Pure mechanical transforms lean AST: it can’t produce broken syntax. Judgment-heavy rewrites lean model, gated hard.
Many migrations are both - AST for the structural skeleton, the model for the parts that need taste.
Verify every changethe gates that earn merge
- Compile / type-check
- The change must build and type-check before it’s eligible to merge.
- Tests
- Run the affected suite; a batch with new failures is blocked, not merged with a note.
- Diff review
- A human reads the batch diff - small batches make this real rather than rubber-stamped.
- Lint / format
- Enforce the repo’s style so the migration doesn’t add noise to every future diff.
Rollback and blast-radius controlbe able to undo fast
- Keep each batch a separate, revertible commit or PR so a bad slice is one
git revertaway. - Where feasible, gate the new path behind a flag so you can disable it in production without a redeploy.
- Define the blast radiusHow much breaks if a change goes wrong; the scope of potential damage. before you start: how many files, which services, what’s the worst case if a batch is wrong.
A migration that merges failing changes with a TODO is how you hand the customer a slow-motion outage.
The gate is the product. If a batch can’t pass, it stays out until it can.
Measuring successthe metrics a customer will trust
- Metric
- % migrated
- What it tells the customer
- Concrete progress against the total - the burn-down they can watch.
- Metric
- Defects introduced
- What it tells the customer
- Bugs or regressions traced to the migration - the honest cost.
- Metric
- Reviewer time saved
- What it tells the customer
- Hours the automation removed vs. doing it by hand - the ROIReturn on Investment. The value gained versus what it cost, the language an economic buyer funds deals in..
- Metric
- Rollbacks / reverts
- What it tells the customer
- How often a batch had to be undone - the stability signal.
| Metric | What it tells the customer |
|---|---|
| % migrated | Concrete progress against the total - the burn-down they can watch. |
| Defects introduced | Bugs or regressions traced to the migration - the honest cost. |
| Reviewer time saved | Hours the automation removed vs. doing it by hand - the ROIReturn on Investment. The value gained versus what it cost, the language an economic buyer funds deals in.. |
| Rollbacks / reverts | How often a batch had to be undone - the stability signal. |
Report these proactively. A customer trusts the engineer who shows defects introduced, not the one who hides them.
“I’d pilot the migration on one module to nail the recipe, encode it as agent instructions plus a rules entry, then roll out in 20-file batches. Every batch has to type-check, pass the affected tests and get a human diff review before merge and each is a separate revertible PR. I’d report percent migrated, defects introduced and reviewer hours saved each week, so the customer sees both the progress and the cost.”
What this looks like at real scalegrind mode and cloud agents on big repos
For the longest, hardest transformations, Cursor’s grind-until-done mode (in beta) lets a cloud agent grind for hours - or as long as needed - on work like a big migration or a from-scratch build. Most jobs don’t need it: toggling a cloud agent on and asking “implement this feature” already does well. Reserve grind mode for the genuinely long horizon, and don’t overuse it.
Dependency-manager migration run as one long autonomous job.
Mechanical and repo-wide - the kind of recipe you pilot once, then batch.
A library/version upgrade across the codebase.
AST-aware for the call/signature changes, model only where judgment is needed.
A researcher built a Chrome-level browser across thousands of commits in grind mode.
The from-scratch end of the long-horizon spectrum.
Demoed on Grafana - roughly 2 million-plus lines and 30,000 files - enabled by sub-agents and semantic indexing, so the agent never tries to read the whole tree at once.
Given only a ticket id (GRAPH-59) plus scope and acceptance criteria, the agent figured out how to test the feature itself and shipped in about an hour what an experienced engineer had estimated would take weeks. For slow repos like Grafana, save the built environment as a team snapshot so new agents start from it instead of rebuilding.
Takeaway. Ship migrations incrementally behind verification gates - tests, types, diff review - and report the metrics a customer trusts: percent migrated, defects introduced, reviewer time saved.