agentsresearchsearch-api

Deep Research Agent Search Pattern

Deep research agents like Gemini Deep Research make 50-200 searches per task. Pattern: iterative query refinement with structured SERP data at $0.25-$1.00/report.

9 min

The dominant deep research agent pattern in 2026 is search-read-compute: a search API finds relevant URLs, a reader API extracts page content, and a compute sandbox executes analysis code. MiroThinker popularized this with Serper + Jina + E2B. A simpler alternative uses a single API that returns structured results with extracted content, cutting the chain from three services to one.

The three-service pattern

MiroThinker and similar deep research agents use three separate services: Serper finds URLs ($1/1k searches), Jina Reader extracts page content from those URLs ($0-free tier, then usage-based), and E2B provides a code sandbox for analysis ($0.004/min). The agent orchestrates: search for sources, read each source, synthesize findings, run any computations needed.

Python
import requests, os

# Three-service pattern: Serper -> Jina -> E2B

def deep_research_three_service(question: str) -> dict:
    """Search-Read-Compute pipeline using three APIs."""

    # Step 1: Search (Serper) - find relevant URLs
    search_resp = requests.post(
        "https://google.serper.dev/search",
        headers={"X-API-KEY": os.environ["SERPER_API_KEY"]},
        json={"q": question, "num": 5},
        timeout=10,
    )
    urls = [r["link"] for r in search_resp.json().get("organic", [])[:5]]

    # Step 2: Read (Jina) - extract content from each URL
    pages = []
    for url in urls:
        read_resp = requests.get(
            f"https://r.jina.ai/{url}",
            headers={"Accept": "application/json"},
            timeout=15,
        )
        if read_resp.status_code == 200:
            pages.append({
                "url": url,
                "content": read_resp.json().get("content", "")[:3000],
            })

    # Step 3: Compute (E2B or local) - analyze extracted data
    # This step typically sends pages to an LLM for synthesis
    # or runs code in a sandbox for data analysis

    return {
        "question": question,
        "sources": len(pages),
        "pages": pages,
    }

# Cost per research query:
# Serper: $0.001 + Jina: ~$0 (free tier) + E2B: ~$0.01 = ~$0.011/query
# But: 3 API keys, 3 failure points, 3 rate limits to manage

The single-API alternative

If you only need search results with snippets (not full page content), a single structured search API eliminates two of the three services. Most research questions can be answered from SERP snippets, AI Overviews, and People Also Ask data without reading full pages.

Python
import requests, os

def deep_research_single_api(question: str) -> dict:
    """Research pipeline using one API for structured search."""

    resp = requests.post(
        "https://api.scavio.dev/api/v1/search",
        headers={"x-api-key": os.environ["SCAVIO_API_KEY"]},
        json={"query": question, "platform": "google", "country_code": "us"},
        timeout=15,
    )
    data = resp.json()

    research = {
        "question": question,
        "direct_answer": None,
        "sources": [],
        "related_questions": [],
    }

    # AI Overview often contains the synthesized answer already
    ao = data.get("ai_overview")
    if ao:
        research["direct_answer"] = ao.get("text", "")
        research["sources"].extend([
            {"url": s.get("link", ""), "title": s.get("title", "")}
            for s in ao.get("sources", [])
        ])

    # Organic results provide supporting evidence
    for r in data.get("organic_results", [])[:5]:
        research["sources"].append({
            "url": r.get("link", ""),
            "title": r.get("title", ""),
            "snippet": r.get("snippet", ""),
        })

    # PAA gives related angles to explore
    for paa in data.get("people_also_ask", []):
        research["related_questions"].append(paa.get("question", ""))

    return research

# Cost: $0.005/query (1 Scavio credit)
# 1 API key, 1 failure point, 1 rate limit
# Tradeoff: no full page content, only SERP-extracted data

When to use which pattern

Python
decision_matrix = {
    "single_api_wins": [
        "Quick fact-checking (answer is in SERP snippets)",
        "Market research (pricing, feature comparisons from snippets)",
        "Trend monitoring (SERP feature changes over time)",
        "Multi-platform research (Google + Reddit + YouTube in one call)",
        "Agent workflows where latency matters (1 call vs 6+)",
    ],
    "three_service_wins": [
        "Deep technical research (need full documentation pages)",
        "Legal/regulatory research (need complete document text)",
        "Academic research (need full paper content)",
        "Content extraction for RAG (building a knowledge base)",
        "Competitive analysis requiring full page scraping",
    ],
}

# Hybrid: use single API for initial triage,
# then three-service for deep dives on promising leads

Hybrid approach: triage then deep dive

Python
def hybrid_research(question: str, deep_dive_threshold: int = 3) -> dict:
    """Triage with single API, deep-dive on top results if needed."""

    # Quick triage: single API call
    triage = deep_research_single_api(question)

    # If we got a direct answer from AI Overview, done
    if triage["direct_answer"]:
        triage["method"] = "ai_overview"
        return triage

    # If snippets are sufficient (short factual queries), done
    if len(triage["sources"]) >= 3:
        snippet_text = " ".join(s.get("snippet", "") for s in triage["sources"])
        if len(snippet_text) > 500:
            triage["method"] = "snippets"
            return triage

    # Otherwise, deep-dive on top URLs using Jina reader
    for source in triage["sources"][:deep_dive_threshold]:
        try:
            read_resp = requests.get(
                f"https://r.jina.ai/{source['url']}",
                headers={"Accept": "application/json"},
                timeout=15,
            )
            if read_resp.status_code == 200:
                source["full_content"] = read_resp.json().get("content", "")[:3000]
        except Exception:
            source["full_content"] = None

    triage["method"] = "deep_dive"
    return triage

# Average cost: ~$0.01/query (most resolve at triage stage)
# vs. $0.011/query for always-deep-dive

Cost comparison at 1,000 research queries/month

  • Three-service (Serper + Jina + E2B): ~$11/month, 3 API keys, highest data depth
  • Single API (Scavio): $5/month, 1 API key, SERP-depth only
  • Hybrid (Scavio triage + Jina deep dive): ~$7/month, 2 API keys, best cost/depth ratio
  • Exa (semantic search + content): $7/month, 1 API key, different retrieval model

Start with the single-API approach and measure how often your agent actually needs full page content. Most teams find that SERP snippets and AI Overview data resolve 70-80% of research queries without needing a reader service at all.