Skip to main content

unique-search-proxy-core

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


1. What this package is

Core is the contract layer. It defines every shared type — deployment configs, HTTP request/response shapes, error codes, and LLM tool schemas — without importing FastAPI, httpx pools, or provider SDKs.

Install it anywhere you need to describe or validate proxy behaviour: the proxy server, the HTTP SDK, assistants-core tool manifests, deployment UIs.

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

2. Role in the system

Core sits at the centre of Path A (schema & config). It is imported by both the proxy pod and caller services; it never makes HTTP calls itself.

flowchart TB
    subgraph consumers["Consumers of core"]
        Client["unique_search_proxy_client"]
        SDK["unique_search_proxy_sdk"]
        AC["assistants-core / deployment UI"]
    end

    subgraph core["unique_search_proxy_core"]
        Contracts["Response & error models"]
        Config["*Config deployment models\n(request_model / exposed_params_model / merge)"]
    end

    AC --> Config
    Client --> Contracts
    Client --> Config
    SDK --> Contracts
    Config -->|"flat request body"| SDK
    Config -->|"flat request body"| Client

System overview → ../README.md


3. Key concepts

The config class owns its entire parameter lifecycle. Every derived surface is a method on the deployment config — there are no standalone projection or resolver modules.

3.1 Config-owned API (search engines)

Admin JSON → GoogleConfig {expose, value}
  ├─ GoogleConfig.request_model()            → GoogleSearchRequest (HTTP body, query required)
  ├─ config.exposed_params_model()           → GoogleExposedParams (LLM knobs; tool inherits it)
  ├─ config.merge(llm_args, query=…)         → validated GoogleSearchRequest
  └─ GoogleConfig.provider_query_params(req) → upstream provider dict
Method Kind Returns
request_model() (classmethod, cached) search / agent / crawl SearchRequestBase (required query) or CrawlRequestBase (required urls) + config fields; ExposableParam knobs unwrapped to optional plain types
exposed_params_model() (instance) search only ExposedParams subclass with exactly the expose=True knobs (camelCase aliases, description-only schema), or None
merge(overrides, *, query) (instance) search only deployment defaults + LLM overrides + query → validated request_model() instance
provider_query_params(request) (classmethod) search only request serialized for the upstream provider, minus _provider_param_exclude_fields (Google adds search_engine_id)

Agent engines (BingAgentConfig, …) and crawlers (BasicConfig, …) only implement request_model(). Crawlers have no exposable params and no merge — a crawl request is simply the deployment config fields plus urls.

3.2 ExposableParam — search-engine only

Optional search parameters use ExposableParam[T]:

  • value — admin default merged into every request (null = deactivated)
  • expose — when true, the parameter appears on the LLM-facing exposed-params model
gl: ExposableParam[str | None] = ExposableParam(expose=False, value="de")  # admin-fixed
gl: ExposableParam[str | None] = ExposableParam(expose=True, value=None)   # LLM-overridable

Bare scalars are not coerced — deployment JSON must use the explicit {"expose": …, "value": …} shape.

3.3 ExposedParams — the LLM tool-schema contract

config.exposed_params_model() returns a plain Pydantic model class. Tool-parameter models graft the knobs on by ordinary inheritance — no field-def plumbing, no stamped attributes:

Exposed = config.exposed_params_model()          # GoogleExposedParams | None
class ToolParams(ToolParamsBase, Exposed): ...   # or create_model(__base__=(...))

ToolParams.model_json_schema()   # camelCase knobs, no title/default noise
Exposed.model_fields             # the exposed field names

The shared ExposedParams base owns the single JSON-schema concern: its model_json_schema strips Pydantic's auto-title and default noise, so admin defaults never leak into what the LLM sees.

3.4 merge — deployment defaults + LLM overrides

request = google_config.merge({"gl": "de"}, query="EU AI Act")
# → validated GoogleSearchRequest ready for POST /v1/search

Deactivated knobs (value=None) are dropped, overrides win over admin defaults, engine always comes from the config. The proxy receives a flat body; it does not resolve deployment config over HTTP.


4. Architecture (modules)

flowchart TB
    subgraph core_pkg["unique_search_proxy_core"]
        Schema["schema.py"]
        Errors["errors.py"]
        PP["param_policy/\nExposableParam · ExposedParams\nrequest bases · derive"]
        Prov["providers/schema.py"]
        SE["search_engines/"]
        AE["agent_engines/"]
        CR["crawlers/"]
    end

    PP --> SE
    PP --> AE
    PP --> CR
    Prov --> SE
    Prov --> CR
    SE --> Schema
    AE --> Schema
    CR --> Schema
    Errors --> Schema
Module Responsibility
schema.py Shared API models: SearchResponse, AgentSearchResponse, CrawlResponse, WebSearchResult, ErrorResponse, SSE events
errors.py ProxyError hierarchy and stable ProxyErrorCode enum
param_policy/exposable_param.py ExposableParam value object, factory-default merge, type introspection, OpenAPI naming
param_policy/exposed_params.py ExposedParams base for LLM-facing parameter models (schema noise stripping)
param_policy/request_base.py SearchRequestBase / AgentRequestBase / CrawlRequestBase (required leading fields)
param_policy/annotations.py Annotation unwrapping helpers (private, used by derive)
param_policy/derive.py derive_request_model / derive_exposed_params_model factories called by the config base classes
providers/schema.py JSON Schema + defaults for deployment UIs (provider_config_json_schema, …)
search_engines/ Config models with the config-owned API (request_model / exposed_params_model / merge / provider_query_params), request union
agent_engines/ Agent config/request models (request_model), output schema
crawlers/ *Config deployment models + derived *CrawlRequest bodies (request_model())

5. Provider contracts

Core registers the discriminator ids and config models. Runtime registration of service classes lives in the client.

Kind IDs Config model
Search engines google, brave, perplexity GoogleConfig, BraveConfig, PerplexityConfig
Agent engines bing, vertexai BingAgentConfig, VertexAIAgentConfig
Crawlers Basic, Tavily, Jina, Firecrawl BasicConfig, TavilyConfig, … → BasicCrawlRequest, …

Search engines share BaseSearchEngineConfig (fetch_size, timeout). Crawlers share BaseCrawlerConfig (timeout only — urls live on derived request models).


6. Key APIs (by use case)

Deployment UI — JSON Schema for a provider

from unique_search_proxy_core.providers.schema import (
    provider_config_json_schema,
    provider_default_config,
)

schema = provider_config_json_schema("search_engine", "google")
defaults = provider_default_config("search_engine", "google")

Tool manifest — exposed LLM knobs

Exposed = google_config.exposed_params_model()   # GoogleExposedParams | None
class ToolParams(ToolParamsBase, Exposed): ...   # graft knobs by inheritance
ToolParams.model_json_schema()                   # camelCase, no title/default noise

Runtime — build flat request before HTTP call

request = google_config.merge(llm_invocation_dict, query="EU AI Act")
body = GoogleConfig.provider_query_params(request)  # upstream provider dict

Shared types and errors

from unique_search_proxy_core import (
    SearchResponse,
    ProxyError,
    EngineNotConfiguredError,
    WebSearchResult,
)

7. Features summary

  • Discriminated provider configs (engine, crawler Literal discriminators)
  • Search-only: ExposableParam policy; config-owned request_model / exposed_params_model / merge / provider_query_params
  • Agent: BingAgentConfig.request_model() (injects query; excludes output_schema)
  • Crawl: BasicConfig.request_model() (injects urls); no exposable params / no merge
  • CamelCase JSON aliases on all models
  • Zero server dependencies (import-linter enforced in the client package)

8. Installation & development

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

Consumers needing HTTP access should use unique-search-proxy-sdk rather than calling the proxy with raw httpx.


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_core-2026.34.0.tar.gz (38.5 kB view details)

Uploaded Source

Built Distribution

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

unique_search_proxy_core-2026.34.0-py3-none-any.whl (64.9 kB view details)

Uploaded Python 3

File details

Details for the file unique_search_proxy_core-2026.34.0.tar.gz.

File metadata

  • Download URL: unique_search_proxy_core-2026.34.0.tar.gz
  • Upload date:
  • Size: 38.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_core-2026.34.0.tar.gz
Algorithm Hash digest
SHA256 e6ae647c0e3a37a7d3517e1aa26bbc9d1b6dbb5f908943e73a5ab21666548d0f
MD5 573dd1112336656ca71851fc9f8fbd55
BLAKE2b-256 d5cc89f2d784a2550e4dd32011b75b3f8b44cbe5669ef8902f94e6be317423b8

See more details on using hashes here.

File details

Details for the file unique_search_proxy_core-2026.34.0-py3-none-any.whl.

File metadata

  • Download URL: unique_search_proxy_core-2026.34.0-py3-none-any.whl
  • Upload date:
  • Size: 64.9 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_core-2026.34.0-py3-none-any.whl
Algorithm Hash digest
SHA256 29c41006860cc2d1cef05cf8357ff72fed2dba4c63bbdf9abd23cabe8f993fa2
MD5 14ffa9f87d2bdc6124aff6ea30ff59a2
BLAKE2b-256 1accf761e6e547f1e1fa5ad6acffac4750c1234182791e4fef74097e74d008e1

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

2026.34.3

2 files

2026.34.2

2 files

2026.34.1

2 files

This release

2026.34.0 This release

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