Hermes v0.13.0 附带了一个损坏的网络搜索工具,该工具会返回空结果或许多查询超时。该问题源于其默认搜索后端受到速率限制且不可靠。您无需等待补丁,只需几分钟即可换入工作的搜索 API 后端。本教程介绍如何用 Scavio API 替换 Hermes 搜索工具,该工具以每次查询 0.005 美元的价格可靠地返回结构化 SERP 数据。该修复只需要更改搜索功能,无需更改其他代理代码。
前置条件
- 安装 Hermes v0.13.x
- 已安装 Python 3.9+
- 请求已安装库
- 来自 scavio.dev 的 Scavio API 密钥
操作指南
步骤 1: 诊断损坏的搜索工具
首先,通过 Hermes 运行测试查询并检查工具输出来确认搜索问题。典型的失败模式是空结果、超时错误或格式错误的 JSON。
# 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}')步骤 2: 构建替换搜索功能
创建一个与 Hermes 搜索工具界面相匹配的直接替代品。该函数接受一个查询字符串并以 Hermes 期望的格式返回结果。
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"]}')步骤 3: 修补Hermes搜索工具注册
覆盖 Hermes 代理配置中的默认搜索工具。这无需修改 Hermes 源代码即可替换损坏的后端。
# 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步骤 4: 端到端验证修复是否有效
通过修补后的 Hermes 代理运行测试查询,以确认搜索正常工作。测试边缘情况,例如空结果和长查询。
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 示例
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 示例
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();预期输出
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