Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

unique-search-proxy-sdk

Part of Unique Search Proxy · PyPI: unique-search-proxy-sdk


1. What this package is

The SDK is the caller's HTTP client. Platform services (e.g. assistants-core) use it to reach the proxy pod at runtime — search, agent search, and crawl — without hand-crafting httpx calls or duplicating route paths.

It depends on core for request validation and typed errors. It does not include the FastAPI server.

Package Question it answers
Core What can be configured and what does a valid request/response look like?
Client How are provider calls executed at runtime?
SDK (this) How do callers reach the proxy over HTTP?

2. Role in the system

The SDK implements Path B (runtime HTTP) from the system overview. Schema work (Path A) stays in core — the SDK does not expose deployment config or LLM call-schema endpoints.

flowchart LR
    Caller["Caller service"]
    SDK["unique_search_proxy_sdk"]
    Core["unique_search_proxy_core"]
    Proxy["unique_search_proxy_client"]

    Caller --> SDK
    SDK --> Core
    SDK -->|"httpx"| Proxy

Before a search call, the caller (or SDK) validates the payload against core request models. Non-2xx responses become the same ProxyError subclasses defined in core.


3. Architecture

Two layers: a hand-written facade over OpenAPI-generated code.

flowchart TB
    subgraph sdk_pkg["unique_search_proxy_sdk"]
        Facade["UniqueSearchProxyClient"]
        SC["SearchClient"]
        ASC["AgentSearchClient"]
        CC["CrawlClient"]
        Transport["OpenapiTransport"]
        Gen["_generated/"]
        Conv["converters.py"]
        Err["errors.py"]
    end

    Core["unique_search_proxy_core"]
    Proxy["Proxy pod"]

    Facade --> SC & ASC & CC
    SC & ASC & CC --> Transport
    Transport --> Gen
    SC --> Conv --> Core
    Err --> Core
    Gen -->|"httpx AsyncClient"| Proxy
Layer Path Responsibility
Facade client.py UniqueSearchProxyClient — composes sub-clients, health(), ready()
Sub-clients search_client.py, agent_search_client.py, crawl_client.py Per-provider typed endpoints + compatibility dispatchers
Endpoint factory _endpoint.py async_post_endpoint / async_sse_endpoint (ParamSpec from core request models)
Transport _transport.py, _http.py Shared httpx lifecycle, base URL, timeout
Generated _generated/ Route functions + attrs models from OpenAPI (do not edit)
Converters converters.py Core Pydantic models → generated SDK models
Errors errors.py Error envelope → core ProxyError subclasses

The client package is the source of truth for the HTTP contract. When routes change, regenerate _generated/ from unique_search_proxy_client/openapi.json.


4. Usage

Each provider exposes a typed endpoint whose kwargs mirror the core *Request Pydantic model (via ParamSpec). Snake_case and camelCase aliases both work (fetch_size / fetchSize).

from unique_search_proxy_sdk import UniqueSearchProxyClient

async with UniqueSearchProxyClient("http://unique-search-proxy:2349") as client:
    await client.health()

    # Typed per-provider endpoints (preferred)
    result = await client.search.google(query="unique ag", gl="ch", fetch_size=10)
    brave = await client.search.brave(query="news", country="US", safesearch="strict")
    agent = await client.agent_search.bing(query="EU AI Act timeline", fetch_size=5)
    crawl = await client.crawl.basic(urls=["https://example.com"])

    # Compatibility dispatchers (engine/crawler string)
    result = await client.search.search("unique ag", engine="google", fetch_size=10)
    agent = await client.agent_search.search("query", engine="bing")
    crawl = await client.crawl.crawl(["https://example.com"], crawler="Basic")

    # Agent SSE streaming
    async for event in client.agent_search.bing_stream(query="query"):
        ...

    # Low-level: one generated function per route
    raw_client = client.openapi

Search payloads are validated through core's parse_search_request() before serialization. Agent and crawl clients follow the same pattern.


5. API mapping

Facade method HTTP
health() GET /health
ready() GET /ready
search.google(...) / .brave(...) / .perplexity(...) POST /v1/search
search.search(...) POST /v1/search (dispatcher)
agent_search.bing(...) / .vertexai(...) POST /v1/agent-search
agent_search.bing_stream(...) / .vertexai_stream(...) POST /v1/agent-search/stream (SSE)
agent_search.search(...) / .stream(...) same routes (dispatchers)
crawl.basic(...) / .tavily(...) / .jina(...) / .firecrawl(...) POST /v1/crawl
crawl.crawl(...) POST /v1/crawl (dispatcher)
openapi Low-level generated client (one function per route)

Endpoint payloads and provider ids → Client README.


6. Error handling

Non-success responses with a proxy error envelope raise typed exceptions from core:

from unique_search_proxy_core import EngineNotConfiguredError, UpstreamError

ENGINE_NOT_CONFIGURED (503) includes missing_env_vars parsed from the error details list — useful for operators and LLM tool consumers.

Transport failures (non-JSON body, connection errors) raise UniqueSearchProxyClientError.


7. Codegen workflow

Generated via openapi-python-client from the server's OpenAPI spec.

cd ../unique_search_proxy_client
uv sync
uv run python scripts/generate_sdk.py
Path Role
unique_search_proxy_sdk/_generated/ Regenerated httpx client + attrs models
unique_search_proxy_client/openapi.json Exported spec (codegen input)
unique_search_proxy_sdk/client.py Hand-written facade (not regenerated)

Other codegen tools considered: OpenAPI Generator, datamodel-code-generator, Kiota — see git history in the client README if needed.


8. Testing

Pass an injected httpx.AsyncClient with ASGITransport for in-process tests against create_app():

import httpx
from httpx import ASGITransport
from unique_search_proxy_client.web.app import create_app
from unique_search_proxy_sdk import UniqueSearchProxyClient

app = create_app()
async with httpx.AsyncClient(
    transport=ASGITransport(app=app),
    base_url="http://test",
) as http:
    async with UniqueSearchProxyClient("http://test", http_client=http) as client:
        ...

Run the app lifespan so the in-process HttpClientPool is initialised.


9. Installation & development

cd unique_search_proxy_sdk
uv sync
uv run pytest
uv run ruff check .
uv run basedpyright

Depends on unique-search-proxy-core. Does not depend on unique-search-proxy at runtime (only as a dev dependency for integration tests).


License

Proprietary — Unique AG

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

unique_search_proxy_sdk-2026.36.0.dev0.tar.gz (39.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

File details

Details for the file unique_search_proxy_sdk-2026.36.0.dev0.tar.gz.

File metadata

  • Download URL: unique_search_proxy_sdk-2026.36.0.dev0.tar.gz
  • Upload date:
  • Size: 39.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for unique_search_proxy_sdk-2026.36.0.dev0.tar.gz
Algorithm Hash digest
SHA256 0d5cf419cd77c1d078e0d50b48343f4d0f711d86b9e0c9df61a1a6f752cf6362
MD5 f7f7651355d955c76baebf3224ea6d50
BLAKE2b-256 444408d21c2b4275e8de8621b2f4bd27575e36e8e255e5ce55f6c1c0a7731192

See more details on using hashes here.

File details

Details for the file unique_search_proxy_sdk-2026.36.0.dev0-py3-none-any.whl.

File metadata

  • Download URL: unique_search_proxy_sdk-2026.36.0.dev0-py3-none-any.whl
  • Upload date:
  • Size: 79.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for unique_search_proxy_sdk-2026.36.0.dev0-py3-none-any.whl
Algorithm Hash digest
SHA256 7eb617ecf07229f3483abebb22b20ef4dfc3351489125cdbc9da6071fd42bf29
MD5 af37f891702a33b9058cf2bae705902c
BLAKE2b-256 ce741b874c351e1efc48f301e21a26f7d8b6d5b52cfe3768efc590d24c39de52

See more details on using hashes here.

Release history Release notifications | RSS feed

2026.38.0

2 files

2026.36.2

2 files

2026.36.1

2 files

2026.36.0

2 files

This release

2026.36.0.dev0 This release

2 files

2026.34.3

2 files

2026.34.2

2 files

2026.34.1

2 files

2026.34.0

2 files

2026.32.4

2 files

2026.32.3

2 files

2026.32.2

2 files

2026.32.1

2 files

2026.32.0

2 files

2026.30.1

2 files

2026.30.0

2 files

2026.28.4

2 files

2026.28.3

2 files

2026.28.2

2 files

2026.28.1

2 files

2026.28.0

2 files

2026.26.0

2 files

2026.24.2

2 files

2026.24.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page