Local multi-agent coding setups using Pi, llama-swap, or similar tools generate code in a private, offline environment. The problem: they hallucinate API signatures, invent non-existent packages, and use deprecated patterns. Adding a search tool that checks current documentation before generating code fixes this. This tutorial connects your local multi-agent setup to the Scavio API ($0.005/search) so agents can verify APIs, check package versions, and reference current docs.
Prerequisites
- A local multi-agent setup (Pi, llama-swap, or similar)
- Python 3.9+ installed
- requests library installed
- A Scavio API key from scavio.dev
Walkthrough
Step 1: Build the documentation search tool
Create a search function optimized for code documentation lookups. It targets specific documentation sites and formats results for code context.
import os, requests
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
URL = 'https://api.scavio.dev/api/v1/search'
H = {'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'}
def search_docs(query: str, language: str = 'python') -> str:
"""Search for code documentation and API references."""
# Add language context
doc_sites = {
'python': 'docs.python.org OR pypi.org OR readthedocs.io',
'javascript': 'developer.mozilla.org OR npmjs.com OR nodejs.org',
'typescript': 'typescriptlang.org OR npmjs.com',
'rust': 'docs.rs OR crates.io',
}
site_filter = doc_sites.get(language, '')
full_query = f'{query} {language} {site_filter}'.strip()
resp = requests.post(URL, headers=H,
json={'query': full_query, 'country_code': 'us', 'num_results': 5})
results = resp.json().get('organic_results', [])
if not results:
return f'No documentation found for: {query}'
return '\n\n'.join(
f'[{i+1}] {r["title"]}\n{r.get("snippet", "")}\nURL: {r["link"]}'
for i, r in enumerate(results)
)
# Test: search for API documentation
print(search_docs('requests post json headers', 'python'))
print('---')
print(search_docs('fetch api post request', 'javascript'))Step 2: Add package version checking
Before using a package in generated code, verify it exists and check the current version. This prevents the agent from importing non-existent packages.
def check_package(name: str, language: str = 'python') -> dict:
"""Verify a package exists and get current version info."""
if language == 'python':
query = f'pypi.org {name} package'
elif language in ('javascript', 'typescript'):
query = f'npmjs.com {name} package'
else:
query = f'{name} package {language}'
resp = requests.post(URL, headers=H,
json={'query': query, 'country_code': 'us', 'num_results': 3})
results = resp.json().get('organic_results', [])
if not results:
return {'name': name, 'exists': False}
# Check if pypi/npm appears in results
registry_hit = any('pypi.org' in r.get('link', '') or 'npmjs.com' in r.get('link', '')
for r in results)
return {
'name': name,
'exists': registry_hit,
'top_result': results[0]['title'],
'snippet': results[0].get('snippet', '')[:150],
'url': results[0]['link'],
}
# Test packages
for pkg in ['requests', 'fastapi', 'nonexistent-fake-pkg-xyz']:
result = check_package(pkg)
status = 'EXISTS' if result['exists'] else 'NOT FOUND'
print(f'[{status}] {pkg}: {result.get("top_result", "N/A")[:50]}')Step 3: Create the agent tool interface
Define tools that your multi-agent system can call. The search_docs and check_package tools integrate with any OpenAI-compatible tool calling setup.
import json
AGENT_TOOLS = [
{
'type': 'function',
'function': {
'name': 'search_docs',
'description': 'Search for programming documentation, API references, and code examples. Use BEFORE writing code that uses external libraries or APIs.',
'parameters': {
'type': 'object',
'properties': {
'query': {'type': 'string', 'description': 'What to search for (e.g., "fastapi dependency injection")'},
'language': {'type': 'string', 'enum': ['python', 'javascript', 'typescript', 'rust'], 'description': 'Programming language context'}
},
'required': ['query']
}
}
},
{
'type': 'function',
'function': {
'name': 'check_package',
'description': 'Verify a package exists before importing it. Prevents hallucinated package names.',
'parameters': {
'type': 'object',
'properties': {
'name': {'type': 'string', 'description': 'Package name'},
'language': {'type': 'string', 'enum': ['python', 'javascript'], 'description': 'Package ecosystem'}
},
'required': ['name']
}
}
}
]
def handle_tool_call(name: str, args: dict) -> str:
if name == 'search_docs':
return search_docs(args['query'], args.get('language', 'python'))
elif name == 'check_package':
result = check_package(args['name'], args.get('language', 'python'))
return json.dumps(result)
return 'Unknown tool'
print('Agent tools defined:', [t['function']['name'] for t in AGENT_TOOLS])Step 4: Wire into the multi-agent loop
Connect the tools to your local multi-agent system. The coding agent searches docs before writing code, and the review agent checks packages before approving.
def coding_agent_loop(task: str, model: str = 'llama3') -> str:
"""A coding agent that searches docs before generating code."""
llm_url = 'http://localhost:11434/v1/chat/completions'
messages = [
{'role': 'system', 'content': (
'You are a coding assistant. ALWAYS use search_docs to check API '
'signatures before writing code. ALWAYS use check_package to verify '
'packages exist before importing them. Write working, tested code.'
)},
{'role': 'user', 'content': task}
]
for turn in range(5):
resp = requests.post(llm_url, json={
'model': model, 'messages': messages,
'tools': AGENT_TOOLS, 'max_tokens': 1024
})
msg = resp.json()['choices'][0]['message']
messages.append(msg)
if not msg.get('tool_calls'):
return msg.get('content', '')
for tc in msg['tool_calls']:
args = json.loads(tc['function']['arguments']) if isinstance(tc['function']['arguments'], str) else tc['function']['arguments']
result = handle_tool_call(tc['function']['name'], args)
messages.append({'role': 'tool', 'tool_call_id': tc['id'], 'content': result})
return messages[-1].get('content', 'Max turns reached')
# Test the coding agent
code = coding_agent_loop('Write a Python function that fetches JSON from an API using httpx')
print(code[:500])Python Example
import os, requests, json
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'}
def search_docs(query, lang='python'):
resp = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'query': f'{query} {lang} documentation', 'country_code': 'us', 'num_results': 3})
return '\n'.join(f'[{i+1}] {r["title"]}: {r.get("snippet","")}'
for i, r in enumerate(resp.json().get('organic_results', [])))
def check_pkg(name, lang='python'):
registry = 'pypi.org' if lang == 'python' else 'npmjs.com'
resp = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'query': f'{registry} {name}', 'country_code': 'us', 'num_results': 1})
results = resp.json().get('organic_results', [])
exists = any(registry in r.get('link', '') for r in results)
print(f"{'EXISTS' if exists else 'NOT FOUND'}: {name}")
print(search_docs('httpx async client'))
check_pkg('httpx')
check_pkg('fake-nonexistent-pkg')JavaScript Example
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;
async function searchDocs(query, lang = 'javascript') {
const resp = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: `${query} ${lang} documentation`, country_code: 'us', num_results: 3 })
});
return ((await resp.json()).organic_results || []).map((r, i) => `[${i+1}] ${r.title}: ${r.snippet || ''}`).join('\n');
}
async function checkPkg(name) {
const resp = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: `npmjs.com ${name}`, country_code: 'us', num_results: 1 })
});
const results = (await resp.json()).organic_results || [];
console.log(`${results.some(r => r.link.includes('npmjs.com')) ? 'EXISTS' : 'NOT FOUND'}: ${name}`);
}
searchDocs('fetch api post').then(console.log);
checkPkg('express');Expected Output
[EXISTS] requests: requests 2.32.0 - PyPI
[EXISTS] fastapi: fastapi - PyPI - A modern, fast web framework
[NOT FOUND] nonexistent-fake-pkg-xyz
Agent tools defined: ['search_docs', 'check_package']
[1] requests - PyPI: HTTP library for Python
Requests allows you to send HTTP requests extremely easily...
URL: https://pypi.org/project/requests/