LangGraph Deep Research Search Layer
Search layer architecture for LangGraph deep research agents. Problem: search quality and cost at 50-200 queries/task. Solution: structured API with budget caps.
Deep research agents built on LangGraph typically make 50-200 search queries per task. At SerpAPI pricing ($0.015-$0.036/query effective), a single research task costs $0.75-$7.20 just for search. Switching to a credit-based search API with budget caps keeps costs predictable and prevents runaway spending when agents enter search loops.
The problem: uncontrolled search costs
LangGraph deep research agents follow a plan-search-analyze-repeat cycle. Each cycle generates multiple search queries. A complex research task ("analyze the competitive landscape of CRM tools for SMBs") can trigger 150+ searches as the agent explores subtopics, verifies claims, and fills knowledge gaps. Without budget controls, costs are unbounded.
LangGraph agent with budgeted search
import os, requests
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated
class ResearchState(TypedDict):
query: str
search_results: list
analysis: str
budget_remaining: float
searches_made: int
COST_PER_QUERY = 0.005
H = {"x-api-key": os.environ["SCAVIO_API_KEY"]}
def search_node(state: ResearchState) -> ResearchState:
"""Execute search with budget check."""
if state["budget_remaining"] < COST_PER_QUERY:
return {**state, "search_results": [],
"analysis": "Budget exhausted. Returning partial results."}
resp = requests.post("https://api.scavio.dev/api/v1/search",
headers=H, json={"query": state["query"], "platform": "google"})
results = resp.json().get("organic_results", [])[:5]
return {
**state,
"search_results": results,
"budget_remaining": state["budget_remaining"] - COST_PER_QUERY,
"searches_made": state["searches_made"] + 1,
}
def should_continue(state: ResearchState) -> str:
if state["budget_remaining"] < COST_PER_QUERY:
return END
if state["searches_made"] >= 50:
return END
return "search"
graph = StateGraph(ResearchState)
graph.add_node("search", search_node)
graph.add_conditional_edges("search", should_continue)
graph.set_entry_point("search")Multi-platform search for richer context
def multi_platform_search(query: str, platforms: list = None):
"""Search across platforms for comprehensive research."""
platforms = platforms or ["google", "reddit", "youtube"]
results = {}
for platform in platforms:
resp = requests.post("https://api.scavio.dev/api/v1/search",
headers=H, json={"query": query, "platform": platform})
results[platform] = resp.json().get("organic_results", [])[:5]
return results
# Cost: 3 platforms x $0.005 = $0.015 per multi-platform search
# vs single-platform: $0.005
# Richer context for the agent to analyzeCost comparison for a 100-query research task
- SerpAPI Developer ($75/mo for 5K): $1.50 effective cost. Eats 2% of monthly quota per task
- Tavily ($0.008/credit, basic): $0.80 per task. AI-summarized results, less structured
- Scavio ($0.005/credit): $0.50 per task. Structured JSON, multi-platform
- Exa ($5/1K requests): $0.50 per task. Semantic search, different result quality
Design pattern: search budget as agent constraint
The budget cap is not just a cost control -- it is a design constraint that forces the agent to be efficient. An agent with unlimited searches will over-search, making redundant queries for information it already has. A budgeted agent must decide: "is this search worth $0.005 given what I already know?" This decision-making produces better research output because the agent prioritizes high-value queries.