Search grounding means giving your AI agent access to live web results so it can answer questions about current events, prices, and recent changes without hallucinating. You do not need LangChain, LlamaIndex, or any framework -- a simple Python function that calls a search API and injects results into the prompt works just as well. This tutorial gets a beginner from zero to a grounded agent in under 15 minutes using only the requests library and the Scavio API at $0.005 per search.
Prerequisites
- Python 3.8+ installed
- requests library installed (pip install requests)
- A Scavio API key from scavio.dev (250 free credits/month)
- Any LLM API key (OpenAI, Anthropic, etc.) or a local model
Walkthrough
Step 1: Get your API key and test it
Sign up at scavio.dev and copy your API key. Test it with a simple curl command or Python script to make sure it works.
import requests, os
API_KEY = os.environ.get('SCAVIO_API_KEY', 'your_key_here')
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY, 'Content-Type': 'application/json'},
json={'query': 'hello world', 'country_code': 'us'})
if resp.status_code == 200:
results = resp.json().get('organic_results', [])
print(f'API works. Got {len(results)} results.')
else:
print(f'Error: {resp.status_code} - {resp.text}')Step 2: Write the search function
Create a single function that takes a question and returns formatted search results. This is the core of your grounding system -- just 10 lines of code.
def search_web(question: str) -> str:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY, 'Content-Type': 'application/json'},
json={'query': question, 'country_code': 'us'})
if resp.status_code != 200:
return 'Search failed. Answer from your own knowledge.'
results = resp.json().get('organic_results', [])[:5]
if not results:
return 'No results found.'
return '\n'.join(
f'{r["title"]}\n{r.get("snippet", "")}\nSource: {r["link"]}\n'
for r in results
)Step 3: Build the grounded prompt
Combine the search results with the user question in a prompt template. Tell the LLM to use the search results and cite sources.
def make_prompt(question: str) -> str:
search_results = search_web(question)
return f"""Answer the following question using ONLY the search results below.
If the results do not contain enough info, say so.
Cite your sources with URLs.
Search Results:
{search_results}
Question: {question}
Answer:"""
# Test it:
prompt = make_prompt('What is the cheapest CRM in 2026?')
print(prompt)Step 4: Connect to your LLM
Pass the grounded prompt to any LLM. This example uses OpenAI but works identically with Anthropic, local Ollama, or any chat API.
from openai import OpenAI
client = OpenAI() # uses OPENAI_API_KEY env var
def ask(question: str) -> str:
prompt = make_prompt(question)
response = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': prompt}],
max_tokens=500
)
return response.choices[0].message.content
# Your first grounded query:
answer = ask('What is the cheapest CRM in 2026?')
print(answer)Step 5: Add a conversation loop
Turn the one-shot query into a conversational agent. Each user message gets grounded with fresh search results.
def chat_loop():
print('Grounded Agent (type "quit" to exit)')
print(f'Search cost: $0.005 per question\n')
while True:
question = input('You: ').strip()
if question.lower() in ('quit', 'exit', 'q'):
break
if not question:
continue
answer = ask(question)
print(f'\nAgent: {answer}\n')
if __name__ == '__main__':
chat_loop()Python Example
import os, requests
from openai import OpenAI
API_KEY = os.environ['SCAVIO_API_KEY']
client = OpenAI()
def search_web(question: str) -> str:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY, 'Content-Type': 'application/json'},
json={'query': question, 'country_code': 'us'})
results = resp.json().get('organic_results', [])[:5]
return '\n'.join(f'{r["title"]}\n{r.get("snippet", "")}\nSource: {r["link"]}' for r in results)
def ask(question: str) -> str:
ctx = search_web(question)
prompt = f'Use these search results to answer:\n\n{ctx}\n\nQuestion: {question}'
resp = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': prompt}],
max_tokens=500)
return resp.choices[0].message.content
if __name__ == '__main__':
print(ask('Best free CRM 2026'))JavaScript Example
const API_KEY = process.env.SCAVIO_API_KEY;
async function searchWeb(question) {
const resp = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: question, country_code: 'us' })
});
const data = await resp.json();
return (data.organic_results || []).slice(0, 5)
.map(r => `${r.title}\n${r.snippet || ''}\nSource: ${r.link}`).join('\n\n');
}
async function main() {
const question = 'Best free CRM 2026';
const context = await searchWeb(question);
console.log(`Search context (cost: $0.005):\n${context}`);
// Pass context + question to your LLM of choice
}
main().catch(console.error);Expected Output
API works. Got 10 results.
Grounded Agent (type "quit" to exit)
Search cost: $0.005 per question
You: What is the cheapest CRM in 2026?
Agent: Based on search results, HubSpot CRM remains the most popular
free option in 2026 with unlimited users. For paid plans, Freshsales
starts at $9/user/month. Zoho CRM offers a free tier for up to 3 users.
Source: https://www.hubspot.com/pricing
Source: https://www.freshworks.com/crm/pricing/