Try
5,000 searches
$9.25
$1.85/1K searches
- Wire it into one agent
- Same API as the largest pack
- Credits never expire
Use case · AI agents · tool name web_search
An agent that can search but not read guesses from snippets. Give it one tool that does both: it searches the live web and returns the first pages as clean Markdown, numbered so the model can cite them.
Quick answer
How do I give an AI agent a web search tool that returns page content?
Wrap a web search API as a tool that takes a query and returns numbered sources with their page text. LLMWebSearch does this in one call: ranked results from a live search, with the first 3 pages read as Markdown, for one credit. Prices start at $9.25 for 5,000 searches and fall to $1.20/1K searches. No KYC; pay in crypto.
| Tool | web_search(query, recent) calling POST https://llmwebsearch.com/api/v1/search |
|---|---|
| Returns | Up to 20 ranked results; the first 3 with their page text in Markdown |
| Length control | max_chars per page, read for the number of pages, max_results for the list |
| Cost | One credit pays for one search: up to 20 ranked results, with the pages of the first 3 read and returned as Markdown. Reading 4 to 10 pages makes it 2 credits. A call that ends in an error costs nothing |
| Filters | Choose the country and language of the results, a time range (past day, week, month or year), web or news results, and domains to include or exclude |
| Ready-made integrations | MCP server, OpenAI function calling, LangChain and LlamaIndex, n8n, OpenClaw |
Because the answer is rarely in the snippet. A results page gives a title and one or two lines chosen by the search engine. The number, date or rule your user asked about sits further down the page.
An agent that only sees snippets has two bad options. It can answer from a fragment and risk being wrong, or it can call a second tool to fetch each page. The second option doubles the round trips and the tool definitions.
With LLMWebSearch, the first pages arrive already read. Navigation, ads and cookie banners are removed, so the model spends its tokens on content. The remaining results still carry their snippets, which help the model decide whether to search again.
Keep the schema small: one required query and, at most, one or two switches. Models call simple tools more reliably. The example below exposes a recent flag that maps to time_range=month; everything else is fixed in your code.
The function returns plain text, not JSON. Each source starts with a number, a title and a URL, followed by its Markdown. That layout makes citations like [2] natural for the model.
If your agent already ships a tool called web_search, as Claude Code and OpenClaw do, give yours another name such as search_web. Two tools with one name confuse the model.
import json
import os
import requests
API = "https://llmwebsearch.com/api/v1/search"
HEADERS = {"Authorization": "Bearer " + os.environ["LLMWEBSEARCH_API_KEY"]}
# Tool definition in the OpenAI function-calling format; most agent frameworks accept the same JSON schema.
WEB_SEARCH_TOOL = {
"type": "function",
"function": {
"name": "web_search",
"description": "Search the live web. Returns numbered sources; the first ones include the page text in Markdown.",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "A short search query, 3 to 8 words"},
"recent": {"type": "boolean", "description": "True to keep only results from the past month"},
},
"required": ["query"],
},
},
}
def web_search(query, recent=False, read=3, max_chars=4000):
"""Run one search (1 credit with read <= 3) and return compact text the model can cite."""
body = {"q": query, "max_results": 5, "read": read, "max_chars": max_chars}
if recent:
body["time_range"] = "month"
resp = requests.post(API, headers=HEADERS, json=body, timeout=60)
resp.raise_for_status()
lines = []
for r in resp.json()["results"]:
lines.append(f"[{r['position']}] {r['title']} — {r['url']}")
if r.get("content_status") == "ok":
lines.append(r["content"])
else:
lines.append(r.get("snippet", ""))
lines.append("")
return "\n".join(lines)
def run_tool_call(call):
"""Execute a tool call returned by the model and give back the text for the tool message."""
args = json.loads(call["function"]["arguments"])
return web_search(args["query"], recent=args.get("recent", False))Search when the answer depends on facts that change or that the model cannot know. Prices, versions, laws, schedules and recent events qualify. Definitions and stable knowledge usually do not.
Write that rule into the system prompt, and add a budget. Three habits help:
Three parameters decide how much text reaches the model. read sets how many pages are read, from 0 to 10. max_chars caps each page, from 500 to 50,000 characters. max_results sets how many results are listed, from 1 to 20.
For a chat agent, read=3 with max_chars=4000 returns about 12,000 characters of page text per search. That leaves room for several searches in one conversation. For a research job that summarises as it goes, longer pages are fine.
The word_count field tells you how long the full page was before the cut. The agent can use it to decide whether to fetch more with the extract endpoint.
The result still comes back, with its title, URL and snippet, but without content. A content_status field says why.
blocked_by_robots: the site's robots.txt does not allow our reader.blocked_by_site_policy: A site that sets Content-Signal: ai-input=no in its robots.txt keeps its pages out of your results' content.target_refused: the site answered with a refusal; its status is in target_status.fetch_failed or fetch_timeout: the page did not load in time.When a site turns our reader away, the result comes back without content and with the site's status: we never solve CAPTCHAs, sign in to accounts or work around a block or a paywall. Tell the agent to use the snippet, or another source, when a page comes back empty. The search itself is still one credit, whatever happened to each page.
Built-in tools are convenient but give you less control. As of October 22, 2026, OpenAI's web_search tool costs $10 per 1,000 calls plus the search content billed as input tokens. Anthropic's Claude web search also costs $10 per 1,000 searches plus token costs. Gemini 3 grounding includes 5,000 free searches a month on the paid tier, then costs $14 per 1,000.
These tools mostly return a written answer with citations, not the raw pages. They also tie your search to one model vendor. A standalone tool works with any model and lets you set the length of every page. The built-in tools comparison has the full table.
One credit per search when read is 3 or less. An assistant used by a team, answering 100 questions a day with 4 searches each, runs about 12,000 searches a month. 25,000 searches at $41.25 covers that month and most of the next.
A coding agent used by one developer may search 20 times a day, or about 600 times a month. 5,000 searches at $9.25 then lasts several months, because credits never expire. The cost guide shows the arithmetic for larger workloads.
Prototype on 5,000 searches; move to 25,000 searches or 100,000 searches once the agent is in daily use.
5,000 searches
$9.25
$1.85/1K searches
25,000 searches
$41.25
$1.65/1K searches
100,000 searches
$145
$1.45/1K searches
In every plan: Top 3 pages read as Markdown · Country, language, time and domain filters · Failed calls not charged · Credits never expire
Yes, through a small MCP server that exposes the search as a tool. The MCP page has the code and the client configuration.
Yes. The schema above is plain JSON Schema, which Anthropic, Google, Mistral and open-source frameworks accept with small changes. The tool only calls our HTTPS endpoint.
Count calls in your tool wrapper and return a short message once the budget is spent. Put the budget in the system prompt as well, so the model plans for it.
It can try. Treat page text as data: tell the model in the system prompt to ignore instructions found inside sources, and never let a source trigger actions on its own.
From $1.20/1K searches · no KYC
Get an API key