Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

feat: Add Serply as a selectable web_search provider

Aperta
#381 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 2 giorni

@googio ci sta già lavorando.

Dal 2/10/2026.

  • #420 di @googio — aperta

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
38/100
Tipo di issue
Funzionalità
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
rust

Direzione di ricerca

Start with the existing web-search provider factory and configuration in tool/web_search/mod.rs and config.rs, then compare the planned implementation in tool/web_search/serply.rs with tests/web_search_serply_test.rs and the deployment documentation files. Done means the mock tests cover query mapping, filtering, errors, metadata, and concurrency configuration, while cargo fmt and clippy pass without regressions for You.com and Brave.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Problem statement / motivation

Part of #291
Status: proposal, sequenced after #329 so the second alternative provider reuses the same configuration plumbing
Scope: Serply provider integration, configuration plumbing, and tests

The providers #291 lines up cover three backend shapes: an independent index (Brave), an agent-oriented answer/snippet service (Tavily), and a self-hosted metasearch (SearXNG). None of them returns Google's own organic ranking. For a gateway-executed web_search that matters in two situations I keep hitting:

  • Operator queries. site:, -site:, inurl:, filetype: and intitle:"..." are the vocabulary models already know from training data, and they only behave as expected against Google. Brave and Tavily each honour a subset, differently.
  • Ranking parity. When an eval or a user report says "Google shows X first", a backend that returns Google's SERP is the only way to reproduce it.

Serply is a Google SERP API: GET /v1/search returns Google's organic results as JSON, with the operators above passing through untouched, country targeting via gl, recency via tbs, and news via tbm=nws in the same result shape. It is prepaid credits rather than a subscription (2,500 free credits on signup, no card), which speaks to the barrier-to-entry point in #291.

Disclosure: I work on Serply and this is the Serply team account. I am proposing the contract here first, per #291, rather than opening a PR cold; details below are measured against the live API, not read off the docs.

Proposed solution
A. Provider implementation (tool/web_search/serply.rs)
  • Endpoint: GET {base_url}/v1/search with query parameters. Base URL default https://api.serply.io.
  • Authentication: X-Api-Key: {api_key} header, never a query parameter, so the key never lands in a logged URL. Key resolved from SERPLY_API_KEY.
  • Identify the caller: User-Agent: agentic-api on every request.
  • Deserialization: forward-compatible structs with #[serde(default)] over the envelope results: [{ title, link, description, position, result_type, metadata: { display_url } }], mapped onto WebSearchResult as url <- link, title <- title, description <- description. Every row in results[] is result_type: "organic"; ads, answers, places and knowledge panels live in their own top-level arrays and are ignored.
  • Errors: a bad or missing key is HTTP 401 with a {"detail": "..."} body, not error.
  • Request:
GET /v1/search?q=<query>&num=10[&gl=<country>][&tbs=qdr:d|w|m|y]
X-Api-Key: <SERPLY_API_KEY>
User-Agent: agentic-api
B. Input adaptation policy matrix
Parameter / input Serply behaviour Gateway adaptation policy
include_domains / exclude_domains No server-side filter parameter; site: / -site: operators inside q do work Client-side DomainFilter post-filter, same as Brave. Rewriting q with site: operators stays out of scope, matching the #291 non-goal.
count num is an upper bound with a ceiling of 10; num=20 returns the same page as num=10 Clamp to 10 with tracing::debug!, and trim the response to the requested count client-side, because a page can carry 9 or 11 rows at num=10.
freshness tbs=qdr:d / qdr:w / qdr:m / qdr:y pass through to Google (measured: 1/9 overlap with an unfiltered baseline, same-day articles) Freshness::Day -> qdr:d, Week -> qdr:w, Month -> qdr:m, Year -> qdr:y. Freshness::Range is omitted with a debug log rather than forwarded: Google's cdr: form does not pass through, and sending it would name a filter the results do not honour.
country gl=<code>, any ISO country code, documented Forwarded as gl. Without it the exit region is whatever Google assigns, so the docs should not describe the default as worldwide.
language, safesearch Not verified against the live API Ignored with tracing::debug! in the first cut, called out in the docs.
You.com specifics (livecrawl, livecrawl_formats, crawl_timeout, boost_domains) No equivalent Ignored with tracing::debug!, as Brave does.
News tbm=nws returns news in the same results[] shape, num honoured Out of scope for the first cut (it is a second request per query); news stays empty.
C. Concurrency and rate limiting
  • Concurrency ceiling: no published per-second cap; inherit the gateway limit, configurable via AGENTIC_WEB_SEARCH_MAX_CONCURRENT_QUERIES as in #327.
  • 429: fail web_search_call without retry, surfacing Retry-After verbatim.
  • 401 / 403: fail naming SERPLY_API_KEY without echoing the credential or the response body.
D. Configuration and precedence matrix
Setting Environment variable config.toml key Default
Provider AGENTIC_WEB_SEARCH_PROVIDER [web_search].provider "you" ("serply" selects this provider)
API key named by api_key_env [web_search].api_key_env "SERPLY_API_KEY"
Base URL AGENTIC_WEB_SEARCH_BASE_URL [web_search].base_url https://api.serply.io
Max concurrency AGENTIC_WEB_SEARCH_MAX_CONCURRENT_QUERIES [web_search].max_concurrent_queries inherits gateway limit

Adds WebSearchProviderKind::Serply (ALL grows to include it), default_api_key_env, default_base_url, the mod.rs factory arm, and the operator-facing docs rows in docs/deploying/README.md and docs/deploying/kubernetes.md beside Brave.

Scope boundaries
In scope Explicitly out of scope (deferred)
SerplySearchProvider (GET /v1/search) News via tbm=nws and the Scholar vertical
Client-side domain post-filter, count clamp and trim, freshness and country mapping site: query rewriting for domain filters
Axum mock HTTP tests (tests/web_search_serply_test.rs) language / safesearch forwarding until measured
Verification checklist
  • 200 OK: query parameters shape correctly and results[] maps to WebSearchResult, asserting the actual HTTP query string in the mock.
  • Count: count=25 sends num=10 and returns at most 10; an 11-row page at count=5 returns 5.
  • Domain filtering: include_domains / exclude_domains are applied through DomainFilter.
  • Freshness: Day sends tbs=qdr:d; a range sends no tbs.
  • 401 / 403: fails web_search_call, references SERPLY_API_KEY, does not leak the credential.
  • 429: surfaces Retry-After verbatim without retrying.
  • Metadata: echoes "provider": "serply" in metadata[].
  • Zero regressions: You.com and Brave remain byte-identical.
  • Hygiene: cargo fmt, cargo clippy --all-targets -- -D warnings, file size limits.
Alternatives considered
  • Reaching Google through SearXNG (#326) with its Google engine enabled. That works for self-hosted deployments but inherits SearXNG's scraping fragility and rate limits on shared IPs, and it strips the operator pass-through and gl targeting that make the SERP shape useful.
  • Emulating domain filters by rewriting q with site: operators. Serply would honour it, but #291 rules query rewriting out, and the client-side DomainFilter already gives the same guarantee.
Additional context
  • API reference: https://serply.io/docs
  • I can implement this against the #324 contract myself and open the PR once #329 lands, so the configuration plumbing is written once and the two providers do not conflict in config.rs and mod.rs. If you would rather keep the provider series in one hand, this issue is the contract for whoever picks it up; either way, happy to answer questions about the API here.
Lingua principale
Rust
Stelle
323
Fork
87
Merge medio
3g 2h
PR unite (30g)
66

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di vllm-project/agentic-api

Tutte le issue di vllm-project/agentic-api

Issue simili

Altre issue su Rust

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.