How to Optimize AI Agent Cost and Latency
Where agent cost and latency actually come from, the concrete levers to pull, and how to measure before you optimize the wrong thing.
An agent that costs $8 and four minutes to close a ticket isn't automatically too expensive
— it might be doing exactly the right amount of work. The mistake is optimizing before you know where the money and time are going. This piece covers where cost and latency come from in an agent loop, the levers that actually move them, and how to measure so you fix the real bottleneck instead of guessing. It assumes you already have a working agent loop — if not, start with how to build your first AI agent.
Where the cost and latency actually come from
A single LLM call is cheap and fast to reason about. An agent is a loop of them, and the loop is where cost and latency compound:
- Iterations multiply the base cost. Every tool-call round trip is another model request — an agent that takes 8 turns pays for 8 requests' worth of input processing, not one.
- Context grows every turn. Each tool result and prior message gets appended and resent on the next call. By turn 10, you're reprocessing everything from turns 1–9, even if the model only needs the last two.
- Output tokens are the expensive kind. Output tokens cost several times more per token than input across providers. Verbose reasoning and chatty status updates between tool calls add up fast.
- Tool round-trips are serial by default. If the model calls a tool, waits, then calls another, each round trip adds full network and inference latency — three independent lookups run one after another cost three round trips instead of one.
None of this is exotic — it's the direct consequence of loop that resends growing context and waits on I/O,
which is what most agents are under the hood. Attack each piece specifically rather than reaching for one knob.
The levers that actually work
Prompt caching
The single highest-leverage lever for both cost and latency is reusing a stable prompt prefix instead of reprocessing it every turn. Providers that support prompt caching let you mark a prefix — a system prompt, tool definitions, a large document — so repeated requests sharing that exact prefix are billed and processed at a steep discount, often on the order of a 90% reduction for the cached portion, with a corresponding drop in time-to-first-token.
Caching only pays off if the prefix is genuinely stable: same tools, system prompt, and model, in the same order, request after request. Any change upstream of your cache boundary — a timestamp in the system prompt, a reordered tool list — invalidates it. For placement patterns and the failure modes that silently break caching, see prompt caching: how to cut LLM cost and latency.
Model selection and routing
Not every step needs your most capable model. Classifying a ticket or deciding does this need a tool call
is a different job than planning a multi-step refactor. Routing easy steps to a smaller, cheaper, faster model and reserving the frontier model for steps that need real judgment is one of the most direct ways to cut both cost and latency.
Route statically by step type (if you already know a step is classification or formatting, hardcode it to the cheap model) or dynamically via a cheap upfront classifier that estimates task complexity and picks the model for the rest of the turn — a lightweight classifier adds negligible latency, a heavier model-based one more.
Watch the failure mode: routing too aggressively to a weak model produces wrong output that goes unnoticed or triggers a retry on the expensive model anyway — now you've paid for both calls and gained nothing.
Reduce the number of turns
Every turn is a full round trip, so the fastest way to cut latency and cost together is to need fewer of them: give the model everything it needs to act in one shot instead of a clarifying-question-then-act cycle, prefer tools that return exactly what's needed over ones that return a firehose the model has to re-query, and let the model batch several actions into one tool call (update these five records
) instead of one call per record where the workflow allows it.
Trim and compact context
Since every turn resends the accumulated conversation, a long-running agent accumulates dead weight — stale tool results, exploratory reasoning no longer relevant, verbose logs. Periodically summarizing or dropping that content keeps each request's input smaller, which is cheaper and faster independent of caching. It does work somewhat against caching (a compacted prefix is a new prefix), so the balance depends on run length: short-lived agents usually don't need it, long-running ones usually do. For a broader look at managing what's in context versus reaching for a tool or more context window, see RAG vs. tools vs. long context.
Run independent tool calls in parallel
If a turn requires three independent lookups — inventory, a customer record, a shipping estimate — running them serially pays the full latency of each, one after another. Running them concurrently collapses that to roughly the latency of the slowest single call. This only applies when the calls are genuinely independent; dependent calls still run in sequence. Most tool-calling APIs let a single model turn request multiple tool calls at once specifically so the caller can execute them in parallel.
Stream for perceived latency
Total completion time and perceived latency aren't the same thing. Streaming the response as it's generated lets a user see the first words within a second or two even if the full answer takes much longer — it doesn't reduce actual cost or compute time, but it's close to free to implement and meaningfully changes how slow an agent feels.
Batch where you can tolerate latency
For workloads that don't need a real-time response — nightly reports, bulk classification, backfilling data — batch processing APIs trade turnaround time (often hours) for a substantial per-token discount. If nothing's waiting on the result, this is close to free money.
Cap max tool iterations
Agent loops can run away — a model that keeps calling tools without converging, or gets stuck retrying a failing action. A hard ceiling on iterations, with a defined fallback when it's hit (return partial progress, escalate to a human, fail explicitly), bounds worst-case cost and latency. It's a safety net more than an optimization, but an agent without one has no upper bound on either.
Measure before you optimize
Every lever above targets a specific bottleneck — if you don't know which one you actually have, you'll optimize the wrong thing. At minimum, instrument each run with: tokens in vs. out (and cache-read vs. cache-write vs. uncached) per turn; turns and tool calls per completed task; wall-clock latency broken into model-inference vs. tool-execution vs. network time; and cost per completed task, not just per API call — a cheap model needing three retries can cost more than an expensive model that succeeds once.
A quick per-task breakdown sketch, even a rough one, usually reveals the real problem fast:
Task: "summarize and file this support ticket"
Turn 1 model=cheap in=1.2k (0.9k cached) out=80 0.3s
Turn 2 model=cheap in=1.4k (1.1k cached) out=120 0.4s
Turn 3 model=frontier in=2.1k (1.1k cached) out=650 4.1s <- bottleneck
Turn 4 model=cheap in=2.9k (2.6k cached) out=40 0.3s
--------------------------------------------------------
total: 4 turns, ~7.6k tokens in / 890 out, 5.1s wall-clock
In this sketch, turn 3 dominates both cost and latency — a single frontier-model call producing a long output. That tells you exactly what to attack next: does that step actually need the frontier model, or would a lower effort setting or a cheaper model do just as well? Without the breakdown, you'd be guessing between caching, routing, and parallelism when only one is the real bottleneck for this task shape.
The tradeoffs are real
Every lever here trades something. A cheaper, faster model makes more mistakes on hard tasks, meaning more oversight, retries, or human review downstream — savings on the model call can get eaten by the cost of catching what it got wrong. Aggressive context trimming can drop information the model needed later. A tight iteration cap can cut off a task one step from finishing. None of this means don't optimize — it means treat cost, latency, and quality as three dials you're balancing, not one number to minimize. The right setting depends on what the task is worth and how much unsupervised failure you can tolerate; a customer-facing chat response and an overnight batch job don't belong on the same settings.
Start from measurement, fix the actual bottleneck, and re-measure. That loop is the whole optimization process — everything else here is just the list of levers to reach for once you know which one you need. For the architecture that produces the loop you're optimizing in the first place, see how to build your first AI agent.