A model client sees one thing: a chat completion request and its response. It can count how many times it sent a prompt and how many tokens came back. What it cannot see is what happened between the moment the agent decided to call a tool and the moment the tool's result re-entered context.
Those two moments are often far apart. The MCP specification describes tools as functions the model can execute, with JSON-RPC messages travelling between hosts, clients and servers (MCP specification). The protocol includes error reporting, progress tracking and cancellation as first-class utilities. Every error path is a place where a retry can be manufactured outside the model client's field of view.
Practical consequences:
- A tool-level HTTP client that retries on a 503 generates extra calls that never appear as model requests.
- An orchestrator that catches a timeout and re-dispatches the same tool call does so in application code, not in the model client.
- A framework with its own internal retry policy, wrapping the same tool, adds attempts the client never observes.
- A re-plan after a restart replays a tool call from a durable log, again invisible to the model client.
If you bill, rate limit, or debug from a client-side counter, you will be measuring the wrong population. The OpenAI-style token counters and OTel GenAI attributes are built around LLM operations, not tool invocations; the GenAI semantic conventions across OTel versions split chat spans, agent spans, and tool spans into distinct conventions (Greptime on OTel GenAI evolution). That split is a hint: tool invocation is its own unit of work.



