Give an AI Coding Agent a Fast Feedback Loop
An agent working in a repository where the checks take eleven minutes is not a slow agent. It is an agent that gets eleven minutes of blindness after every edit.
Give an AI Coding Agent a Fast Feedback Loop
An agent working in a repository where the checks take eleven minutes is not a slow agent. It is an agent that gets eleven minutes of blindness after every edit, and blindness is where the expensive failures come from. It guesses instead of checking, it stacks three speculative changes into one run, and when something breaks it has no idea which of the three did it.
The fix is not a faster model. It is a check the agent can run in under a minute that tells it whether it just broke something. Everything below is about building that.
The arithmetic that makes this worth an afternoon
Take a task that needs eight verify-and-adjust cycles, which is ordinary for a non-trivial change.
Full check time | Time spent waiting across 8 cycles | What the agent does about it |
|---|---|---|
40 seconds | 5 minutes | Checks after every edit |
3 minutes | 24 minutes | Starts batching edits |
11 minutes | 88 minutes | Runs the suite twice, guesses the rest |
The second column is the obvious cost. The third column is the real one. Once a check is slow enough that the agent avoids running it, you have lost the mechanism that made agent-written code reviewable in the first place, and you are back to reading diffs on trust.
There is also a direct bill. If your agent runs in a cloud sandbox, the meter runs during those eleven minutes while the model does nothing at all.
Step 1: define one command that is the fast check
Most repositories have no answer to "what should I run to know I did not break anything, quickly". The agent then invents one, usually the slowest possible option.
Add a single entry point. The name matters less than the fact that it is one command with a stable name.
# package.json
"scripts": {
"check": "tsc --noEmit && eslint --cache src && vitest run --changed"
}# Makefile
check:
ruff check . && mypy app && pytest -m "not slow" -qBudget: under 60 seconds on a warm cache. If it cannot be, the rest of this article is how to get it there.
Step 2: split the suite by cost, not by folder
The usual reason a suite is slow is that a small number of tests do real work: network calls, container startup, database migrations, browser automation. They are worth having and they do not belong in the loop the agent runs after every edit.
Mark them and exclude them by default.
# pytest: mark and skip by default
@pytest.mark.slow
def test_full_checkout_flow(browser):
...pytest -m "not slow" -q # the fast check
pytest -q # everything, before a PRVitest and Jest have the same shape through project or tag configuration, and the Jest CLI docs cover the filtering flags. The pytest documentation on markers covers the Python version.
A rough target: the fast tier should be at least 80 percent of your assertions and under 20 percent of your runtime. If a handful of tests own most of the clock, that is a good afternoon's work regardless of agents.
Step 3: make the check incremental
Running everything after a one-line change is waste that compounds. Three levers, roughly in order of return:
Type check without emitting.
tsc --noEmitis much faster than a build and catches the largest single class of agent mistake, which is calling something that does not exist with arguments it would not accept.Lint with a cache.
eslint --cacheandruffboth skip unchanged files. Ruff in particular turns a multi-second step into a sub-second one.Test only what changed. Vitest has
--changed, Jest has--onlyChanged, and pytest has--testmonvia a plugin. These use different notions of "related", so verify the selection is not silently empty on your repo before you trust it.
Step 4: tell the agent the command exists
An agent will not use a script it does not know about. Put the command in the instruction file the agent reads, along with the rule about when to run it. If you do not have one yet, how to write an AGENTS.md file covers the format.
The wording that works is specific and imperative:
## Checks
Run `npm run check` after every edit that touches src/. It takes about 35 seconds.
Do not batch multiple unrelated edits before running it.
Run `npm run check:full` once before opening a pull request. It takes about 9 minutes,
so do not run it during iteration.Two details do most of the work here. Stating the runtime lets the agent make a sensible decision about batching. Stating explicitly that the slow one is for the end stops it from running the expensive command out of caution.
Step 5: make failures readable in one screen
A fast check that produces 400 lines of output is not fast, because the agent now spends tokens and attention parsing it, and long outputs push the actual error out of the useful part of the context window.
Use quiet or dot reporters for the fast tier.
pytest -q,vitest run --reporter=dot.Fail fast during iteration.
pytest -x,vitest --bail=1. The first failure is almost always the informative one.Strip progress bars and spinners in non-interactive runs. They serialise into thousands of useless characters.
Keep stack traces short.
--tb=shortin pytest is usually enough to locate a fault.
The difference between a 12-line failure and a 400-line failure shows up as fewer wrong guesses, because the agent can hold the whole failure in view alongside the code it just wrote.
What good looks like afterwards
A reasonable end state for a mid-sized repository:
Tier | Command | Target | When |
|---|---|---|---|
Fast |
| under 60s | After every edit |
Full |
| under 10 min | Before opening a PR |
CI | pipeline | whatever it takes | On push |
The agent lives entirely in the first row. Everything else is a gate, not a loop.
The failure this prevents
Without a fast tier, the most common pattern is an agent that makes four changes, runs the suite once, sees three failures, and then starts changing tests instead of code, because the mapping from failure to cause has been lost. That specific pathology is common enough that we wrote about it separately in when an AI coding agent changes tests to make them pass.
The related trap is an agent that keeps re-running a check that fails for reasons unrelated to its change. If your fast tier contains anything flaky, remove it from the fast tier, then fix it. Prompting AI to fix a flaky test covers the fixing part, and agents stuck in a loop covers what it looks like when you do not.
Where all of this sits in the wider tooling picture is in our AI coding tools overview.
For a more structured take on the same idea, Warp Factories: agent pipelines you version control covers treating an agent's own working steps as version-controlled pipelines.
FAQ
How fast does the fast check need to be?
Under a minute is the threshold where agents reliably run it after every edit rather than batching. Under 30 seconds is better. The exact number matters less than it being fast enough that skipping it saves nothing.
Should the fast check include the type checker?
Yes, if you have one. Type errors are the most common category of agent mistake and the cheapest to catch, and tsc --noEmit or mypy on a warm cache is usually the fastest useful signal in the whole suite.
What if my test suite cannot be split?
Start with the type checker and linter alone as the fast tier. That is a worse signal than tests but still far better than an eleven-minute wait, and it gives you something to add to as you mark slow tests.
Does this matter for cloud agents too?
More, not less. Cloud sandboxes bill for compute time during test runs, so a slow suite costs money as well as iterations, and the sandbox usually starts from a cold cache.
How did this land?
About the author

Staff Engineer, Platform
Carlo works on the platform that turns prompts into running apps. He writes the engineering deep dives and the changelog notes worth reading.


