Why your agent's tool call latency budget needs to be 10x your prompt latency
A tool-call latency budget should usually be an order of magnitude larger than the prompt-processing latency you are willing to tolerate—not because tools deserve to be slow, but because agent latency compounds across networks, queues, retries, and serial decisions. If you budget tool calls as though they were local function calls, normal variance will consume the entire end-to-end deadline.
Prompt latency is not the right baseline
Suppose a model begins producing a tool decision 180 ms after receiving a cached, compact prompt. It is tempting to set a 250 ms target for the tool and call anything slower a regression. That target ignores where the work runs.
A remote tool call may include:
- DNS and connection setup.
- TLS negotiation.
- An API gateway and authentication check.
- A queue wait at the provider.
- Database or search execution.
- Response serialization and transfer.
- Client-side validation and instrumentation.
Even if each layer is healthy, their tail latencies add. A 40 ms network leg, 60 ms gateway, 250 ms query, and 50 ms response path already total 400 ms before variance. The prompt path may remain inside one provider’s optimized infrastructure; the tool path crosses systems owned by several teams.
“10x” is a useful starting ratio, not a law. If prompt processing to the first tool decision is 200 ms, begin with a 2-second tool budget. Then replace the ratio with measured percentiles and an explicit end-to-end deadline.
Budget the agent run, not an isolated call
The user experiences the full critical path. A single 1.2-second tool call may be acceptable. Four serial 1.2-second calls are not.
Write the budget as an equation:
T_total = T_model_decision
+ sum(T_serial_tools)
+ max(T_parallel_tools)
+ T_model_answer
+ T_retries
+ T_queueing
Consider an agent with a 6-second service-level objective:
- Initial model decision: 350 ms
- Two serial tools: 1,200 ms each
- Two parallel tools: 900 ms at the slower branch
- Final model answer: 1,300 ms
- Application overhead: 250 ms
The expected path is 5,200 ms. That leaves only 800 ms for variance or retry. A single timeout-and-retry policy can push the request beyond the SLO even when every component meets its local average.
The first fix is not necessarily a faster tool. It may be parallelization, a cached result, a smaller retry window, or removal of an unnecessary planning turn.
Use percentile budgets and separate timeouts
Averages hide the failures users notice. If a tool returns in 300 ms nine times and 6 seconds once, its average is 870 ms. That number describes none of the ten experiences well.
Track at least p50, p95, and p99 by tool and operation. Set three different controls:
- Alert threshold: evidence that the latency distribution moved, such as p95 rising from 700 ms to 1,100 ms.
- Soft budget: a point where the agent should prefer a cache, partial result, or alternate tool.
- Hard timeout: the maximum time the request may block before cancellation.
Do not use one number for all three. An alert at 1 second might be sensible while the hard timeout remains 2.5 seconds. Otherwise a modest regression turns directly into user-visible failures.
A minimal Python wrapper can enforce the hard limit while recording enough information to tune it:
import asyncio
import time
from collections.abc import Awaitable, Callable
from typing import TypeVar
T = TypeVar("T")
async def call_with_budget(
tool_name: str,
call: Callable[[], Awaitable[T]],
*,
timeout_s: float = 2.0,
) -> T:
started = time.perf_counter()
outcome = "ok"
try:
return await asyncio.wait_for(call(), timeout=timeout_s)
except TimeoutError:
outcome = "timeout"
raise
except Exception:
outcome = "error"
raise
finally:
latency_ms = (time.perf_counter() - started) * 1000
record_tool_call(
tool=tool_name,
latency_ms=latency_ms,
outcome=outcome,
timeout_ms=timeout_s * 1000,
)
The important detail is recording timed-out calls too. If telemetry captures only completed requests, the latency dashboard improves precisely when the service gets worse.
Retries spend from the same account
Retries are not free reliability. They consume latency budget and often increase load on a dependency that is already struggling.
For a 6-second end-to-end SLO, a tool cannot have a 4-second timeout followed by one 4-second retry. The policy is arithmetically incapable of meeting the SLO. A better allocation might be:
- First attempt: 1.4-second timeout
- Jittered backoff: 100–250 ms
- Second attempt: 1.0-second timeout
- Fallback or partial response: 400 ms
That caps the retry branch near 3 seconds. It still requires idempotency for write operations. Never automatically retry an action such as charge_card or send_email unless the tool supports an idempotency key and the client reuses it.
Retry only conditions likely to change on another attempt: a transient connection reset, rate-limit response with a usable delay, or short provider timeout. A schema mismatch will not heal in 200 ms. Retrying malformed data only extends the outage.
Detect distribution shifts before the timeout fires
Hard timeouts are the last line of defense. They tell you a request already failed. A better monitor detects that p95 moved while most calls still complete.
Compare a recent window against a baseline using both absolute and relative thresholds. For example, alert when all of these are true:
- At least 100 calls occurred in each window.
- Current p95 exceeds 1,000 ms.
- Current p95 is at least 40% above the seven-day baseline.
- The change persists for three consecutive five-minute windows.
The absolute threshold prevents noise on tiny values; the relative threshold catches meaningful shifts; the sample floor avoids reacting to five unusual calls. Group by operation and region before blaming the whole provider. A global aggregate can hide one failing endpoint or invent a regression when traffic mix changes.
Shape drift belongs beside latency. A provider may respond in 120 ms with an error object that still carries HTTP 200. Fast invalid data is not a successful tool call. Record duration, outcome, and response shape together.
Where the 10x advice does not apply
A local deterministic tool may deserve a much tighter ratio. An in-process calculator taking 200 ms is slow even if the model spent 100 ms choosing it. A database lookup on the same network can often sustain a sub-100 ms p95. Safety-critical actions may require a fixed deadline derived from the business process rather than model latency.
The ratio also breaks down for deliberately long-running tools: video rendering, large exports, code execution, or human approval. Those should use asynchronous jobs, progress states, and resumable workflows. Giving a synchronous request a 90-second timeout is not latency budgeting.
Finally, a slow model can make the ratio absurd. If the planning turn takes 4 seconds, a 40-second tool budget is not justified. Start from the user-facing SLO, reserve time for the final answer, and allocate the remainder across the critical path.
ToolPulse can record per-tool latency, failures, and shape changes, but no monitor can choose the budget for you. Set the end-to-end deadline first, measure the real call graph, and make every timeout prove that the full request can still finish on time.