An LLM only knows what it was trained on. The moment your LangChain agent needs a fact from after the cutoff — today’s news, a price, a changelog — it needs live web search. This guide wires that in, and does it in a way that lets you swap search providers without touching your agent code.
The one-key approach
You could sign up for Serper, then Tavily, then Exa, juggle three API keys, and hard-code one into your agent. Or you point a single Auxiliar key at the gateway and reach all of them through one endpoint — https://api.auxiliar.ai/<provider>/... — with your upstream keys injected server-side. Switching from Serper to Tavily becomes a one-line change to the request path.
Step 1 — a search tool
Create a LangChain tool that calls the gateway. This example uses Serper (the cheapest, fastest Google backend in our benchmark); swap the path to use another provider.
import os, requests
from langchain_core.tools import tool
AUX = "https://api.auxiliar.ai"
HEADERS = {"Authorization": f"Bearer {os.environ['AUXILIAR_API_KEY']}"}
@tool
def web_search(query: str) -> str:
"""Search the live web. Use for anything recent, factual, or beyond your training data."""
r = requests.post(f"{AUX}/serper/search",
headers=HEADERS, json={"q": query}, timeout=30)
r.raise_for_status()
results = r.json().get("organic", [])[:5]
return "\n".join(f"{o['title']} — {o['link']}\n{o.get('snippet','')}" for o in results)
That’s the whole integration. Your AUXILIAR_API_KEY is the only credential; the gateway forwards to google.serper.dev and bills the call to your balance.
Step 2 — give it to an agent
from langchain.chat_models import init_chat_model
from langgraph.prebuilt import create_react_agent
llm = init_chat_model("anthropic:claude-sonnet-5")
agent = create_react_agent(llm, tools=[web_search])
result = agent.invoke({"messages": [
{"role": "user", "content": "What shipped in the latest Next.js release?"}
]})
print(result["messages"][-1].content)
The agent now decides when to search, calls your tool, and grounds its answer in live results.
Step 3 — swap providers without rewriting anything
Because every provider sits behind the same key, changing your search backend is a path change. Prefer an agent-native index that returns a relevance score and an optional answer? Point at Tavily:
r = requests.post(f"{AUX}/tavily/search",
headers=HEADERS, json={"query": query}, timeout=30)
Want semantic/neural discovery instead of keyword search? Use /exa/search. Each provider keeps its native request and response shape — Auxiliar passes them straight through — so you follow the provider’s own docs, just with the Auxiliar base URL and key. (Full per-provider schemas live at docs.auxiliar.ai.)
Which search provider should you use?
It depends on the job: cheapest Google grounding, agent-native RAG, or neural discovery each have a different winner. We benchmarked all eleven on the same corpus — see the best search API for AI agents and the head-to-head Exa vs Tavily and Serper vs SerpApi comparisons. Since they’re all on one key, the pragmatic move is to route each query type to whichever scored best.