AI agents look simple at first.
You take a model, add a prompt, maybe connect a tool, and it works. It feels like you are just making one API call and getting an answer.
That illusion disappears the moment the agent starts doing real work.
In production, an agent is not one call. It is a loop. It may call the model multiple times, retrieve memory, execute tools, retry on failure, and refine its own output.
That is where cost shows up.
Not just in tokens, but in latency, complexity, and system load.
The mental model most people miss
Most tutorials present agents like this:
User → Model → Response
Real systems look more like this:
User → Runtime → Model → Tools → Memory → Validation → Model → Response
And that flow may repeat several times.
Each step adds cost.
Not just money. Time, complexity, and failure risk.
1. Token cost is not just one request
The first hidden cost is tokens.
Developers often assume a single request with a fixed prompt. In reality, an agent may call the model multiple times within one run.
For example:
- One call to decide what to do
- One call after retrieving memory
- One call after tool execution
- One call to generate the final response
Each call includes input tokens and output tokens.
If you also include memory retrieval, the prompt gets larger over time. That increases token usage even further.
A simple way to think about it:
const totalTokenCost =
(numberOfCalls) *
(inputTokens + outputTokens);
The problem is that numberOfCalls is not always predictable. It depends on how the agent behaves.
This is why cost can grow faster than expected.
2. Tool calls are not free
Tool usage is often treated as a free extension of the model. It is not.
Each tool call adds:
Network latency
External API cost
Failure scenarios
Additional model calls after execution
For example, a simple flow might look like:
Model decides → Call tool → Tool responds → Model interprets → Continue
Even if the tool itself is cheap, the surrounding orchestration is not.
In many cases, the cost of using a tool is not the tool itself, but the extra model calls and latency it introduces.
3. Retries multiply everything
Retries are where costs start to compound.
If a tool fails, the agent may retry. If the model returns invalid output, the system may retry. If validation fails, the system may retry again.
Each retry is not just one extra call. It repeats the entire step.
A simple retry loop might look like this:
for (let i = 0; i < 3; i++) {
try {
return await callTool(input);
} catch {
continue;
}
}
Now imagine this happening inside an agent loop.
One failure can lead to:
Multiple tool calls
Multiple model calls
Longer execution time
Retries are necessary, but without limits, they become expensive quickly.
4. Latency grows with each step
Latency is often underestimated.
Each model call takes time. Each tool call adds network delay. Each retry increases total execution time.
Even if each step is fast, the combined latency can be noticeable.
A simple breakdown:
Model call: 500ms to 2s
Tool call: 200ms to 1s
Memory retrieval: 100ms to 300ms
Now combine them across multiple steps.
An agent that feels “instant” in a demo can easily take several seconds in production.
This is not always a problem, but it becomes important for user experience.
5. Memory adds both value and cost
Memory is powerful, but it is not free.
Every time you retrieve memory, you add:
Query cost (vector search or database lookup)
Additional tokens (more context sent to the model)
Complexity in prompt construction
If memory is not filtered carefully, it can:
Increase token usage significantly
Add irrelevant context
Reduce model accuracy
The key is not more memory, but better memory.
Retrieve only what is relevant to the current goal.
6. Reflection and “thinking” steps increase usage
Many modern agent patterns include reflection.
The agent may:
Evaluate its own output
Re-plan its next step
Summarize intermediate results
These patterns improve quality, but they also add more model calls.
For example:
Model → Draft response
Model → Critique response
Model → Refine response
This can double or triple token usage.
Reflection is useful, but it should be used intentionally.
7. Cost is not just money
When people talk about cost, they usually mean API pricing.
In practice, cost also includes:
Latency. Slow agents reduce user experience.
System load. More calls mean more infrastructure usage.
Failure surface. More steps increase the chance of something going wrong.
Debugging complexity. More moving parts make issues harder to trace.
This is why cost should be treated as an architectural concern, not just a billing concern.
A simple way to think about it
If I had to simplify everything into one idea, it would be this:
Each new capability multiplies cost.
More tools → more calls
More memory → more tokens
More retries → more loops
More reasoning → more model usage
Agents do not scale linearly. They scale multiplicatively.
What actually works in practice
In real TypeScript systems, I try to keep things controlled.
Limit the number of steps. Do not let the agent run indefinitely.
Keep prompts small. Only include relevant context.
Use tools intentionally. Do not expose everything.
Set retry limits. Avoid infinite loops.
Track usage. Measure tokens, latency, and failures.
These are not optimizations. They are guardrails.
The real takeaway
AI agents are powerful, but they are not free abstractions.
Every decision you add to the system has a cost. Every layer adds complexity. Every retry multiplies usage.
The goal is not to remove these features. The goal is to use them intentionally.
A simple, controlled agent that solves a specific problem is often more valuable than a complex agent that tries to do everything.
Because in production systems, efficiency and reliability matter more than flexibility.
And understanding the hidden cost is the first step toward building something that actually scales.
Top comments (6)
One small thing on the
totalTokenCost = calls * (input + output)model though: it's actually optimistic, because input tokens aren't constant across those calls. Each loop usually carries the growing transcript plus fresh memory hits, so call number three is paying for calls one and two all over again. Closer to a sum of increasing inputs than one number times a count. Doesn't change your point, it just means the real curve is steeper than the formula suggests, which honestly makes the guardrails argument stronger.The retry section understates the nastiest failure mode: retries don't just multiply cost linearly, they interact with your context window. When a tool call fails and you retry inside the agent loop, a lot of frameworks append the error output and the failed attempt back into the conversation history. So retry #3 isn't running against the same prompt as attempt #1 — it's running against a bigger, dirtier context that now contains two prior failures, which makes the model more likely to fail again the same way. You get a doom loop where each retry costs more tokens and is more likely to need another retry.
The fix isn't just a retry cap. It's deciding what the retry actually sees. Retrying a transient network 500 should replay the original clean request; retrying a bad-model-output validation failure should include the error so the model can correct — but you almost never want to accumulate every prior failed attempt. Those are two different retry policies that people collapse into one
forloop, and the collapse is where the cost blows up. Worth adding a rule to your guardrails list: retries must be idempotent in context, not just bounded in count.The retry point is the one that bit us hardest. A failed step doesn't cost one more call — it re-runs the whole sub-loop, memory pulls and tool calls included, so the curve bends up fast. What helped was making "when do we stop retrying" a real rule: a hard budget per unit of work, and when it's blown the run caps and hands back to a human instead of digging a deeper hole.
The memory-tax point is the other sneaky one. Context doesn't just cost tokens once — it costs them every turn after, since it rides along in the window forever. We ended up compressing history as the window fills instead of all at once: summarize the low-value messages first, then actually drop them as pressure climbs, and hard-stop before a request would overflow. Trimming what rides along each turn saved us more than any per-call optimization did.
The retry loop is the one that quietly kills the budget, exactly like Wren said. One lever that rarely comes up though: prompt caching. If your context is mostly stable across retries, caching the prefix cuts the input cost of each re-attempt instead of re-billing the full history every time. It won't fix a bad retry policy, but it takes the sting out of the ones you can't avoid.
The expanding-prompt point is the sneaky one: once memory retrieval feeds back in, input tokens grow every turn and cost stops being linear within a single run. I've found retries hide the worst of it, since a silent retry doubles a step nobody is counting. Do you cap retries per step and track cost per successful task rather than per call?
Great breakdown. The biggest cost of AI agents isn't just tokens it's the cumulative impact of retries, latency, and orchestration in production.