ScavioScavio
产品定价文档
登录开始使用
  1. 首页
  2. 教程
  3. 如何为代理即服务构建搜索层
教程

如何为代理即服务构建搜索层

为代理服务平台构建多租户、基于信用的搜索层。兼容 MCP、速率受限且成本跟踪。

获取免费API密钥API文档

代理即服务平台需要一个共享搜索层来​​跟踪每个租户的信用使用情况、实施速率限制并与 MCP 配合使用。本教程构建了一个搜索服务层,该层将 Scavio API 与多租户信用跟踪、每租户速率限制和 MCP 兼容工具定义封装在一起。每个基础搜索费用为 0.005 美元,您可以为您的租户加价。

前置条件

  • Python 3.8+
  • 请求库
  • 来自 scavio.dev 的 Scavio API 密钥
  • 对多租户架构的基本了解

操作指南

步骤 1: 定义租户信用体系

创建用于多租户搜索使用的信用跟踪系统。

Python
import os, requests, json, time
from collections import defaultdict

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

class TenantCredits:
    def __init__(self):
        self.credits = {}  # tenant_id -> remaining credits
        self.usage = defaultdict(list)  # tenant_id -> [{timestamp, query, cost}]

    def add_tenant(self, tenant_id, credits):
        self.credits[tenant_id] = credits
        print(f'Tenant {tenant_id}: {credits} credits allocated')

    def use_credit(self, tenant_id, amount=1):
        if tenant_id not in self.credits:
            return False, 'Tenant not found'
        if self.credits[tenant_id] < amount:
            return False, 'Insufficient credits'
        self.credits[tenant_id] -= amount
        self.usage[tenant_id].append({'time': time.time(), 'cost': amount})
        return True, f'{self.credits[tenant_id]} credits remaining'

    def get_usage(self, tenant_id):
        return {'remaining': self.credits.get(tenant_id, 0),
                'used': len(self.usage.get(tenant_id, [])),
                'total_cost': sum(u['cost'] for u in self.usage.get(tenant_id, []))}

credits = TenantCredits()
credits.add_tenant('tenant_a', 1000)
credits.add_tenant('tenant_b', 500)
print(credits.get_usage('tenant_a'))

步骤 2: 构建限速搜索包装器

创建具有每个租户速率限制和信用检查的搜索功能。

Python
class SearchLayer:
    def __init__(self):
        self.credits = TenantCredits()
        self.rate_limits = {}  # tenant_id -> {max_per_minute, window_start, count}

    def set_rate_limit(self, tenant_id, max_per_minute):
        self.rate_limits[tenant_id] = {'max': max_per_minute, 'start': time.time(), 'count': 0}

    def check_rate_limit(self, tenant_id):
        if tenant_id not in self.rate_limits:
            return True
        rl = self.rate_limits[tenant_id]
        now = time.time()
        if now - rl['start'] > 60:
            rl['start'] = now
            rl['count'] = 0
        if rl['count'] >= rl['max']:
            return False
        rl['count'] += 1
        return True

    def search(self, tenant_id, query, platform=None):
        if not self.check_rate_limit(tenant_id):
            return {'error': 'Rate limit exceeded', 'retry_after': 60}
        ok, msg = self.credits.use_credit(tenant_id)
        if not ok:
            return {'error': msg}
        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()
        return {'results': data.get('organic_results', [])[:5],
                'credits_remaining': self.credits.credits.get(tenant_id, 0),
                'tenant': tenant_id}

layer = SearchLayer()
layer.credits.add_tenant('demo', 100)
layer.set_rate_limit('demo', 30)  # 30 searches/minute
result = layer.search('demo', 'best serp api 2026')
print(f'Results: {len(result.get("results", []))}, Credits: {result.get("credits_remaining")}')

步骤 3: 添加与 MCP 兼容的工具定义

以 MCP 格式定义搜索工具以进行代理集成。

Python
def mcp_tool_definitions():
    """Return MCP-compatible tool definitions for the search layer."""
    return [
        {
            'name': 'search',
            'description': 'Search the web for current information. Supports platforms: google, reddit, youtube, amazon, walmart.',
            'inputSchema': {
                'type': 'object',
                'properties': {
                    'query': {'type': 'string', 'description': 'Search query'},
                    'platform': {'type': 'string', 'enum': ['google', 'reddit', 'youtube', 'amazon', 'walmart'],
                                 'description': 'Search platform (default: google)'}
                },
                'required': ['query']
            }
        },
        {
            'name': 'usage',
            'description': 'Check remaining search credits and usage stats.',
            'inputSchema': {'type': 'object', 'properties': {}}
        }
    ]

def handle_mcp_call(tenant_id, tool_name, args):
    """Handle an MCP tool call from an agent."""
    if tool_name == 'search':
        return layer.search(tenant_id, args['query'], args.get('platform'))
    elif tool_name == 'usage':
        return layer.credits.get_usage(tenant_id)
    return {'error': f'Unknown tool: {tool_name}'}

tools = mcp_tool_definitions()
print(f'MCP tools available: {[t["name"] for t in tools]}')
result = handle_mcp_call('demo', 'search', {'query': 'python tutorial', 'platform': 'reddit'})
print(f'MCP search result: {len(result.get("results", []))} results')

步骤 4: 生成租户使用情况报告

构建用于计费和监控的使用情况报告。

Python
def tenant_report(tenant_id):
    usage = layer.credits.get_usage(tenant_id)
    print(f'\n=== Tenant Report: {tenant_id} ===')
    print(f'  Credits remaining: {usage["remaining"]}')
    print(f'  Searches used: {usage["used"]}')
    print(f'  Total cost (internal): ${usage["total_cost"] * 0.005:.3f}')
    # Calculate billing at markup
    markup = 2.0  # 2x markup
    billed = usage['total_cost'] * 0.005 * markup
    print(f'  Billed to tenant (2x markup): ${billed:.3f}')
    print(f'  Margin: ${billed - usage["total_cost"] * 0.005:.3f}')

def platform_report():
    print(f'\n=== Platform Usage Report ===')
    total_searches = 0
    total_revenue = 0
    for tenant_id in layer.credits.credits:
        usage = layer.credits.get_usage(tenant_id)
        total_searches += usage['used']
        revenue = usage['total_cost'] * 0.005 * 2  # 2x markup
        total_revenue += revenue
        print(f'  {tenant_id}: {usage["used"]} searches, ${revenue:.3f} billed')
    internal_cost = total_searches * 0.005
    print(f'\n  Total searches: {total_searches}')
    print(f'  Internal cost: ${internal_cost:.3f}')
    print(f'  Total revenue: ${total_revenue:.3f}')
    print(f'  Profit: ${total_revenue - internal_cost:.3f}')

# Simulate some usage
for i in range(5):
    layer.search('demo', f'test query {i}')
tenant_report('demo')
platform_report()

Python 示例

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

credits = {'tenant_a': 100}

def tenant_search(tenant_id, query):
    if credits.get(tenant_id, 0) <= 0:
        return {'error': 'No credits'}
    data = requests.post('https://api.scavio.dev/api/v1/search',
        headers=SH, json={'query': query, 'country_code': 'us'}).json()
    credits[tenant_id] -= 1
    print(f'[{tenant_id}] "{query}": {len(data.get("organic_results", []))} results ({credits[tenant_id]} credits left)')
    return data.get('organic_results', [])[:3]

tenant_search('tenant_a', 'serp api')

JavaScript 示例

JavaScript
const SH = { 'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json' };
const credits = { tenant_a: 100 };

async function tenantSearch(tenantId, query) {
  if ((credits[tenantId] || 0) <= 0) return { error: 'No credits' };
  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());
  credits[tenantId]--;
  console.log(`[${tenantId}] "${query}": ${(data.organic_results||[]).length} results (${credits[tenantId]} left)`);
  return (data.organic_results || []).slice(0, 3);
}
await tenantSearch('tenant_a', 'serp api');

预期输出

JSON
Tenant demo: 100 credits allocated

Results: 5, Credits: 99
MCP tools available: ['search', 'usage']
MCP search result: 5 results

=== Tenant Report: demo ===
  Credits remaining: 93
  Searches used: 7
  Total cost (internal): $0.035
  Billed to tenant (2x markup): $0.070
  Margin: $0.035

=== Platform Usage Report ===
  demo: 7 searches, $0.070 billed
  Total searches: 7
  Internal cost: $0.035
  Profit: $0.035

相关教程

  • 如何构建自定义 MCP 搜索服务器
  • 如何构建具有预算控制的 LangGraph 搜索代理
  • 如何为搜索结果构建代理上下文桥

常见问题

大多数开发者在15到30分钟内完成本教程。您需要一个Scavio API密钥(免费套餐即可)和可用的Python或JavaScript环境。

Python 3.8+. 请求库. 来自 scavio.dev 的 Scavio API 密钥. 对多租户架构的基本了解. Scavio API密钥注册即送50个免费积分。

可以。免费套餐注册即送50个积分,完全足够完成本教程并构建一个可运行的原型解决方案。

Scavio提供原生LangChain包(langchain-scavio)、MCP服务器以及适用于任何HTTP客户端的REST API。本教程使用 the raw REST API, 但您可以根据需要适配您选择的框架。

相关资源

Comparison

MCP Search Integration vs Direct API Integration

Read more
Best Of

Google I/O 2026 AI模式变化后最佳搜索API

Read more
Glossary

搜索 API 供应商格局(2026)

Read more
Best Of

2026 年 MCP 服务器最佳搜索 API

Read more
Use Case

MCP 自定义搜索服务器

Read more
Use Case

用于业务运营的 MCP 自定义 API 集成

Read more

开始构建

为代理服务平台构建多租户、基于信用的搜索层。兼容 MCP、速率受限且成本跟踪。

获取免费API密钥阅读文档
ScavioScavio

面向AI智能体的实时搜索API。搜索所有平台,不仅仅是Google。

产品

  • 功能
  • 定价
  • 控制台
  • 联盟计划

开发者

  • 文档
  • API参考
  • 快速开始
  • MCP集成
  • Python SDK

替代方案

  • Tavily替代方案
  • SerpAPI替代方案
  • Firecrawl替代方案
  • Exa替代方案

工具

  • JSON格式化
  • cURL转代码
  • Token计数器
  • 全部工具

© 2026 Scavio. 保留所有权利。

Featured on TAAFT
服务条款隐私政策