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 + agent 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 / agent | ExposedParams subclass with exactly the expose=True knobs (camelCase aliases, description-only schema), or None |
merge(overrides, *, query) (instance) |
search / agent | 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) |
ExposableParamsConfig (in param_policy/exposable_config.py) implements the exposable-parameter lifecycle once; BaseSearchEngineConfig and BaseAgentEngineConfig both extend it. Crawlers (BasicConfig, …) only implement request_model(): they have no exposable params and no merge — a crawl request is simply the deployment config fields plus urls.
3.2 ExposableParam
Optional search and agent parameters use ExposableParam[T]:
value— admin default merged into every request (null= deactivated)expose— whentrue, 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 (+ AnswerSpanCitation), 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/exposable_config.py |
ExposableParamsConfig — the exposed_params_model() / merge() lifecycle shared by search and agent config bases |
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, exposed_params_model, merge), output schema, Bing grounding configuration + agent naming |
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,crawlerLiteral discriminators) - Search & agent: config-owned
request_model/exposed_params_model/merge(provider_query_paramsis search-only); standard engines put optional provider knobs behind theExposableParampolicy - Agent:
BingAgentConfig.request_model()(injectsquery; excludesoutput_schema); Bing'smarket/freshnessare fixed admin values, never exposed to the LLM, and are baked into the hashed agent name (both areLiterals over Bing's documented values, likeBraveCountry). A blankmarketfalls back to theBING_AGENT_DEFAULT_MARKETenvironment variable - Crawl:
BasicConfig.request_model()(injectsurls); 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
Metadata
Release files for unique-search-proxy-core 2026.44.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| unique_search_proxy_core-2026.44.1.tar.gz | 56.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| unique_search_proxy_core-2026.44.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 146.5 kB
Release files / unique_search_proxy_core-2026.44.1.tar.gz
| Download URL | unique_search_proxy_core-2026.44.1.tar.gz |
|---|---|
| Size | 56.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
44e1435342087ce58c3b9b462b6e49c0ced4e660e806fcb9f5d58e3103bb994d
|
|
BLAKE2b-256 checksum How to use checksums |
6c91dd2f046c64adde805dc9cb9ef9882abf8b88bc17013df41bd8c1ff396319
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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}
|
Release files / unique_search_proxy_core-2026.44.1-py3-none-any.whl
| Download URL | unique_search_proxy_core-2026.44.1-py3-none-any.whl |
|---|---|
| Size | 90.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1db518fe5804e99ac88216fdd0ab15fdc289396e44b53c212cccc20d25911c4a
|
|
BLAKE2b-256 checksum How to use checksums |
3077ef2efca52c8df0c408a2c213adbe88420931fa47db30cc6b39a696db8c28
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is 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}
|
Security for unique-search-proxy-core 2026.44.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.