Skip to main content

dr-providers

CI PyPI

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

dr_providers-0.3.0.tar.gz (39.1 kB view details)

Uploaded Source

Built Distribution

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

dr_providers-0.3.0-py3-none-any.whl (60.9 kB view details)

Uploaded Python 3

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

Hashes for dr_providers-0.3.0.tar.gz
Algorithm Hash digest
SHA256 1701360b8af8dd3919ddab597ec8e5e56d9083d4ed2812bcf0eff58c1b1fdc8e
MD5 d0d9e547e966ab512a83ad324e6628ba
BLAKE2b-256 3c5f2a54441195922fc256575722118c50adf6c7b572c626c7de362e83117010

See more details on using hashes here.

Provenance

The following attestation bundles were made for dr_providers-0.3.0.tar.gz:

Publisher: release.yaml on danielle-rothermel/dr-providers

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for dr_providers-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dead9c98a296f50ded97e3e8042416a2391c69e8d060b58e5240a930e349ec19
MD5 07097530fc47bb8e14e18b62f5dab984
BLAKE2b-256 040f50caf959e399221b2443f071025adb26da3a6c95cd2917387c62cc3e8fc5

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page