Tutorial

How to Build a LangGraph Search Agent with Budget Control

Add Scavio search as a LangGraph tool node with budget-aware execution. Python agent with configurable max search limit.

LangGraph agents can call tools in loops, which means an unconstrained search tool can burn through credits on a single query. This tutorial builds a LangGraph agent with Scavio search as a tool node that tracks credit usage per conversation and stops searching when it hits a configurable budget limit. Each search costs $0.005.

Prerequisites

  • Python 3.8+
  • langgraph and langchain installed
  • A Scavio API key from scavio.dev
  • An LLM API key (OpenAI, Anthropic, or local)

Walkthrough

Step 1: Define the budget-aware search tool

Create a LangGraph-compatible tool that tracks and limits search spend.

Python
import os, requests, json
from langchain_core.tools import tool
from typing import Optional

API_KEY = os.environ['SCAVIO_API_KEY']
SH = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}

search_state = {'calls': 0, 'cost': 0.0, 'max_calls': 10}

@tool
def web_search(query: str, platform: Optional[str] = None) -> str:
    """Search the web for current information. Supports google, reddit, youtube, amazon, walmart platforms."""
    if search_state['calls'] >= search_state['max_calls']:
        return f"Budget limit reached ({search_state['max_calls']} searches, ${search_state['cost']:.3f}). Synthesize from existing results."
    body = {'query': query, 'country_code': 'us'}
    if platform: body['platform'] = platform
    data = requests.post('https://api.scavio.dev/api/v1/search',
        headers=SH, json=body).json()
    search_state['calls'] += 1
    search_state['cost'] += 0.005
    results = data.get('organic_results', [])[:5]
    formatted = [f"{r['position']}. {r['title'][:60]} - {r.get('snippet', '')[:100]}" for r in results]
    return f"Search results for '{query}' ({search_state['calls']}/{search_state['max_calls']} budget):\n" + '\n'.join(formatted)

print(web_search.invoke({'query': 'best serp api 2026'}))

Step 2: Build the LangGraph agent graph

Create the agent graph with search tool node and conditional routing.

Python
from langgraph.graph import StateGraph, END
from langgraph.prebuilt import ToolNode
from langchain_core.messages import HumanMessage, AIMessage
from typing import TypedDict, Annotated, Sequence
import operator

class AgentState(TypedDict):
    messages: Annotated[Sequence, operator.add]

def should_continue(state):
    last = state['messages'][-1]
    if hasattr(last, 'tool_calls') and last.tool_calls:
        return 'tools'
    return END

tool_node = ToolNode([web_search])

# Use your preferred LLM:
# from langchain_openai import ChatOpenAI
# llm = ChatOpenAI(model='gpt-4o').bind_tools([web_search])
# Or from langchain_anthropic import ChatAnthropic
# llm = ChatAnthropic(model='claude-sonnet-4-20250514').bind_tools([web_search])

def agent_node(state):
    response = llm.invoke(state['messages'])
    return {'messages': [response]}

graph = StateGraph(AgentState)
graph.add_node('agent', agent_node)
graph.add_node('tools', tool_node)
graph.set_entry_point('agent')
graph.add_conditional_edges('agent', should_continue, {'tools': 'tools', END: END})
graph.add_edge('tools', 'agent')
app = graph.compile()
print('LangGraph agent compiled with budget-aware search.')

Step 3: Run the agent with budget tracking

Execute the agent on a research question and monitor credit usage.

Python
def run_with_budget(question, max_searches=5):
    search_state['calls'] = 0
    search_state['cost'] = 0.0
    search_state['max_calls'] = max_searches
    result = app.invoke({'messages': [HumanMessage(content=question)]})
    final = result['messages'][-1].content
    print(f'\n--- Agent Response ---')
    print(final[:500])
    print(f'\n--- Budget ---')
    print(f'Searches used: {search_state["calls"]}/{max_searches}')
    print(f'Cost: ${search_state["cost"]:.3f}')
    return final

# Research question with budget limit
run_with_budget('Compare the top 3 SERP APIs for Python developers in 2026', max_searches=5)

Step 4: Add multi-platform search strategy

Configure the agent to search across platforms for richer answers.

Python
def research_with_sources(topic, max_searches=8):
    prompt = f"""Research this topic using multiple search platforms for a complete picture:
    Topic: {topic}

    Strategy:
    1. Search Google for overview and top results
    2. Search Reddit for real user opinions
    3. Search YouTube for tutorial coverage
    4. Synthesize findings with sources

    Use the platform parameter: google (default), reddit, youtube, amazon
    Budget: {max_searches} searches maximum."""
    search_state['calls'] = 0
    search_state['cost'] = 0.0
    search_state['max_calls'] = max_searches
    result = app.invoke({'messages': [HumanMessage(content=prompt)]})
    print(f'\nResearch complete. {search_state["calls"]} searches, ${search_state["cost"]:.3f}')
    return result['messages'][-1].content

research_with_sources('best search API for AI agents', max_searches=8)

Python Example

Python
import os, requests
from langchain_core.tools import tool

SH = {'x-api-key': os.environ['SCAVIO_API_KEY'], 'Content-Type': 'application/json'}
budget = {'n': 0, 'max': 5}

@tool
def web_search(query: str) -> str:
    """Search the web for current information."""
    if budget['n'] >= budget['max']:
        return 'Budget reached. Use existing results.'
    data = requests.post('https://api.scavio.dev/api/v1/search',
        headers=SH, json={'query': query, 'country_code': 'us'}).json()
    budget['n'] += 1
    results = data.get('organic_results', [])[:3]
    return '\n'.join(f"{r['title'][:50]}" for r in results)

print(web_search.invoke({'query': 'langgraph tutorial'}))
print(f'Budget: {budget["n"]}/{budget["max"]} (${budget["n"] * 0.005:.3f})')

JavaScript Example

JavaScript
// LangGraph.js equivalent:
const SH = { 'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json' };
let budget = { n: 0, max: 5 };

async function webSearch(query) {
  if (budget.n >= budget.max) return 'Budget reached.';
  const data = await fetch('https://api.scavio.dev/api/v1/search', {
    method: 'POST', headers: SH,
    body: JSON.stringify({ query, country_code: 'us' })
  }).then(r => r.json());
  budget.n++;
  return (data.organic_results || []).slice(0, 3)
    .map(r => r.title.slice(0, 50)).join('\n');
}
console.log(await webSearch('langgraph tutorial'));
console.log(`Budget: ${budget.n}/${budget.max} ($${(budget.n * 0.005).toFixed(3)})`);

Expected Output

JSON
Search results for 'best serp api 2026' (1/5 budget):
1. Scavio - Unified Search API for Developers - Best SERP API with multi-platform...
2. SerpAPI - Google Search API - Reliable Google search results...
3. DataForSEO - SEO Data Provider - Comprehensive SEO data...

LangGraph agent compiled with budget-aware search.

--- Agent Response ---
Based on my research across 3 searches, the top SERP APIs for Python developers...

--- Budget ---
Searches used: 3/5
Cost: $0.015

Related Tutorials

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

Python 3.8+. langgraph and langchain installed. A Scavio API key from scavio.dev. An LLM API key (OpenAI, Anthropic, or local). A Scavio API key gives you 250 free credits per month.

Yes. The free tier includes 250 credits per month, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses LangChain, but you can adapt to your framework of choice.

Start Building

Add Scavio search as a LangGraph tool node with budget-aware execution. Python agent with configurable max search limit.