Skip to content

Parallel Search Integration

Updated: November 7, 2025
Owners: LLM Platform Team
Docs: docs.parallel.ai/home

Overview

We use Parallel's Search API for queries that require multi-hop reasoning, rich citations, or structured aggregation (e.g., "best deals on a Mac mini" or venue discovery). The smart router now treats Parallel as a first-class provider alongside Perplexity and free/OAuth APIs.

Provider Architecture

  • Providers live in app/orchestrator/providers/.
  • Each provider implements the SearchProvider interface (execute, close) and registers itself through provider_registry.
  • The smart router only talks to providers via ProviderRequest/ProviderResult. Adding a new backend means implementing a provider class and registering it—no router rewrites.
  • ParallelSearchProvider uses app/services/search/parallel_client.py for auth, headers, and defaults.

Configuration

Add the following to your environment (local .env, Render, Railway, etc.):

PARALLEL_API_KEY=...             # Required
PARALLEL_SEARCH_VERSION=search-extract-2025-10-10  # Optional beta flag (see docs)
PARALLEL_DEFAULT_MAX_RESULTS=8   # Optional override via settings if needed

Notes: - The default max results can be adjusted through settings.parallel_default_max_results (Pydantic automatically reads PARALLEL_DEFAULT_MAX_RESULTS if present). - If no key is present the provider is skipped, and the router falls back to Perplexity → GPT-5.

Runtime Behavior

  1. SmartRouter registers providers when instantiated (get_smart_router()).
  2. Query analysis labels complex aggregation intents as DataSource.PARALLEL by default.
  3. _route_to_provider builds a ProviderRequest, including an objective string that captures workflow + parameters.
  4. ParallelSearchProvider calls /v1beta/search with the objective and curated query list, requesting excerpts for top results.
  5. Responses are normalized:
  6. response: summarized text (Parallel answer + highlight bullet list).
  7. metadata.citations: list of {title, url} for downstream use.
  8. metadata.raw: full Parallel payload (for auditing/observability).
  9. If Parallel returns no content or errors, we automatically retry via Perplexity, then GPT-5.

Observability

  • Look for "[SmartRouter] Provider 'parallel' succeeded" logs to confirm execution.
  • metadata.sources_used and metadata.citations are bubbled up for multi-intent requests.
  • Add provider-specific dashboards by filtering logs on provider=parallel (metadata field).

Testing

  • Unit tests should stub ParallelSearchClient.search to avoid real HTTP calls.
  • Ensure routing tests cover DataSource.PARALLEL intents and fallback paths.
  • The integration does not run in CI without a key; keep mocks deterministic.

Extending Further

  • Use the same provider pattern to add Parallel Task/FindAll APIs when we need custom schemas.
  • For vertical-specific research (e.g., pricing tables), adjust the objective and output parsing inside ParallelSearchProvider._build_response.
  • If future providers require background jobs or streaming, extend ProviderResult to capture those artifacts—router changes should stay minimal.