How to Add Real-Time Web Search to an OpenAI or Claude Agent in 4 Steps

Want your agent to ground answers in current information? You need exactly two things: a search API that returns LLM-ready snippets, and a tool definition the model can call. This walkthrough does both in 4 steps.
一句話總結
- •Step 1: Get an API key (free) and try the endpoint with curl.
- •Step 2: Fetch the OpenAI / Claude tool schema directly from the API — no hand-writing JSON.
- •Step 3: Register the tool with your agent (OpenAI Assistants, Anthropic Messages, LangChain, or n8n).
- •Step 4: Implement the tool handler that calls /api/search/web and returns results to the model.
Why this is short
Most \"add web search to your LLM\" tutorials are long because they're really tutorials about a search-API SDK or a heavyweight agent framework. This one isn't. The whole job is: pick an endpoint, register it as a tool, write a 5-line handler.
1Get an API key (free) and call the endpoint
Sign up at apipick.com/dashboard/api-keys. New accounts get 100 free credits — no credit card. Create a key and try the endpoint:
curl -X POST https://www.apipick.com/api/search/web \
-H "x-api-key: pk_yourkey" \
-H "Content-Type: application/json" \
-d '{"query": "what is retrieval augmented generation"}'You'll get back a small ranked list of titles, URLs, and snippets. Confirming this works in curl saves debugging time later.
2Fetch the tool schema (don't hand-write it)
API Pick exposes ready-to-paste tool schemas at GET /api/search/web/tool-schema. The response includes both an OpenAI-style function definition and a Claude tool use definition.
curl https://www.apipick.com/api/search/web/tool-schemaCache the result — it doesn't change between calls. Hand-writing function schemas is the most common source of bugs in agent code (wrong type, wrong required fields, missing description).
3Register the tool with your agent
OpenAI Assistants
from openai import OpenAI
import requests
client = OpenAI()
schema = requests.get("https://www.apipick.com/api/search/web/tool-schema").json()
assistant = client.beta.assistants.create(
name="Research Agent",
model="gpt-4o",
instructions="Use web_search whenever the user asks about current events or anything that changes after your training cutoff.",
tools=[{"type": "function", "function": schema["openai"]}],
)Anthropic Claude
import anthropic
import requests
schema = requests.get("https://www.apipick.com/api/search/web/tool-schema").json()
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=[schema["claude"]],
messages=[{"role": "user", "content": "Summarise this week's RAG research."}],
)LangChain
from langchain.tools import tool
import requests
@tool
def web_search(query: str) -> dict:
"""Real-time web search. Use for any question that needs current information."""
return requests.post(
"https://www.apipick.com/api/search/web",
headers={"x-api-key": "pk_yourkey"},
json={"query": query},
).json()n8n
Add an HTTP Request node: method POST, URL https://www.apipick.com/api/search/web, header x-api-key: pk_yourkey, JSON body {"query": "{{ $json.query }}"}. Wire it into your agent or LLM Chain node. No SDK required.
4Handle the tool call
For OpenAI Assistants, when the run pauses with a requires_action status, run the search and submit the output:
import json, time, requests
from openai import OpenAI
client = OpenAI()
KEY = "pk_yourkey"
def run_with_tool(thread_id: str, assistant_id: str):
run = client.beta.threads.runs.create(thread_id=thread_id, assistant_id=assistant_id)
while True:
run = client.beta.threads.runs.retrieve(thread_id=thread_id, run_id=run.id)
if run.status == "requires_action":
outputs = []
for call in run.required_action.submit_tool_outputs.tool_calls:
if call.function.name == "web_search":
args = json.loads(call.function.arguments)
result = requests.post(
"https://www.apipick.com/api/search/web",
headers={"x-api-key": KEY},
json=args,
).json()
outputs.append({"tool_call_id": call.id, "output": json.dumps(result)})
client.beta.threads.runs.submit_tool_outputs(
thread_id=thread_id, run_id=run.id, tool_outputs=outputs,
)
elif run.status in ("completed", "failed", "cancelled", "expired"):
return run
time.sleep(0.5)The Anthropic Messages API loop is similar — when the response contains a tool_use block, call the API, then send the result back as a tool_result content block in the next turn.
Tightening the loop
- Set the tool description from the model's perspective: \"Use this when the user asks about current events, breaking news, or anything that may have changed after your training cutoff.\" Don't say \"this is a web search API\".
- Cache results in your handler when the same query appears twice in a session. Web search results are stable for ~minutes; you don't need to pay 15 credits twice in the same conversation.
- Add a
start_datefilter when freshness matters. \"This week's news\" with no date filter often returns last year's headlines.
Where to go next
Once your agent can search, the natural next step is to read the linked pages. Add the URL Content Extraction API as a second tool — same auth, same JSON shape, batch up to 25 URLs per call. The combo \"search + extract\" is the smallest useful research agent.
常見問題
Can I use this with the OpenAI Responses API instead of Assistants?
Yes. The same tool schema works in client.responses.create() — pass it via tools=[{...}] exactly as shown in the OpenAI docs. The handler shape is identical: parse tool_calls, run POST /api/search/web, return the JSON.
Do I need to format results before returning them to the model?
No. POST /api/search/web returns ranked title + URL + LLM-friendly snippet. Pass the raw JSON back as the tool result. The model will quote the snippets and link the URLs.
How much does each agent turn cost?
Each web search call is 15 credits (~$0.015 at $5/5,000 credits). A typical agent turn that uses the tool once is well under a US cent of search cost — the LLM tokens dominate.
What if the model never calls the tool?
Make the tool description specific. "Use this for any question that requires current or post-training information" works much better than "web search". Models route to tools they understand the purpose of.
Can I limit results to a country or date range?
Yes. Pass country_code (ISO 3166-1 alpha-2) and/or start_date / end_date (YYYY-MM-DD). Add these as parameters in your tool schema if you want the model to choose them; or hard-code them in the handler if your agent has a fixed locale or freshness requirement.
本文使用的 API
Sarah Choy 是 API Pick 的 CEO,專注於為 AI Agent 與 LLM 工作流打造可用於正式環境的 API。