Search API for LLM: How to Add Real-Time Lookup
What "search API for LLM" actually means
When developers search for "search API for LLM," they're usually looking for one of two things: a way to give a language model live access to the web (or an internal knowledge base) so it can answer questions beyond its training cutoff, or an API that returns structured search results an LLM can reason over. In practice these are the same problem. You need a search provider that returns clean, parseable results, and an LLM that can decide when to call it, read the results, and turn them into a grounded answer.
This is not a model feature — no LLM natively "knows" today's date, stock prices, or last week's release notes. The fix is tool use (also called function calling): you describe a search function to the model, the model emits a structured call when it needs external data, your backend executes the actual HTTP request to a search API, and the result gets fed back into the conversation. The model never touches the internet directly — your code is always in the loop.
The basic architecture
A search-enabled LLM pipeline has four parts:
- A search provider — Brave Search API, Serper, Tavily, Bing Web Search, or your own Elasticsearch/vector index.
- A tool schema — a JSON description of the search function (name, parameters, description) that you pass to the model.
- An orchestration loop — code that checks if the model wants to call the tool, executes it, and sends the result back.
- The LLM endpoint — the actual API call to Claude, GPT, or whichever model you're using.
If you're already routing your Claude traffic through SubToAPI, parts 3 and 4 are simplified: you get a standard HTTPS endpoint with full tool-use support, so the orchestration loop looks the same regardless of which app or environment is calling it.
Defining a search tool
Here's a minimal tool definition you'd send alongside a message:
{
"name": "web_search",
"description": "Search the web for current information. Use this when the user asks about recent events, prices, or anything not in your training data.",
"input_schema": {
"type": "object",
"properties": {
"query": { "type": "string", "description": "The search query" }
},
"required": ["query"]
}
}
And a request that includes it:
curl https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet",
"max_tokens": 1024,
"tools": [{
"name": "web_search",
"description": "Search the web for current information.",
"input_schema": {
"type": "object",
"properties": { "query": { "type": "string" } },
"required": ["query"]
}
}],
"messages": [
{ "role": "user", "content": "What was announced in the latest Claude release?" }
]
}'
The model responds with a tool_use block containing the query it wants to run. Your code executes the actual search call — for example, against Brave Search — and sends the results back as a tool_result message. The model then writes its final answer using that data.
Wiring it up in JavaScript
async function runSearchLoop(userMessage) {
let messages = [{ role: "user", content: userMessage }];
const tools = [{
name: "web_search",
description: "Search the web for current information.",
input_schema: {
type: "object",
properties: { query: { type: "string" } },
required: ["query"]
}
}];
let response = await callModel(messages, tools);
while (response.stop_reason === "tool_use") {
const toolCall = response.content.find(c => c.type === "tool_use");
const results = await searchProvider(toolCall.input.query); // e.g. Brave/Serper
messages.push({ role: "assistant", content: response.content });
messages.push({
role: "user",
content: [{
type: "tool_result",
tool_use_id: toolCall.id,
content: JSON.stringify(results)
}]
});
response = await callModel(messages, tools);
}
return response;
}
callModel here is a thin wrapper around a POST to /v1/messages. Full details on request shape and tool-result formatting are in the tool use docs; the general request/response contract is in the messages docs.
Choosing a search provider
Not all search APIs are equally suited to LLM consumption:
- Brave Search API — cheap, fast, decent snippet quality, good default choice.
- Serper / SerpApi — scrape Google SERPs, useful when you need exact ranking or local results.
- Tavily — built specifically for LLM agents, returns pre-summarized, citation-friendly results.
- Bing Web Search — solid coverage, works well if you're already on Azure.
- Internal vector search (pgvector, Pinecone, Weaviate) — for retrieval over your own docs, not the open web. This is the right call when the "search" is really RAG over private data.
Whichever you pick, keep the tool description narrow. A model given a vague "search anything" tool will call it too often, burning latency and tokens. Describe exactly when to use it — recent events, prices, specific facts — and let the model answer from its own knowledge otherwise.
Handling latency and streaming
Search calls add a network round trip on top of the model call, so total response time for a search-augmented answer is model latency + provider latency + a second model call. If you're building a chat UI, stream the final answer once the tool loop resolves rather than trying to stream through the tool-call phase — see streaming basics for how server-sent events work with multi-turn tool calls.
For production traffic, cache search results for identical queries within a short TTL (a few minutes is usually enough) — it cuts provider costs and avoids redundant calls when several users ask about the same trending topic.
Getting started
If you're already building on Claude and want tool use, streaming, and usage metadata behind one API key instead of juggling console access, SubToAPI turns your existing Claude access into a standard HTTPS endpoint — Solo at €9/month for solo builders, Team and Scale plans for shared workloads. There's a free trial at signup, and the quickstart walks through your first authenticated request in a few minutes.
questions
Is a search API for LLM the same as RAG? Not exactly. RAG (retrieval-augmented generation) usually means retrieving from your own indexed documents. A search API for LLM often means live web search, but the mechanism — retrieve, then feed into the prompt — is the same pattern.
Which search provider is cheapest for LLM tool use? Brave Search API is generally the lowest-cost option with acceptable quality for most use cases. Tavily costs more but returns results already formatted for LLM consumption, which can reduce your own parsing work.
Do I need tool use support, or can I just fetch search results and paste them into the prompt? You can paste results manually for simple cases, but tool use lets the model decide when a search is needed, which avoids unnecessary calls and keeps latency and cost down for queries the model can already answer.