Tutorial

How to Fix Hermes v0.13.0 Broken Search with a Search API

Replace the broken Hermes v0.13.0 search tool with a working search API backend. Quick fix guide with drop-in Python code.

Hermes v0.13.0 shipped with a broken web search tool that returns empty results or times out for many queries. The issue stems from its default search backend being rate-limited and unreliable. Rather than waiting for a patch, you can swap in a working search API backend in minutes. This tutorial shows how to replace the Hermes search tool with the Scavio API, which returns structured SERP data reliably at $0.005 per query. The fix requires changing only the search function -- no other agent code changes needed.

Prerequisites

  • Hermes v0.13.x installed
  • Python 3.9+ installed
  • requests library installed
  • A Scavio API key from scavio.dev

Walkthrough

Step 1: Diagnose the broken search tool

First, confirm the search issue by running a test query through Hermes and checking the tool output. The typical failure modes are empty results, timeout errors, or malformed JSON.

Python
# Test the current Hermes search tool:
# In your Hermes agent, run a query that requires search:
# "What is the current price of Bitcoin?"
#
# Common error outputs:
# - {"results": []}  (empty results)
# - TimeoutError: Search request timed out after 30s
# - JSONDecodeError: Expecting value (malformed response)
#
# If you see any of these, the search backend is broken.

import requests

# Quick test of the default Hermes search endpoint:
try:
    resp = requests.get('http://localhost:8080/search?q=test', timeout=10)
    print(f'Status: {resp.status_code}')
    print(f'Results: {len(resp.json().get("results", []))}')
except Exception as e:
    print(f'Search broken: {e}')

Step 2: Build the replacement search function

Create a drop-in replacement that matches the Hermes search tool interface. The function takes a query string and returns results in the format Hermes expects.

Python
import requests, os

SCAVIO_KEY = os.environ['SCAVIO_API_KEY']

def hermes_search_replacement(query: str, num_results: int = 5) -> dict:
    """Drop-in replacement for broken Hermes search tool.
    Returns results in Hermes-compatible format."""
    try:
        resp = requests.post('https://api.scavio.dev/api/v1/search',
            headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
            json={'query': query, 'country_code': 'us'},
            timeout=15)
        resp.raise_for_status()
        data = resp.json()
        results = [{
            'title': r['title'],
            'url': r['link'],
            'content': r.get('snippet', ''),
        } for r in data.get('organic_results', [])[:num_results]]
        return {'results': results}
    except Exception as e:
        return {'results': [], 'error': str(e)}

# Test the replacement:
result = hermes_search_replacement('current bitcoin price')
print(f'Results: {len(result["results"])}')
for r in result['results']:
    print(f'  {r["title"]}')

Step 3: Patch the Hermes search tool registration

Override the default search tool in your Hermes agent configuration. This replaces the broken backend without modifying Hermes source code.

Python
# Option 1: Override in your agent setup script
# Find where Hermes registers its search tool and replace it:

def register_fixed_search(agent):
    """Replace the broken Hermes search with working API."""
    # Remove the broken tool
    if hasattr(agent, 'tools'):
        agent.tools = {name: tool for name, tool in agent.tools.items()
                       if name != 'web_search'}
    # Register the working replacement
    agent.register_tool(
        name='web_search',
        description='Search the web for current information.',
        function=hermes_search_replacement,
        parameters={
            'query': {'type': 'string', 'description': 'Search query'},
            'num_results': {'type': 'integer', 'description': 'Number of results', 'default': 5}
        }
    )
    print('Search tool replaced successfully')

# Option 2: Environment variable override
# Some Hermes configs support:
# HERMES_SEARCH_BACKEND=custom
# HERMES_SEARCH_ENDPOINT=https://api.scavio.dev/api/v1/search

Step 4: Verify the fix works end to end

Run test queries through the patched Hermes agent to confirm search works correctly. Test edge cases like empty results and long queries.

Python
def verify_search_fix():
    test_cases = [
        ('current bitcoin price', True),
        ('best python frameworks 2026', True),
        ('xyznonexistentquery12345', False),  # should return empty gracefully
        ('a' * 500, False),  # very long query
    ]
    passed = 0
    for query, expect_results in test_cases:
        result = hermes_search_replacement(query)
        has_results = len(result.get('results', [])) > 0
        has_error = 'error' in result
        if expect_results and has_results:
            status = 'PASS'
            passed += 1
        elif not expect_results and not has_error:
            status = 'PASS'
            passed += 1
        else:
            status = 'FAIL'
        print(f'[{status}] "{query[:40]}" -> {len(result.get("results", []))} results')
    print(f'\n{passed}/{len(test_cases)} tests passed')
    print(f'Cost: ${len(test_cases) * 0.005:.3f}')

verify_search_fix()

Python Example

Python
import os, requests

SCAVIO_KEY = os.environ['SCAVIO_API_KEY']

def hermes_search(query: str, num_results: int = 5) -> dict:
    try:
        resp = requests.post('https://api.scavio.dev/api/v1/search',
            headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
            json={'query': query, 'country_code': 'us'}, timeout=15)
        results = [{'title': r['title'], 'url': r['link'], 'content': r.get('snippet', '')}
                   for r in resp.json().get('organic_results', [])[:num_results]]
        return {'results': results}
    except Exception as e:
        return {'results': [], 'error': str(e)}

# Quick test
for q in ['bitcoin price', 'python tutorial', 'nonexistent12345']:
    r = hermes_search(q)
    print(f'{q}: {len(r["results"])} results')

JavaScript Example

JavaScript
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;

async function hermesSearch(query, numResults = 5) {
  try {
    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, country_code: 'us' })
    });
    const data = await resp.json();
    return { results: (data.organic_results || []).slice(0, numResults)
      .map(r => ({ title: r.title, url: r.link, content: r.snippet || '' })) };
  } catch (e) {
    return { results: [], error: e.message };
  }
}

async function main() {
  for (const q of ['bitcoin price', 'python tutorial']) {
    const r = await hermesSearch(q);
    console.log(`${q}: ${r.results.length} results`);
  }
}

main();

Expected Output

JSON
Search broken: TimeoutError: Search request timed out after 10s

Results: 5
  Bitcoin Price Today - Live BTC Chart
  BTC/USD - Bitcoin Price & Market Cap

[PASS] "current bitcoin price" -> 5 results
[PASS] "best python frameworks 2026" -> 5 results
[PASS] "xyznonexistentquery12345" -> 0 results
[PASS] "aaaaaaaaaa..." -> 0 results

4/4 tests passed
Cost: $0.020

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.

Hermes v0.13.x installed. Python 3.9+ installed. requests library installed. A Scavio API key from scavio.dev. 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 the raw REST API, but you can adapt to your framework of choice.

Start Building

Replace the broken Hermes v0.13.0 search tool with a working search API backend. Quick fix guide with drop-in Python code.