dr-providers
| Repo Definitions (terms, contracts) | dr-serialize |
|---|
dr-providers makes LLM provider calls through explicit, typed contracts. It supports OpenRouter, OpenAI, Gemini, and Anthropic while keeping call identity, provider translation, transport policy, and outcomes separate.
Package map
| Package | Responsibility |
|---|---|
dr_providers.modeling |
Identity-bearing definitions, configs, requests, routes, controls, and transcripts |
dr_providers.translation |
Pure provider request-body construction and parsed-response translation |
dr_providers.transport |
Credentials, endpoints, timeout policy, and one-invocation HTTP execution |
dr_providers.outcomes |
Typed responses, expected failures, invocation evidence, and conformance warnings |
dr_providers.lifecycle |
Invocation classification, serializable retry state, deterministic transitions, and terminal call results |
dr_providers.core |
Shared provider protocol and failure vocabulary |
dr_providers.surfaces.testing |
Deterministic ScriptedProvider for network-free tests |
dr_providers.surfaces.cli |
Optional dr-providers one-shot CLI |
dr_providers.surfaces.serve |
Optional localhost FastAPI facade |
The top-level dr_providers exports are the stable general import surface.
Functional-area module paths primarily make ownership discoverable; they are
not a second compatibility surface.
Install
dr-providers requires Python 3.12 or newer.
uv add dr-providers
Unless an API key is injected directly, real HTTP calls read the credential selected by their transport policy:
| Provider | Environment variable |
|---|---|
| OpenRouter | OPENROUTER_API_KEY |
| OpenAI | OPENAI_API_KEY |
| Gemini | GEMINI_API_KEY |
| Anthropic | ANTHROPIC_API_KEY |
Python quickstart
This OpenAI example uses the stable package import surface:
from threading import Event
from dr_providers import (
AcceptAllSemanticResponseClassifier,
GenerationControls,
HttpProvider,
MessageRole,
PromptMessage,
ProviderCallOutcomeKind,
ProviderCallRequest,
ProviderCallState,
ProviderKind,
StandardProviderCallRetryPolicy,
Transcript,
openai_responses_config,
policy_for,
run_local_provider_call,
)
config = openai_responses_config(
model="gpt-5-mini",
controls=GenerationControls(token_limit=256),
)
request = ProviderCallRequest(
config=config,
transcript=Transcript(
messages=(
PromptMessage(
role=MessageRole.USER,
content="Say hello in one word.",
),
)
),
)
classifier = AcceptAllSemanticResponseClassifier()
state = ProviderCallState.initial(
request=request,
retry_policy=StandardProviderCallRetryPolicy(),
classifier_identifier=classifier.identifier,
)
with HttpProvider(
policy=policy_for(
ProviderKind.OPENAI,
max_connections=1,
max_keepalive_connections=1,
)
) as provider:
result = run_local_provider_call(
provider=provider,
state=state,
classifier=classifier,
cancellation=Event(),
)
evidence = result.completed_invocations[-1].observation.evidence
if result.outcome.kind is ProviderCallOutcomeKind.ACCEPTED:
assert evidence.response is not None
print(evidence.response.text)
else:
print(result.outcome)
Expected transport failures are retained in invocation evidence and classified
into the terminal ProviderCallResult. Unexpected programming or infrastructure
errors can still raise.
CLI and local server
Install and run the one-shot CLI:
uv add 'dr-providers[cli]'
uv run dr-providers --provider openai-responses \
--model gpt-5-mini \
--token-limit 256 \
-m 'Say hello in one word.'
Install the serving extra and bind the FastAPI facade to localhost:
uv add 'dr-providers[serve]'
uv run python -m dr_providers.surfaces.serve serve --port 8322
Outcome and evidence boundaries
HttpProvider.invoke() makes at most one provider wire request and returns
versioned serializable ProviderInvocationEvidence. The evidence binds the
request identity hash and transport-policy identity to structured HTTP request
metadata and exactly one response or expected failure. The HTTP request
evidence is the sole owner of the constructed request-body mapping.
run_local_provider_call() classifies each invocation, applies the selected
serializable retry policy through the deterministic lifecycle transition, and
returns the complete ordered ProviderCallResult. The standard policy permits
at most two invocations with one one-second retry, only for contained transient
network/provider failures and contained transport timeouts. The standard HTTP
provider uses direct synchronous native phase timeouts, so it observes a timeout
only after the local HTTP operation has ended. It owns and reuses one bounded
client; closing stops admission, drains active invocations, and closes that
client once. Connect, write, and pool phase timeouts and the response-read idle
timeout do not bound the total wall-clock duration of a slow response that keeps
producing bytes.
The public transport-policy defaults allow 10 open connections and retain 5
idle connections. A caller that shares one HttpProvider across concurrent
work must explicitly size both limits to its own maximum concurrent
invoke() calls. The one-shot CLI, live matrix, and quickstart run one admitted
invocation per provider and therefore configure both limits to 1. The local
server also configures both limits to 1, but it creates one HttpProvider per
HTTP request, so its connection limit and reuse are scoped to that provider and
request rather than the server as a whole.
ProviderCallState, ProviderRetryInstruction, and ProviderCallResult are
JSON-serializable handoff values. A durable consumer can persist the declared
next state and schedule the instruction's delay before invoking again; restoring
at that boundary produces the same terminal result as the uninterrupted local
driver. The local driver follows transition outputs and performs only its
declared cancellation-aware wait; the deterministic transition owns retry and
terminal decisions.
Cancellation is draining: it starts no successor and retains an active invocation observation if that invocation completes. It does not promise remote provider cancellation or prompt release of provider capacity. Lifecycle values are neutral to storage and workflow runtimes. This package does not provide durable persistence, workflow scheduling, global admission, or exactly-once provider effects.
The exact encoded request body and decompressed response body are bounded by
identity-bearing transport policy limits. Complete in-limit response bodies are
retained as JSON when possible or as text otherwise; over-limit responses retain
no partial body. Original HTTP wire bytes are not retained. The standard HTTP
path redacts known credential header names. Direct
ProviderHttpRequestEvidence construction and deserialization remain
trusted-data paths.
Repository validation
The default suite is offline: pytest excludes tests marked live.
uv sync --locked --all-extras
uv run pre-commit install
scripts/pre-check.sh
uv build
Run the complete live matrix without changing the committed wire corpus:
uv run python scripts/run_live_matrix.py
Capturing and promoting replacement corpus data is a separate, deliberate
operation. It stages outside the repository, validates and redacts the
complete five-case capture, then updates data/wire-corpus/:
uv run python scripts/capture_live_corpus.py capture --promote
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dr_providers-0.3.0.tar.gz.
File metadata
- Download URL: dr_providers-0.3.0.tar.gz
- Upload date:
- Size: 39.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1701360b8af8dd3919ddab597ec8e5e56d9083d4ed2812bcf0eff58c1b1fdc8e
|
|
| MD5 |
d0d9e547e966ab512a83ad324e6628ba
|
|
| BLAKE2b-256 |
3c5f2a54441195922fc256575722118c50adf6c7b572c626c7de362e83117010
|
Provenance
The following attestation bundles were made for dr_providers-0.3.0.tar.gz:
Publisher:
release.yaml on danielle-rothermel/dr-providers
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dr_providers-0.3.0.tar.gz -
Subject digest:
1701360b8af8dd3919ddab597ec8e5e56d9083d4ed2812bcf0eff58c1b1fdc8e - Sigstore transparency entry: 2387821141
- Sigstore integration time:
-
Permalink:
danielle-rothermel/dr-providers@f4931d71c3a2cec4c03caae03b02ccb8188000c6 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/danielle-rothermel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@f4931d71c3a2cec4c03caae03b02ccb8188000c6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file dr_providers-0.3.0-py3-none-any.whl.
File metadata
- Download URL: dr_providers-0.3.0-py3-none-any.whl
- Upload date:
- Size: 60.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dead9c98a296f50ded97e3e8042416a2391c69e8d060b58e5240a930e349ec19
|
|
| MD5 |
07097530fc47bb8e14e18b62f5dab984
|
|
| BLAKE2b-256 |
040f50caf959e399221b2443f071025adb26da3a6c95cd2917387c62cc3e8fc5
|
Provenance
The following attestation bundles were made for dr_providers-0.3.0-py3-none-any.whl:
Publisher:
release.yaml on danielle-rothermel/dr-providers
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dr_providers-0.3.0-py3-none-any.whl -
Subject digest:
dead9c98a296f50ded97e3e8042416a2391c69e8d060b58e5240a930e349ec19 - Sigstore transparency entry: 2387821145
- Sigstore integration time:
-
Permalink:
danielle-rothermel/dr-providers@f4931d71c3a2cec4c03caae03b02ccb8188000c6 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/danielle-rothermel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@f4931d71c3a2cec4c03caae03b02ccb8188000c6 -
Trigger Event:
push
-
Statement type: