Plan or Retrieve First? A Scale Study of Tool Discovery Architectures
Organizations: Apple
Abstract
Tool-augmented LLM agents discover relevant APIs from large registries before planning execution, yet finite context windows prohibit injecting all tool definitions into a single prompt. The dominant approach, which we term Retrieve-then-Plan (RtP), embeds the user query and retrieves similar tools via approximate nearest-neighbor search. We study an alternative Plan-then-Retrieve (PtR) paradigm in which the LLM first generates Abstract Tool Stubs (hypothesized function signatures describing needed capabilities) which then serve as retrieval queries against the registry. Evaluating on ToolBench (46,984 unique API endpoints, 50 categories) across single-tool (G1), intra-category multi-tool (G2), and cross-category multi-tool (G3) query subsets, we find a clear complexity-dependent crossover: RtP outperforms PtR on single-tool queries while PtR outperforms RtP on multi-tool queries. This crossover holds at every retrieval budget (k=1 to 20), is robust across registry sizes from 1k to 47k APIs, and is consistent across model families (Gemini 2.5 Flash and gpt-oss-120b). We characterize a stub-hallucination failure mode (the LLM invents plausible but non-existent API names) that acts as a double-edged sword: on simple queries PtR's stubs abstract away proper-noun signals that RtP matches directly, yet on complex queries the same mechanism decomposes multi-faceted intent into functional sub-needs. We further analyze token overhead and show that PtR's extra discovery call roughly doubles inference cost, which pays off on multi-tool queries but hurts on single-tool ones, motivating complexity-adaptive routing as a practical direction, one that can be driven by a zero-cost signal already present in the pipeline (RtP's top-1 retrieval score).
Figures & tables
| G1 | G2 | G3 | ||||
| RtP | PtR | RtP | PtR | RtP | PtR | |
| 1 | ||||||
| 3 | ||||||
| 5 | ||||||
| 10 | ||||||
| 20 | ||||||
| Query | PtR Stub(s) | Ground-Truth API | PtR R | RtP R |
| RtP wins: query contains the API name directly | ||||
| “latest news about crime in Germany” | news_article_search_api | German Police and Crime News Live | 0.00 | 1.00 |
| “programming memes from Reddit” | reddit_api_client | Programming Memes Reddit/Get All | 0.00 | 1.00 |
| “electricity bill PLN analysis” | get_postpaid_pln_bill_details | Cek ID PLN/Get Data Tagihan | 0.00 | 1.00 |
| “Testing out Sharing w/ Rachael” | api_specification_retriever | Testing out Sharing w/ Rachael | 0.00 | 1.00 |
| PtR wins: query describes a capability; stubs bridge the semantic gap | ||||
| RtP | PtR | |||||
| Subset | Metric | Mean | Std | Mean | Std | |
| G1 ( ) | Pass Rate | |||||
| Precision | ||||||
| Recall | ||||||
| G2 ( ) | Pass Rate | |||||
| Precision | ||||||
| Subset | Gen.% | Stubs/q | Unique% | Match% | Cos |
| G1 | 98.5% | 2.1 | 98.6% | 40.6% | 0.874 (correct) / 0.872 (incorrect) |
| G2 | 99.5% | 2.4 | 93.6% | 38.3% | 0.843 / 0.840 |
| G3 | 100% | 2.5 | 79.1% | 24.8% | 0.858 / 0.854 |
| Subset | Stubs/q | PtR eff. width | RtP eff. width | Budget-equiv. | RtP recall |
| G1 | 2.1 | 5 | 10 | 0.453 | |
| G2 | 2.4 | 5 | 10 | 0.186 | |
| G3 | 2.5 | 5 | 10 | 0.217 |
| Metric | Arch. | G1 | G2 | G3 |
| Selection rate | PtR | 28.6% | 28.2% | 26.8% |
| RtP | 26.7% | 21.2% | 22.4% | |
| Jaccard (selected) | both | 0.40 | 0.29 | 0.28 |
| Plan steps | PtR | 3.8 | 3.9 | 4.1 |
| RtP | 3.5 | 3.7 | 3.6 | |
| Fidelity | PtR | 98.8% | 97.8% | 98.5% |
| Subset | Identical | Divergent | |
| G1 | 200 | 2.5% | 97.5% |
| G2 | 200 | 1.0% | 99.0% |
| G3 | 100 | 0.0% | 100.0% |
| RtP | PtR | Overhead | R | |
| G1 | ||||
| G2 | ||||
| G3 |
| Query | PtR Stub | RtP Retrieved (correct) |
| “crime news in Germany” | news_search_api | German Police and Crime News Live |
| “programming memes, Reddit” | reddit_api_client | Programming Memes Reddit/Get All Memes |
| “PLN electricity bill” | get_pln_bill_details | Cek ID PLN/Get Data Tagihan |
| “Testing out Sharing w/ Rachael” | api_spec_retriever | Testing out Sharing w/ Rachael/Input test |
| G1 Recall | G2 Recall | ||||
| Registry size | RtP | PtR | RtP | PtR | Div% |
| 1,000 | |||||
| 2,000 | |||||
| 5,000 | |||||
| 10,000 | |||||
| 20,000 | |||||
| Precision | Recall | Pass Rate | ||||
| Subset | RtP | PtR | RtP | PtR | RtP | PtR |
| G1 | 0.274 | 0.372 | ||||
| G2 | 0.168 | 0.143 | ||||
| G3 | 0.135 | 0.160 | ||||