
Security News
Federal Audit Finds NIST Wasted Funds With No Plan to Clear NVD Backlog
Federal audit finds NIST lacked a plan to clear the NVD backlog, wasted funds on duplicate work, and delayed use of CISA data.
pi-web-providers
Advanced tools
Configurable web access extension for pi with per-tool provider routing and explicit provider option schemas for search, contents, quick grounded answers, and research.
A meta web extension for pi that routes search, content extraction, quick grounded answers, and research through configurable per-tool providers, with explicit provider-specific option schemas for each managed tool.
Most web extensions hard-wire a single backend. pi-web-providers lets you
mix and match providers per tool instead, so web_search, web_contents,
web_answer, and web_research can each use a different backend or be turned
off entirely. Treat web_answer as a fast path for simple grounded questions,
not as a replacement for source inspection or deeper research.
web_search or web_answer call and get grouped results back in one
responseweb_contents
extraction from web_search results in the background and reuse the cached
pages later for faster follow-up readspi install npm:pi-web-providers
Run:
/web-providers
This edits the global config file ~/.pi/agent/web-providers.json. The
settings UI mirrors the three sections below: tools, providers, and settings.
Each tool can be routed to any compatible provider:
Provider credentials can be literal values, environment variable names, or
!command references. pi-web-providers resolves those secrets lazily on the
first matching tool use, not when a session starts. This avoids startup delays
from password-manager commands such as op; missing or failing secrets are
reported when the tool is actually called.
Built-in local providers
| Provider | search | contents | answer | research | Auth |
|---|---|---|---|---|---|
| Claude | β | β | Local Claude Code auth | ||
| Codex | β | Local Codex CLI auth |
API-backed providers
| Provider | search | contents | answer | research | Auth |
|---|---|---|---|---|---|
| Brave | β | β | β | BRAVE_SEARCH_API_KEY / BRAVE_ANSWERS_API_KEY | |
| Cloudflare | β | CLOUDFLARE_API_TOKEN + CLOUDFLARE_ACCOUNT_ID | |||
| Exa | β | β | β | β | EXA_API_KEY |
| Firecrawl | β | β | β | FIRECRAWL_API_KEY | |
| Gemini | β | β | β | GOOGLE_API_KEY | |
| Linkup | β | β | β | LINKUP_API_KEY | |
| Ollama | β | β | OLLAMA_API_KEY | ||
| OpenAI | β | β | β | OPENAI_API_KEY | |
| Parallel | β | β | PARALLEL_API_KEY | ||
| Perplexity | β | β | β | PERPLEXITY_API_KEY | |
| Serper | β | SERPER_API_KEY | |||
| Tavily | β | β | TAVILY_API_KEY | ||
| Valyu | β | β | β | β | VALYU_API_KEY |
Advanced option: custom can route any managed tool through a local wrapper
command using a JSON stdin/stdout contract.
See example-config.json for the minimal default
configuration.
Each managed tool maps to one provider id under the top-level tools key.
Removing a tool mapping turns that tool off. A tool is only exposed when it is
mapped to a compatible provider and that provider is currently available.
Shared defaults and tool-specific settings live under settings; search-specific
settings live under settings.search, and async research uses
settings.researchTimeoutMs. Provider option schemas are strict: only the keys
shown for the active provider are accepted.
web_searchSearch the public web for up to 10 queries in one call. It returns grouped
titles, URLs, and snippets for each query. Batch related queries when grouped
comparison matters; use separate sibling web_search calls when independent
results should arrive as soon as they are ready.
| Parameter | Type | Default | Description |
|---|---|---|---|
queries | string[] | required | One or more search queries to run (max 10) |
maxResults | integer | 5 | Result count per query, clamped to 1β20 |
options | object | β | Provider-specific settings exposed by the selected provider schema |
options is omitted when the configured search provider has no per-call
provider options. Runtime controls are not accepted in tool calls. Configure
retry, timeout, and background contents prefetch under settings and
settings.search; prefetch starts only when settings.search.provider is set.
web_contentsRead the main text from one or more web pages. It reuses cached pages when they
match and fetches only missing or stale URLs. Batch related pages when they are
meant to be read as one bundle; use separate sibling web_contents calls when
each page can be acted on independently.
| Parameter | Type | Default | Description |
|---|---|---|---|
urls | string[] | required | One or more URLs to extract |
options | object | β | Provider-specific settings exposed by the selected provider schema |
web_contents reuses any matching cached pages already present in the local
in-memory cacheβwhether they came from prefetch or an earlier readβand only
fetches missing or stale URLs.
web_answerAnswer one or more simple factual questions using web-grounded evidence. Use it
as a lightweight shortcut when you want a concise grounded answer without
manually selecting and reading sources. Prefer web_search plus web_contents
when source selection matters or you need to inspect primary sources directly;
prefer web_research for open-ended, controversial, or multi-step
investigations.
When you ask more than one question, the response is grouped into per-question sections. Batch related questions when the answers belong together; split them into sibling calls when earlier independent answers can unblock the next step. Collapsed results show a short answer preview; expand the tool result to read the full answer.
| Parameter | Type | Default | Description |
|---|---|---|---|
queries | string[] | required | One or more questions to answer in one call (max 10) |
options | object | β | Provider-specific settings exposed by the selected provider schema |
Responses are grouped into per-question sections when more than one question is provided.
web_researchInvestigate a topic across web sources and produce a longer report.
web_research is always asynchronous: it starts a background run, returns a
short dispatch notice immediately, and later posts a completion message with a
saved report path.
| Parameter | Type | Default | Description |
|---|---|---|---|
input | string | required | Research brief or question |
options | object | β | Provider-specific settings exposed by the selected provider schema |
options is provider-specific. Equivalent concepts can use different field
names across SDKsβfor example Perplexity uses country, Exa uses
userLocation, and Valyu uses countryCode. Runtime controls are not accepted
in tool calls.
Unlike the other managed tools, web_research does not accept local timeout,
retry, polling, or resume controls. Research has one opinionated execution
style: pi starts it asynchronously, tracks it locally, and saves the final
report under .pi/artifacts/research/.
The built-in providers below integrate with official SDKs or documented APIs.
web_search via Web Search, plus optional llm_context, news, videos, images, and places search modesweb_answer and web_research via Brave Answers streaming chat completionsweb_search_optionsmodel option (brave or brave-pro) for answer and research callsweb_contents stays routed to URL-fetch providers; Brave LLM Context is query-based retrieval and is exposed as a search mode insteadSetup
{
"tools": {
"search": "brave",
"answer": "brave",
"research": "brave"
},
"providers": {
"brave": {
"credentials": {
"search": "BRAVE_SEARCH_API_KEY",
"answers": "BRAVE_ANSWERS_API_KEY"
}
}
}
}
Use providers.brave.options.search.mode or per-call search options to select
llm_context, news, videos, images, or places. Places details and
descriptions are opt-in because they can add calls, latency, and place-specific
semantics.
@anthropic-ai/claude-agent-sdkWebSearch and WebFetch tools with structured JSON outputmodel, thinking, effort, maxThinkingTokens, maxTurns, and
maxBudgetUsd as provider options for search and answer callscloudflareweb_contents via Cloudflare Browser Rendering's /markdown
endpointgotoOptions.waitUntil as the provider-specific contents optionSetup
Account | Browser Rendering | Edit{
"tools": {
"contents": "cloudflare"
},
"providers": {
"cloudflare": {
"credentials": {
"api": "CLOUDFLARE_API_TOKEN"
},
"accountId": "CLOUDFLARE_ACCOUNT_ID"
}
}
}
If Cloudflare returns 401 Authentication error, the token permission, token
scope, or account ID is usually wrong.
@openai/codex-sdkmodel, modelReasoningEffort, and webSearchMode as provider
options for web_searchexa-jsweb_search, web_contents, web_answer, and web_researchweb_research is exposed through pi's async research workflowcategory, type, date filters,
includeDomains, excludeDomains, userLocation, and contentsproviders.exa.options.searchweb_contents, web_answer, and web_research currently use fixed provider behavior with no extra per-call provider options@mendable/firecrawl-jsweb_search, web_contents, and page-scoped web_answerquestion format against one explicit page URL;
set options.url in the web_answer call or
providers.firecrawl.options.answer.url as a defaultlang, country, sources, categories,
location, timeout, and scrapeOptionsformats, onlyMainContent, includeTags,
excludeTags, waitFor, headers, location, mobile, and proxyurl, onlyMainContent, includeTags,
excludeTags, waitFor, headers, location, mobile, and proxyquestion formatbaseUrl overrides are supported for self-hosted Firecrawl
instances, proxies, and testing. API keys are required for Firecrawl Cloud,
but can be omitted for self-hosted endpoints that do not enforce
authentication.@google/genaiweb_search, web_answer, and web_researchweb_research is exposed through pi's async research workflowmodel and generation_config for search, model and config
for answers, and only the conservative deep-research option
agent_config.thinking_summaries for researchtools, response_format, response_modalities, or system_instruction
because the default deep-research agent rejects several of those fieldslinkup-sdkweb_search via Linkup Search with fixed searchResults outputweb_contents via Linkup Fetch and always returns markdownweb_research via Linkup's async Research APIdepth, includeImages, includeDomains,
excludeDomains, fromDate, and toDaterenderJs, includeRawHtml, and extractImagesoutputType, mode, reasoningDepth,
includeDomains, excludeDomains, fromDate, toDate, and
structuredOutputSchemasourcedAnswer; provide structuredOutputSchema for
structured outputweb_search via Ollama's POST /api/web_search endpointweb_contents via Ollama's POST /api/web_fetch endpointOLLAMA_API_KEY by defaultbaseUrl overrides the default https://ollama.com API host for
proxies or compatible endpointsweb_search.maxResults is
clamped to 1β10 for this providerMinimal config:
{
"tools": {
"search": "ollama",
"contents": "ollama"
},
"providers": {
"ollama": {
"credentials": {
"api": "OLLAMA_API_KEY"
}
}
}
}
openaiweb_search, web_answer, and web_researchweb_search_preview tool for search,
answer, and research callsmodel and instructions for web_search and web_answermodel, instructions, and max_tool_calls for web_researchSetup
web_search, web_answer, web_research, or any
subset of them to openai.providers.openai.options.search.model,
providers.openai.options.answer.model, and
providers.openai.options.research.model.{
"tools": {
"search": "openai",
"answer": "openai",
"research": "openai"
},
"providers": {
"openai": {
"credentials": {
"api": "OPENAI_API_KEY"
},
"options": {
"search": {
"model": "gpt-4.1"
},
"answer": {
"model": "gpt-4.1"
},
"research": {
"model": "o4-mini-deep-research"
}
}
}
}
}
You can also set instructions as a provider default under
providers.openai.options.search, providers.openai.options.answer, or
providers.openai.options.research, and set max_tool_calls under
providers.openai.options.research. All of them can also be overridden per
call.
@perplexity-ai/perplexity_aiweb_search, web_answer, and web_researchweb_research is exposed through pi's async research workflowweb_searchweb_answer and sonar-deep-research for web_researchcountry, search_mode,
search_domain_filter, and search_recency_filtermodel for answer and research callsparallel-webmodeexcerpts and full_contentweb_search via Serper's Google endpoints for web, image, video,
places, maps, reviews, news, shopping, product reviews, Lens, Scholar,
patents, autocomplete, and webpage resultsmode, gl, hl, location, page, tbs,
autocorrect, and mode-specific fields such as url, ll, placeId,
cid, fid, productId, nextPageToken, and webpage include flags.
Reviews mode uses the top-level query when no place identifier is provided.
includeMarkdown defaults to true for webpage scrapingknowledgeGraph, answerBox, peopleAlsoAsk, and relatedSearchesbaseUrl overrides are supported for proxies and testingMinimal config:
{
"tools": {
"search": "serper"
},
"providers": {
"serper": {
"credentials": {
"api": "SERPER_API_KEY"
}
}
}
}
@tavily/coreweb_search via Tavily Searchweb_contents via Tavily Extracttopic, searchDepth, timeRange, country,
exactMatch, includeAnswer, includeRawContent, includeImages,
includeFavicon, includeDomains, excludeDomains, and daysextractDepth, format, includeImages, query,
chunksPerSource, and includeFaviconvalyu-jsweb_search, web_contents, web_answer, and web_researchweb_research is exposed through pi's async research workflowsearchType, responseLength, and countryCoderesponseLength and countryCodeproviders.valyu.options.search,
providers.valyu.options.answer, and providers.valyu.options.researchweb_contents currently uses fixed provider behavior with no extra per-call
provider optionsThe custom provider lets you bring your own wrapper command for any
managed tool. Each capability can point at a different local command under
providers["custom"].options.
custom does not expose standard per-call options fields. Put
provider-specific behavior in the wrapper configuration or in the wrapper
implementation.
The repo includes actual wrapper examples under
examples/custom/wrappers/. They are
small bash scripts that use jq for JSON handling. Each one uses a different
backend pattern:
codex --search exec for web_searchcurl for web_contentsclaude -p for web_answercurl for web_researchCopy the example wrappers into a local ./wrappers/ directory, then configure:
{
"tools": {
"search": "custom",
"contents": "custom",
"answer": "custom",
"research": "custom"
},
"providers": {
"custom": {
"options": {
"search": {
"argv": ["bash", "./wrappers/codex-search.sh"]
},
"contents": {
"argv": ["bash", "./wrappers/gemini-contents.sh"]
},
"answer": {
"argv": ["bash", "./wrappers/claude-answer.sh"]
},
"research": {
"argv": ["bash", "./wrappers/perplexity-research.sh"]
}
}
}
}
}
Those example wrappers deliberately use different local CLIs and APIs so you can see several wrapper styles in one setup without extra glue code.
Each capability can also set an optional cwd and env block. Use cwd when
one wrapper must run from a specific directory. Use env for per-command
variables; each value can be a literal string, an environment variable name, or
!command.
web_research uses the same async workflow as every other research provider:
pi starts the wrapper in the background, tracks the job locally, and writes the
final report to a file when it finishes.
Wrapper contract:
stdin: one JSON request object with capability plus the per-call managed
inputs (query, urls, input, maxResults, options, cwd)stdout: one JSON response object
search: { "results": [{ "title", "url", "snippet" }] }contents: { "answers": [{ "url", "content"?: "...", "summary"?: unknown, "metadata"?: {}, "error"?: "..." }] }answer / research: { "text": "...", "summary"?: "...", "itemCount"?: 1, "metadata"?: {} }stderr: optional progress lines0: successSee examples/custom/README.md for a
copy-and-pasteable setup, and see
examples/custom/wrappers/ for the actual
wrapper files.
The settings block holds shared execution defaults that apply to all
providers unless overridden in a provider's own settings block:
| Field | Default | Description |
|---|---|---|
requestTimeoutMs | 30000 | Maximum time for a single provider request |
retryCount | 3 | Retries for transient failures |
retryDelayMs | 2000 | Initial delay before retrying |
researchTimeoutMs | 1800000 | Maximum total time for an async web_research job (30 min) |
pi remove npm:pi-web-providers
FAQs
Configurable web access extension for pi with per-tool provider routing and explicit provider option schemas for search, contents, quick grounded answers, and research.
The npm package pi-web-providers receives a total of 363 weekly downloads. As such, pi-web-providers popularity was classified as not popular.
We found that pi-web-providers demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Β It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Federal audit finds NIST lacked a plan to clear the NVD backlog, wasted funds on duplicate work, and delayed use of CISA data.

Research
/Security News
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.

Research
/Security News
The North Korean malware loader hides in a Packagist-listed package and its GitHub branch to fetch and execute remote code in a likely Contagious Interview-style lure.