← All guides
Build guides

How to Add Web Search to a LangChain Agent (2026)

Give a LangChain agent live web search in a few lines — one Auxiliar key, any search provider, swap between them by changing one path.

Updated 2026-06-30 · Auxiliar

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.

One key. Every provider on this page.

Stop juggling signups and invoices. One Auxiliar API key calls all of them — upstream keys injected server-side, usage billed to a single balance. Swap the base URL and go.

curl https://api.auxiliar.ai/serper/search \
  -H "Authorization: Bearer $AUXILIAR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"q": "who won the 2026 f1 constructors championship"}'

Keep building