Does tool routing actually help? Measured against two deliberately unintelligent baselines.
held_out. These tasks were held back from the whole of development and executed exactly once, after the last change to anything the agent does. Nothing below was iterated against, and no re-run is possible: the reservation that permitted this execution is spent.minsafe-deep-03, minsafe-deep-04) were run during development before the split was being honoured, and are permanently excluded. The sealed set is therefore 38 tasks, not 40, and that reduction is disclosed rather than absorbed.| System | Answer accuracy | Ungradable | Mean tool calls |
|---|---|---|---|
| Agent (tool routing) | 92% 35/38 95% CI 79–97% | 0 | 2.79 n=38 |
| no_agent (calls every tool) | 94% 34/36 95% CI 82–98% | 2 | 4.95 n=38 |
| always_lookup (one tool) | 92% 35/38 95% CI 79–97% | 0 | 1.58 n=38 |
no_agent calls every tool on every package and lets the model answer once, so it always holds strictly more information than the routing agent. Routing is therefore dominated whenever calling everything is affordable and fits in the context window. That is arithmetic, not a property of this task set, and the task set was deliberately not redesigned until the agent won.Same tasks, different systems, so the information is in the discordant pairs — tasks where exactly one system was right. Treating the two as independent proportions discards most of it.
always_lookup| Wins | Ties | Losses | Discordant | Exact McNemar p | Excluded |
|---|---|---|---|---|---|
| 2 | 34 | 2 | 4 | 1.00 | 0 |
no_agent| Wins | Ties | Losses | Discordant | Exact McNemar p | Excluded |
|---|---|---|---|---|---|
| 2 | 31 | 3 | 5 | 1.00 | 2 |
Each tool result is corrupted one way per run: an HTTP 503, a valid-but-empty payload, or a record with the field the answer depends on removed. This is the one condition the baselines structurally cannot compete in — both are single-shot scripts and cannot retry, switch tool, or abstain.
| System | error (503) | empty | malformed |
|---|---|---|---|
| Agent (tool routing) | 50% 10/20 95% CI 30–70% | 58% 11/19 95% CI 36–77% | 90% 18/20 95% CI 70–97% |
| no_agent (calls every tool) | 0 gradable 20 crashes | 68% 13/19 95% CI 46–85% | 100% 19/19 95% CI 83–100% |
| always_lookup (one tool) | 0 gradable 20 crashes | 50% 10/20 95% CI 30–70% | 84% 16/19 95% CI 62–94% |
These explain the headline; they are not competitors to it. High tool recall alongside low answer accuracy would mean the agent gathered the right evidence and still concluded wrongly.
| System | Tool recall | Tool precision | Negative conflation | Termination | Over-call ratio | Repeat calls |
|---|---|---|---|---|---|---|
| Agent (tool routing) | 0.99 n=38 | 1.00 n=38 | 0% 0/14 95% CI 0–22% | 95% 36/38 95% CI 83–99% | 1.32 n=38 | 0% 0/38 95% CI 0–9% |
| no_agent (calls every tool) | 1.00 n=38 | 0.51 n=38 | 0% 0/14 95% CI 0–22% | 100% 38/38 95% CI 91–100% | 2.95 n=38 | 0% 0/38 95% CI 0–9% |
| always_lookup (one tool) | 0.75 n=38 | 1.00 n=38 | 0% 0/14 95% CI 0–22% | 100% 38/38 95% CI 91–100% | 0.95 n=38 | 0% 0/38 95% CI 0–9% |
Every version string and advisory identifier in an answer is checked against the entire frozen snapshot. A token that appears nowhere in it was invented; one that exists but belongs to another package is misattributed.
| System | Per assertion | Per task | Hard | Misattributed |
|---|---|---|---|---|
| Agent (tool routing) | ≥ 0% 0/6 95% CI 0–39% | ≥ 0% 0/38 95% CI 0–9% | 0 | 0 |
| no_agent (calls every tool) | ≥ 10% 2/21 95% CI 3–29% | ≥ 3% 1/38 95% CI 0–13% | 0 | 2 |
| always_lookup (one tool) | ≥ 0% 0/13 95% CI 0–23% | ≥ 0% 0/38 95% CI 0–9% | 0 | 0 |