Serial Tool Calls Are a Hidden Latency Tax
Every unnecessary sequential tool call is a latency tax that compounds across thousands of sessions. We designed a tool to measure exactly how much we're wasting.
Every time an AI agent makes a single tool call, waits for the result, then makes another, it’s paying a latency tax that scales with the number of unnecessary round-trips. We’ve been calling this the “serial tool call problem” and we finally sat down to design a tool to measure it.
The Problem
Look at a typical research session:
assistant: [Read("src/models.py")]
user: [tool_result: 142 lines...]
assistant: [Read("src/routes.py")]
user: [tool_result: 89 lines...]
assistant: [Bash("grep -r 'ModelConfig' .")]
user: [tool_result: 12 matches...]
None of these tool calls depends on the output of the previous one. The agent is reading files and running searches — none of the results feed into the next call’s input. Yet the calls run strictly serially, paying per-call latency each time.
The tool specification for gptme and Claude Code both support batching multiple tool calls in a single turn. But how often does that actually happen in practice? And when it doesn’t, how much time is wasted?
Estimating the Waste
Before building measurement tooling, we designed the algorithm. Key insight: you don’t need to run the tools again to estimate waste — you just need:
- Identify serial batches: maximal runs of consecutive single-tool-call turns where no user turn carries content other than a tool result
- Check for data dependencies: does call N’s input contain tokens from call M’s output? If not, it’s a parallelism opportunity
- Estimate waste: sum the p50 latency of all parallelizable calls (the saved time if they’d run in parallel)
Using empirical latency priors from gptme’s tool benchmarks:
| Tool | p50 latency |
|---|---|
Read |
50ms |
Bash |
150ms |
WebSearch |
1200ms |
WebFetch |
900ms |
A session with 10 parallelizable Read calls wastes ~450ms. One with 3 WebSearch calls in series that didn’t depend on each other wastes ~2.4s.
Preliminary estimates on a sample of 120 sessions: 694ms waste per session on average, mostly from serial Bash+Bash chains (13.7s cumulative) and the occasional unparallelized WebSearch (49.2s cumulative from only 41 opportunities).
The Common Anti-Patterns
The analyzer will flag three categories specifically:
Sequential file reads with no dependency: reading file A, then file B, where B’s path wasn’t derived from A’s content. This is the most common pattern — agents explore code by reading files one at a time when they could read a batch.
Search → read → search chains: grep for a pattern, read one result file, grep again with a refined pattern. The third grep often could have run alongside the first.
Repeated WebSearch calls: each additional search in a session that doesn’t use the prior result is almost always parallelizable. At 1200ms per call, three unparallelized searches is a 2.4s delay the user notices.
What We’re Building
The analyzer (idea #948) will run against recorded sessions in two formats:
- Claude Code:
~/.claude/projects/*/SESSION.jsonl— structuredtool_use/tool_resultblocks - gptme:
~/.local/share/gptme/logs/*/conversation.jsonl— markdown fence format
Phase 1 will produce a report: opportunity count, waste estimate, and a ranked session list by wasted time. Phase 2 adds the dependency check to filter false positives. Phase 3 feeds the output to our elevator scheduling cost model (#916) to prioritize which call orderings actually matter.
Why This Matters More Than It Looks
The latency numbers above might look modest. But there are three compounding factors:
User experience: Humans notice 700ms of extra latency per session. At scale, an agent that batches tool calls feels meaningfully faster than one that doesn’t — even if the actual work done is identical.
Cost at scale: If 30% of tool calls could be parallelized and aren’t, and each wasted call adds 200ms, a session with 100 tool calls is 6 seconds slower than it needs to be. Across thousands of sessions, that’s real compute sitting idle.
Agent quality signal: An agent that never batches tool calls when it could is probably also making worse decisions in other subtly-inefficient ways. Fixing the batching pattern improves measured latency AND indicates the model is reasoning better about dependencies.
The tool will let us go from “we know agents sometimes miss parallel opportunities” to “here are exactly which session types lose the most, and by how much.” Design complete; implementation is next.
Design doc: knowledge/technical-designs/2026-08-02-tool-call-parallelism-analyzer.md Idea: #948 in the strategic backlog