Skip to main content
Glama
JerryLiu369

agent-web-search

Agent Web Search

Agent-native web search for AI agents — aggregating model-native search and agent search providers, not traditional search engines.

English | 简体中文

Python 3.10+ PyPI CI MCP 2.x License: MIT

Works with Codex CLI, Claude Code, OpenCode, Hermes, ordinary shell scripts, Python applications, and remote Streamable HTTP MCP clients.

Use with an agent · Providers · Shared interface · Configuration · Other interfaces · Troubleshooting · Architecture · Development


Agent Web Search gives an agent two ways to reach the same provider-neutral search core: a native MCP tool, or a CLI taught through a standard Agent Skill.

This is not a Google/Bing/Baidu metasearch wrapper. Traditional search aggregation fans a keyword query out to conventional engines and merges their result pages. Agent Web Search instead aggregates search capabilities built for agents: model-native web grounding, agent-oriented search APIs, and context-ready sources that accept natural-language questions and return answers, citations, or structured evidence in forms an agent can use directly. DDGS is the only conventional search backend in the current provider set.

Natural-language question
             │
             ▼
        SearchEngine
       ┌─────┼──────────────┐
       ▼     ▼              ▼
     DDGS  Model providers  Agent search providers
           ARK · Gemini     Exa · Parallel · Brave
           Grok · DeepSeek  Perplexity · Tavily · You.com
           Codex Alpha      Zhipu Web Search
           Zhipu Chat

Traditional search aggregation (Google/Bing/Baidu wrappers, scraped SERPs) sends a keyword query to conventional engines and merges result pages. Agent Web Search instead aggregates search capabilities built for agents: one tool call returns structured, citation-ready evidence — or, through model-native grounding providers, a synthesized answer with explicit citations. A measured benchmark shows the practical difference: on a natural-language Chinese query asking for official sources, conventional SERP backends returned no government-domain results in the top 5, while the grounding provider returned the 海关总署 figures with a working citation.

  • Agent-native by design. The primary interface is a complete natural-language question, not a thin keyword fan-out to Google, Bing, or Baidu.

  • Model-native search backends. ARK, Gemini, Grok, DeepSeek, Zhipu Chat Search, and Codex Alpha can combine web retrieval with model-generated synthesis and explicit citations.

  • Agent search providers. Exa, Parallel, Brave, Perplexity, Tavily, You.com, and Zhipu Web Search expose search APIs intended to provide structured, citation-friendly, or context-ready evidence to downstream agents.

  • One provider-neutral contract. Every backend is available through the same MCP tool, CLI, Python API, and normalized results; model-backed providers may also return an answer.

  • Independent providers. Selected providers run concurrently, and one provider's failure never discards another provider's successful result.

  • DDGS remains a simple fallback. DDGS is the only conventional search backend; it requires no API key and keeps the project usable without paid provider credentials. Exa and Parallel are also keyless by default.

  • No telemetry, no shared secrets. Provider keys stay in runtime environment variables; there is no shared API-key service.

Providers

The provider list is intentionally split by the kind of search capability it provides. Only DDGS is a conventional search backend; the other two groups are built around model-native grounding or agent-facing search services.

Free, keyless defaults: DDGS, Exa, and Parallel all work without an API key. Exa and Parallel automatically use their free MCP transports until a paid API key is provided.

Traditional search backend

Provider

Website

Search backend

API key

Enabled by default

DDGS

DuckDuckGo

Conventional DuckDuckGo search

Free · no key required

Yes

Model providers

These providers use a model-native search or grounding surface. Their responses can include a model-generated answer together with citations or other explicit search evidence.

Provider

Website

Model-native search surface

API key

Enabled by default

ARK

Volcengine Ark

Responses API with Doubao web-search grounding

ARK_API_KEY

No

Codex Alpha (experimental)

Alpha Search-compatible gateway

Model-backed Alpha Search surface

AGENT_WEB_SEARCH_CODEX_ALPHA_API_KEY

No

DeepSeek

DeepSeek API

Anthropic Messages API with native web search

DEEPSEEK_API_KEY

No

Gemini

Google AI

Gemini Google Search grounding

GEMINI_API_KEY

No

Grok

xAI

xAI web search and X Search

XAI_API_KEY

No

Zhipu Chat Search

Zhipu AI

GLM Chat Completions with native web search

ZHIPU_CHAT_SEARCH_API_KEY

No

Agent search providers

These providers expose search services for agent consumption: natural-language queries, structured source rows, high-signal excerpts, or citation-friendly metadata rather than a conventional search-page experience.

Provider

Website

Agent-facing search surface

API key

Enabled by default

Exa

Exa

Semantic Search API or free MCP fallback

Free without key · optional EXA_API_KEY

Yes

Parallel

Parallel

Context-oriented search API or free MCP

Free without key · optional PARALLEL_API_KEY

Yes

Brave

Brave Search

Structured Web Search API

BRAVE_SEARCH_API_KEY

No

Perplexity

Perplexity API

Native structured Search API

PERPLEXITY_API_KEY

No

Tavily

Tavily

Agent-oriented Search API

TAVILY_API_KEY

No

You.com

You.com API

Unified web and news Search API

YDC_API_KEY

No

Zhipu Web Search

Zhipu AI

Standalone structured Web Search API

ZHIPU_WEB_SEARCH_API_KEY

No

The provider architecture is intentionally open: another search-capable backend can be added without changing the MCP, Hermes, CLI, or Python-facing interfaces.

Use with an agent

Requirements: Python 3.10+. The default providers — DDGS, Exa, and Parallel — need no API key. Choose one integration shape for your agent; both use the same package and search engine. The PyPI package installs both agent-web-search-mcp and agent-web-search commands.

Option 1: MCP

Choose MCP when the agent supports tool servers and you want typed discovery, protocol-level errors, or remote access. The same agent-web-search-mcp command supports local stdio and stateless Streamable HTTP.

Local stdio MCP

Install the package once:

# Recommended isolated installation
pipx install agent-web-search-mcp

# Or install into the active Python environment
python -m pip install agent-web-search-mcp

Then configure the MCP client to launch agent-web-search-mcp:

{
  "mcpServers": {
    "agent-web-search": {
      "command": "agent-web-search-mcp",
      "args": []
    }
  }
}

If uvx is already available, a client can run the package without a persistent install by using command uvx with args ["agent-web-search-mcp"].

# Codex CLI
codex mcp add agent-web-search -- agent-web-search-mcp

# Claude Code
claude mcp add agent-web-search -- agent-web-search-mcp

OpenCode:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "agent-web-search": {
      "type": "local",
      "command": ["agent-web-search-mcp"],
      "enabled": true
    }
  }
}

Remote MCP over HTTPS

Use one of the deployment buttons at the top of this README, or run the same server yourself:

python -c "import secrets; print(secrets.token_urlsafe(32))"
export AGENT_WEB_SEARCH_AUTH_TOKEN="<your-generated-token>"
agent-web-search-mcp --transport http

The server exposes authenticated POST /mcp and public GET /healthz. A remote MCP client connects like this:

{
  "mcpServers": {
    "agent-web-search": {
      "url": "https://your-deployment.example/mcp",
      "headers": {
        "Authorization": "Bearer your-deployment-token"
      }
    }
  }
}

Every public deployment must set AGENT_WEB_SEARCH_AUTH_TOKEN to at least 32 characters. The server is stateless and does not create MCP-Session-Id values.

Option 2: CLI + Skill

Choose this shape when the agent already has shell access and supports Agent Skills. The Skill teaches the agent how to invoke the CLI, select controls, interpret results, and handle structured failures; no MCP configuration is needed.

  1. Install the CLI:

    pipx install agent-web-search-mcp
    # Or: python -m pip install agent-web-search-mcp
  2. Install the included agent-web-search Skill:

    npx skills add JerryLiu369/agent-web-search --skill agent-web-search

    If the agent does not use the skills installer, copy skills/agent-web-search into that client's Skills directory.

  3. Verify the CLI, then let the agent search:

    agent-web-search --version
    agent-web-search "What changed in the latest OpenAI Codex CLI?"

The CLI writes one JSON document to stdout on success. If every provider fails, it writes the shared all_providers_failed JSON to stderr and exits with status 1, so shell-capable agents can distinguish a real failure from empty results.

| CLI option | MCP argument | Values | Default | | --- | --- | --- | | positional QUERY | query | 1–4,000 character natural-language question | required | | --provider (repeatable) | providers | enabled provider names | all enabled | | --max-results | max_results | 1–20 | 10 | | --time-range | time_range | d, w, m, y | — | | --grok-search-mode | grok_search_mode | web_search, x_search, both | web_search |

pipx install 'git+https://github.com/JerryLiu369/agent-web-search.git'
IMPORTANT

Do not place API keys in shell history, source code, Git commits, screenshots, or checked-in MCP configuration. Supply them through server-side or local environment variables.

Shared request and response

MCP exposes one tool named web_search; the CLI maps to the same inputs.

Argument

Type

Required

Default

Description

query

string, 1–4,000 characters

Yes

Complete natural-language search question

max_results

integer, 1–20

No

10

Desired maximum number of results

time_range

d, w, m, y

No

Past day, week, month, or year

providers

string array

No

All enabled

Narrow the request to enabled providers

grok_search_mode

web_search, x_search, both

No

web_search

Available only when Grok is enabled

Example call:

{
  "query": "GPU kernel generation papers from the past month",
  "max_results": 5,
  "time_range": "m",
  "providers": ["ddgs", "exa"]
}

Provider selection has two levels:

  1. AGENT_WEB_SEARCH_PROVIDERS defines the provider set when the process starts.

  2. The request-level providers argument may narrow that set, but cannot enable a provider that was disabled at startup.

Response format

Each selected provider that succeeds appears under providers; failed providers are omitted:

{
  "query": "GPU kernel generation papers from the past month",
  "providers": {
    "ddgs": {
      "results": [
        {
          "title": "Example result",
          "url": "https://example.com/paper",
          "description": "Excerpt of the matching page",
          "published_at": "2026-08-02"
        }
      ]
    }
  }
}

Field

Meaning

answer

Provider-generated prose answer, when the backend produces one; omitted otherwise

results

Result rows: title, url, description, plus optional published_at and author

If every selected provider fails, MCP returns a tool error. The CLI writes the same payload to stderr and exits with status 1. Both use the stable code all_providers_failed and include per-provider diagnostics:

{
  "error": {
    "code": "all_providers_failed",
    "message": "All enabled search providers failed. Check provider configuration, credentials, quotas, and network access.",
    "provider_errors": {
      "ddgs": "RuntimeError: rate limited"
    }
  },
  "query": "GPU kernel generation papers from the past month"
}

Python API

The CLI, MCP servers, and Hermes plugin are thin wrappers around agent_web_search.SearchEngine, which is the public Python API. SearchRequest accepts the same fields as the MCP tool arguments:

from agent_web_search import SearchEngine, SearchRequest

engine = SearchEngine()  # reads AGENT_WEB_SEARCH_* variables at construction

response = engine.search(
    SearchRequest(query="latest MCP spec changes", max_results=5, time_range="m")
)

for name, provider in response.providers.items():
    print(f"{name}: searched={provider.searched}, results={len(provider.results)}")

if response.all_providers_failed:
    print(response.failed_provider_errors)

Configuration

Configuration is read from environment variables when the CLI, MCP server, or Hermes plugin starts. Restart the process after changing provider settings. See .env.example for a commented template of every variable.

General settings

Variable

Default

Purpose

AGENT_WEB_SEARCH_PROVIDERS

ddgs,exa,parallel

Comma-separated startup-enabled provider set

AGENT_WEB_SEARCH_TIMEOUT

60

Socket timeout for a single upstream HTTP call. Multi-step providers multiply it: keyless Parallel makes up to 3 calls (worst case 3×), ARK may append a continuation call (worst case 2×), so the whole search can take up to 3 × this value

Example:

export AGENT_WEB_SEARCH_PROVIDERS="ddgs,exa,brave"
export AGENT_WEB_SEARCH_TIMEOUT="30"
$env:AGENT_WEB_SEARCH_PROVIDERS = "ddgs,exa,brave"
$env:AGENT_WEB_SEARCH_TIMEOUT = "30"

HTTP transport settings

Variable

Default

Purpose

AGENT_WEB_SEARCH_MCP_TRANSPORT

stdio

stdio or http; --transport may override it

AGENT_WEB_SEARCH_HTTP_HOST

0.0.0.0

HTTP bind host for container deployments

AGENT_WEB_SEARCH_HTTP_PORT

PORT or 8000

HTTP bind port; explicit value overrides platform PORT

AGENT_WEB_SEARCH_AUTH_TOKEN

Required HTTP Bearer Token, at least 32 characters

AGENT_WEB_SEARCH_ALLOW_ANONYMOUS

false

Explicitly disables HTTP auth for trusted/demo environments

AGENT_WEB_SEARCH_HTTP_ALLOWED_HOSTS

Optional comma-separated Host allowlist

AGENT_WEB_SEARCH_HTTP_ALLOWED_ORIGINS

Optional comma-separated Origin allowlist; requires allowed hosts

AGENT_WEB_SEARCH_HTTP_LOG_LEVEL

info

Uvicorn log level for the container server

HTTP settings remain environment-only; the deployment files do not introduce a second application configuration format.

Provider settings

Provider-specific settings below include the credential and model controls for all providers. The supported-provider overview above is grouped by capability; this section is the detailed configuration reference.

1. DDGS

DDGS uses DuckDuckGo and requires no API key or provider-specific environment variables. The ddgs Python dependency is installed with the package.

2. Exa

Exa supports both paid and keyless modes.

Variable

Required

Purpose

EXA_API_KEY

No

Uses the paid Search API when present

EXA_MCP_URL

No

Overrides the free MCP endpoint when no API key is set

Without EXA_API_KEY, Exa falls back to its free MCP endpoint on a best-effort basis. The paid API generally provides higher quota and reliability.

3. Parallel

Parallel returns information-dense excerpts ranked for LLM context. One parallel provider automatically selects its transport:

  • Without a key, it uses Parallel's free Search MCP.

  • With PARALLEL_API_KEY, it uses the paid Search REST API.

Both transports map excerpts into the common result description, so the calling agent does not need to distinguish parallel-free from parallel.

Variable

Required

Purpose

PARALLEL_API_KEY

No

Enables the paid API; omit it to use the free MCP

Parallel is enabled by default and its key is optional.

Volcengine ARK uses model-backed search grounding through the Responses API. Add ark to AGENT_WEB_SEARCH_PROVIDERS after providing the key.

Variable

Required

Purpose

ARK_API_KEY

Yes

One key, or multiple comma/newline-separated keys

AGENT_WEB_SEARCH_ARK_MODELS

No

Comma/newline-separated ARK model IDs

One model stays fixed; multiple models are selected round-robin for successive requests. When multiple ARK keys are configured, a key is selected per request.

Agent Web Search does not require participation in a rewards program. ARK users may optionally review the official Volcengine Collaboration Rewards Program. Quota, supported models, validity periods, and data-authorization terms can change. Check the official terms before opting in. Participation is not required to use Agent Web Search.

5. Brave

Variable

Required

Purpose

BRAVE_SEARCH_API_KEY

Yes

Brave Web Search API credential

Add brave to AGENT_WEB_SEARCH_PROVIDERS after providing the key.

6. Gemini

Variable

Required

Purpose

GEMINI_API_KEY

Yes

Google AI API credential

AGENT_WEB_SEARCH_GEMINI_MODELS

No

Comma/newline-separated Gemini model IDs

Gemini maps common result and time controls into best-effort prompt constraints. One configured model stays fixed; multiple models are selected round-robin for successive requests.

7. Grok

Variable

Required

Purpose

XAI_API_KEY

Yes

xAI API credential

AGENT_WEB_SEARCH_GROK_MODELS

No

Comma/newline-separated Grok model IDs

One configured model stays fixed; multiple models are selected round-robin for successive requests.

When Grok is enabled, the public tool schema adds grok_search_mode:

  • web_search searches the web.

  • x_search searches X with native date filters when available.

  • both exposes both server-side tools in one request and lets Grok choose; it does not issue two independent model requests.

8. Codex Alpha (experimental)

The codex_alpha provider uses only a gateway API key and a complete endpoint implementing /v1/alpha/search; it does not handle Codex OAuth tokens. Set the endpoint, key, and optional model, then add codex_alpha to AGENT_WEB_SEARCH_PROVIDERS:

Variable

Required

Purpose

AGENT_WEB_SEARCH_CODEX_ALPHA_ENDPOINT

Yes

Complete Alpha Search endpoint URL

AGENT_WEB_SEARCH_CODEX_ALPHA_API_KEY

Yes

Gateway Bearer API key

AGENT_WEB_SEARCH_CODEX_ALPHA_MODEL

No

Model ID, default gpt-5.6-luna

The provider sends a normal search_query command and returns standard web search results.

9. DeepSeek

DeepSeek uses the official Anthropic-compatible Messages API and the native web_search_20250305 server tool. It preserves the final model-generated text and maps only explicit web_search_result blocks into normalized results. A valid response may therefore have an answer with an empty results list.

Variable

Required

Purpose

DEEPSEEK_API_KEY

Yes

DeepSeek API credential

AGENT_WEB_SEARCH_DEEPSEEK_BASE_URL

No

Anthropic API base URL; defaults to https://api.deepseek.com/anthropic

AGENT_WEB_SEARCH_DEEPSEEK_MODELS

No

Comma/newline-separated model IDs; defaults to deepseek-v4-flash

Add deepseek to AGENT_WEB_SEARCH_PROVIDERS after providing the key. The provider appends /v1/messages to the configured base URL. Multiple models are selected round-robin for successive requests.

10. Perplexity

This provider uses Perplexity's native structured Search API. It returns result rows rather than a Sonar-generated prose answer; OpenRouter compatibility is intentionally outside this provider's scope.

Variable

Required

Purpose

PERPLEXITY_API_KEY

Yes

Perplexity Search API credential

Add perplexity to AGENT_WEB_SEARCH_PROVIDERS after providing the key.

11. Tavily

Variable

Required

Purpose

TAVILY_API_KEY

Yes

Tavily Search API credential

Add tavily to AGENT_WEB_SEARCH_PROVIDERS after providing the key.

12. You.com

You.com returns unified web and news sections. Agent Web Search merges both, deduplicates URLs, and applies max_results to the combined result list.

Variable

Required

Purpose

YDC_API_KEY

Yes

You.com Search API credential

Add you to AGENT_WEB_SEARCH_PROVIDERS after providing the key.

Zhipu Web Search uses the China standalone Web Search API and returns structured search rows. It is a separate Provider from Zhipu Chat Search; the implementation does not fall back between the two surfaces.

Variable

Required

Purpose

ZHIPU_WEB_SEARCH_API_KEY

Yes

Zhipu Web Search API credential

AGENT_WEB_SEARCH_ZHIPU_WEB_SEARCH_BASE_URL

No

China API base URL; defaults to https://open.bigmodel.cn

Add zhipu_web_search to AGENT_WEB_SEARCH_PROVIDERS after providing the key. The Provider appends /api/paas/v4/web_search to the configured base URL.

Zhipu Chat Search uses the China GLM Chat Completions API with native web search. It returns the model answer plus only explicit top-level search rows; URLs mentioned in answer prose are not treated as citations. It is a separate Provider from Zhipu Web Search and has no API/Chat fallback.

Variable

Required

Purpose

ZHIPU_CHAT_SEARCH_API_KEY

Yes

Zhipu Chat Search API credential

AGENT_WEB_SEARCH_ZHIPU_CHAT_BASE_URL

No

China API base URL; defaults to https://open.bigmodel.cn

AGENT_WEB_SEARCH_ZHIPU_CHAT_MODELS

No

Comma/newline-separated GLM model IDs; defaults to glm-5.3-flash

Add zhipu_chat_search to AGENT_WEB_SEARCH_PROVIDERS after providing the key. The Provider appends /api/paas/v4/chat/completions to the configured base URL. Multiple configured models are selected round-robin for successive requests.

Common search controls

Each provider maps the shared controls to its native API when possible and ignores unsupported controls.

Provider

max_results

time_range

DDGS

Native max_results

Native timelimit

Exa

Native result count

Native publish date

Parallel

REST: native max_results; keyless MCP: client-side truncation (results[:max_results])

Ignored

ARK

Native limit

Prompt constraint

Brave

Native count

Native freshness

Gemini

Prompt constraint

Prompt constraint

Grok

Prompt constraint

Prompt; X Search also uses native dates

Codex Alpha

Local result truncation

Ignored

DeepSeek

Local search-result truncation

Prompt constraint

Perplexity

Native max_results

Native recency filter

Tavily

Native max_results

Native time_range

You.com

Native count, combined cap

Native freshness

Zhipu Web Search

Native count, local deduplication and cap

Native recency filter

Zhipu Chat Search

Native count, local deduplication and cap

Native recency filter

Prompt-based controls are best-effort and are not strict guarantees.

Other interfaces

Native Hermes plugin

Install the native plugin directly from GitHub:

pip install 'ddgs>=9.0'
hermes plugins install JerryLiu369/agent-web-search --no-enable
hermes plugins enable agent-web-search --allow-tool-override

The plugin intentionally replaces Hermes' built-in web_search tool, so the explicit --allow-tool-override grant is required. Start a new Hermes session after enabling it; restart the gateway when using a messaging channel.

Hermes can also connect through its generic MCP integration instead of the native plugin.

Troubleshooting

  • all_providers_failed — every selected provider errored. MCP marks the call as an error; the CLI writes diagnostics to stderr and exits 1. Check keys, quotas, and network access. A single retry may help a transient limit.

  • agent-web-search is not found — install the PyPI package with pipx or pip, then start a new shell so its scripts directory is on PATH.

  • HTTP 401 invalid_token — the Authorization: Bearer … header must match AGENT_WEB_SEARCH_AUTH_TOKEN, which must be at least 32 characters.

  • A provider is missing from a response — failed providers are omitted from successful responses. The Python API exposes the reasons in response.failed_provider_errors.

  • Provider changes have no effect — provider settings are read once at startup; restart the CLI, MCP server, or Hermes plugin after changing them.

  • MCP client times out before the tool returnsAGENT_WEB_SEARCH_TIMEOUT bounds a single upstream HTTP call, not the whole search. Keyless Parallel issues up to 3 calls and ARK may append a continuation request, so the worst case is 3 × AGENT_WEB_SEARCH_TIMEOUT; configure your MCP client's tool timeout accordingly.

Development

Using uv keeps the development environment isolated and reproducible:

git clone https://github.com/JerryLiu369/agent-web-search.git
cd agent-web-search
uv venv
uv pip install -e '.[dev]'
uv run pytest -q
uv run ruff check .
python -m venv .venv
# Linux/macOS: source .venv/bin/activate
# Windows PowerShell: .venv\Scripts\Activate.ps1
python -m pip install -e '.[dev]'
pytest -q
ruff check .

ARCHITECTURE.md is the design source of truth, and AGENTS.md lists the non-negotiable invariants. Read both before changing transports, configuration, authentication, deployment, providers, or tool schemas, keep stdio and HTTP behavior identical, and keep pytest and ruff green in the same change.

License

MIT