Estimating Client Work When Agents Do the Building

Agent-era velocity is bimodal: the same feature can take 20 minutes or 3 days. How I scope, bill, and talk to clients about it honestly.

TL;DR: Story points and velocity math were built for a world where effort was roughly continuous — a medium ticket took roughly medium effort, every time. Agents broke that assumption. The same feature can be twenty minutes of agent work or three days of agent-debugging, and you can’t always tell which one you’re in until you’re in it. My fix isn’t a smarter estimate — it’s a different contract. I quote ranges instead of points, bill milestones instead of hours, and I’m honest with clients about where the variance actually lives: not in the typing, which compressed, but in the review, integration, and verification that didn’t. What you’re pricing now is judgment and blast-radius control, not code output — and the sooner you say that out loud to a client, the fewer awkward invoices you have to explain later.

The SOW doesn’t know what a “medium feature” means anymore

A client asks how long the integration will take and what it’ll cost. I used to have an honest answer built from years of pattern-matching: a CRUD resource with auth and three states is a day and a half, a webhook-driven sync job is three days, a multi-tenant billing change is two weeks and I want a second engineer’s eyes on it. That pattern-matching still works for scope. It stopped working for time, because time is no longer a stable function of scope.

I’ve written before about running an agent-heavy workflow on my own project — 4,154 commits in six months, more than my previous four years combined. The velocity is real. It’s also wildly uneven in a way that a client-facing estimate has to account for or it becomes a lie by omission. A feature that looks identical on the ticket — same acceptance criteria, same rough size — can take an agent twenty minutes to produce a correct, tested implementation, or it can take three days of the agent confidently generating something that’s subtly wrong against a part of the codebase it didn’t have full context on, me catching it, redirecting it, and doing that loop four more times. Same-sized ticket. An order-of-magnitude difference in time. That’s not an estimating error I can train away with more experience — it’s the actual shape of the work now.

This isn’t just my anecdote. METR ran a randomized controlled trial with experienced open-source developers in 2025 and found that when they used current AI coding tools on real tasks in codebases they knew well, they took 19% longer to finish — despite forecasting a 24% speedup going in, and despite still believing, after the fact, that AI had made them faster (METR, 2025). That gap between felt velocity and measured velocity is exactly the trap a fixed-price estimate falls into if you quote off vibes. The variance is real, it’s directionally unpredictable at the ticket level, and both the agent’s output and your own sense of how fast you’re moving will mislead you if you let them.

There’s an active discourse in the agile press about the mechanics of this at the team-process level — Scrum.org has argued that story points don’t map cleanly onto autonomous agents because agents don’t experience effort, fatigue, or uncertainty the way the point system was built to measure, and Agile Insider has proposed treating agent throughput as a separate parallel capacity budget rather than folding it into team velocity. That’s a real and useful conversation if you’re running internal sprint ceremonies. It’s not this post. I’m not trying to fix your standup. I’m trying to answer a narrower, more expensive question: how do you write a Statement of Work, a milestone schedule, and an invoice for a client when you genuinely don’t know in advance which end of that variance a given feature will land on.

Ranges instead of point estimates

The first mechanical change is refusing to give a client a single number for anything above trivial scope, and saying why out loud instead of hedging silently.

I quote a range — low estimate assumes the agent nails it on the first or second pass and I’m mostly reviewing and integrating; high estimate assumes at least one full detour where the agent’s confident output turns out to be wrong against something it didn’t have context on, and I have to catch it, redirect, and re-verify. For most feature-sized work that range runs somewhere between 2x and 4x, not the 20-30% pad I used to build into hand-written-code estimates. That’s a bigger spread than clients are used to seeing, and the instinct is to round it down to look confident. Don’t. A confident wrong number costs you the relationship the first time you blow through it; an honest range costs you nothing but a slightly less impressive-looking proposal.

The range isn’t hedging. It’s the most honest number I can give you, because the honest answer is a distribution, not a point.

What I don’t do is quote the range and then go silent about which end we’re tracking toward. Once work starts, I tell the client within the first day or two of a milestone whether we’re running toward the low end or the high end, and roughly why — “the agent handled the core flow cleanly, we’re tracking low” or “we hit a data-shape the agent didn’t expect and I’m doing a manual pass on three files before I trust them, we’re tracking toward the high end.” That’s a five-minute Slack message. It converts a range that could look like padding into a range that’s clearly grounded in what’s actually happening in the work.

Bill milestones, not hours

The second change is where the money actually attaches. I’ve mostly moved off pure hourly time-and-materials billing for agent-heavy engagements, for a reason that has nothing to do with client trust and everything to do with the fact that hours stopped meaning what they used to mean. An hour of my time on a ticket that goes smoothly might be twenty minutes of prompting and review. An hour on a ticket that goes badly is genuinely an hour of debugging. Billing both the same way either overcharges the client on the easy ticket or undercharges me on the hard one, and neither error is visible to the client in real time — they just see a line item.

Milestone-based billing sidesteps that. I define a milestone as a demonstrable, working outcome — “the integration flow live in staging, all three of its paths tested” — not a time box, and price it against the range I quoted, not against logged hours. The client pays for the outcome; I absorb the variance inside the range I already flagged; and if a milestone runs consistently toward the high end across a project, that’s the signal to renegotiate scope or price going forward, in the open, rather than a signal I quietly eat by working unpaid hours or a signal the client discovers as an inflated final invoice. Time-and-materials isn’t gone from my toolkit — it’s still the right call for genuinely exploratory work where even the scope is uncertain, which I’ll get to below — but for defined feature work, milestones are the honest unit now because they’re the unit the client actually cares about.

The part that didn’t compress

Here’s the part of this that a lot of agent-era pricing conversations skip, because it’s less exciting than the productivity story: not everything got faster, and pricing has to reflect that split honestly.

The 2026 AI Engineering Report, cited in Faros AI’s research, found that under high AI adoption, median time to first PR review is up 156.6%, average time spent in review is up 199.6%, average PR size is up 51.3%, and bugs found per PR are up 54% (Faros AI, 2026). I’ve cited that stat before writing about what a performance review has to measure now that commit volume is agent-inflated, and it applies just as directly here: the generation step compressed hard, and the review, integration, and verification steps didn’t compress at all — they got more expensive, because there’s more volume to review, the code is stylistically clean enough that bugs hide behind good formatting, and the reviewer has to actually understand the logic every time instead of pattern-matching on ugly code as a tell.

That’s the part of my estimate that still looks like the old estimate. Reviewing a generated diff for correctness against business logic the agent didn’t fully have, tracing an integration point through a system the agent only saw one file of, deciding whether a change is safe to ship to production without breaking three other paths that share the same code — none of that got faster, because none of that was ever bottlenecked on typing speed. It was always bottlenecked on judgment, and judgment doesn’t compress just because the draft arrives faster. If I quote a client a number that assumes the whole feature moves at generation speed, I’ve quietly promised them a review-and-verification pass that doesn’t exist, and the gap shows up as either a missed deadline or a corner cut on the pass that catches the expensive bug.

Fixed-bid vs. time-and-materials, reconsidered

The old rule of thumb was: fixed-bid when scope is well understood and the risk is mine to manage, time-and-materials when scope is genuinely unknown and the client should share that risk. That rule still holds, but the inputs to “well understood” changed.

Scope being well understood used to mean I’d built something like it before and could estimate the hand-written effort with confidence. Now it has to mean something narrower: I’ve built something like it before with an agent, in a codebase with similar shape, and I have a real sense of where that specific kind of feature tends to land in the variance — closer to the twenty-minute end or closer to the three-day end. That’s a much smaller set of things I’ll fixed-bid confidently than it used to be, because the agent-era track record on any given feature type is younger than my hand-written track record was.

For genuinely novel integration work, unfamiliar third-party APIs, or anything touching a part of the client’s system I haven’t worked in — the places where an agent is most likely to confidently produce something wrong because it’s inferring conventions instead of following ones it’s seen — I lean time-and-materials with the milestone framing layered on top: bill against demonstrated progress, not raw hours, but don’t pretend I can fix-bid a number I genuinely don’t trust yet. Fixed-bidding scope I can’t confidently place in the variance range isn’t confidence, it’s a bet I’m making with the client’s budget instead of my own, and I don’t like that trade even when I’d probably win it.

What the estimate is actually pricing

The honest reframe, the one I try to say plainly to a client rather than leave implicit in the invoice, is that the thing being priced changed. It was never really pricing typing speed — that was always a rough proxy — but it’s an especially bad proxy now, and pretending otherwise is the fastest way to either underprice yourself or overpromise a client.

What a client is actually paying for in an agent-heavy engagement is judgment about what to build and what not to, the review discipline to catch the plausible-looking wrong answer before it ships, and blast-radius control — the discipline of knowing which change is safe to let run wide and which one needs a narrower, more careful path because the failure mode is expensive. I’ve written about that same blast-radius framing from the inside of my own project: shipping faster means shipping more surface area, and more surface area means more that can break at 2am, which is exactly the argument I make in why AI won’t shrink your team — the velocity doesn’t remove the need for the people who catch what it breaks, it raises the stakes on them. When I quote a client, that’s the labor the number is actually covering, whether or not I say so. Saying so is the difference between a client who understands what they’re buying and one who thinks they’re buying code by the pound.

It’s also, not coincidentally, close to the same lens an investor’s technical reviewer applies during diligence — reading commit history for who’s actually exercising judgment rather than who’s generating volume, a pattern I’ve laid out in surviving technical due diligence as an AI founder. Clients doing diligence on a contractor and investors doing diligence on a founding team are asking a version of the same question: is the judgment real, or is the output just volume dressed up as progress.

Say the quiet part to the client

The uncomfortable option, and the one I think a lot of consultants are quietly taking right now, is pocketing the variance. Quote the old hourly rate, let the easy tickets run fast and profitable, eat the hard tickets’ extra hours without mentioning it, and let the average work out in your favor over enough projects. It’s not fraud, exactly. It’s also not the operating system I run the rest of my practice on, and clients notice the difference between a consultant who explains the shape of the risk up front and one who lets them find out the hard way.

I’ve written elsewhere about running teams — and agents — on trust as the actual operating system rather than the process artifacts stacked on top of it. The client relationship runs on the same substrate. Telling a client “this range is wide because the work is genuinely bimodal now, here’s why, and here’s how I’ll keep you posted on which end we’re tracking toward” costs you a slightly less polished-looking proposal in the first meeting. It buys you a client who doesn’t feel ambushed by the invoice on the milestone that ran long, and who trusts the next range you quote them because the last one held up. That trade is not close.

If you’re scoping an agent-heavy engagement

If you’re staffing or scoping work where agents are doing a meaningful share of the building — whether you’re the one hiring the consultant or the one writing the SOW — this is exactly the kind of thing worth walking through before the contract is signed rather than after the first milestone slips. Let’s talk about how the engagement should actually be structured.