Catalog PyPI
PACKAGE EXPLORERView in registry

aetia-gateway-sdk

PyPI

Public Python SDK for the Aetia LLM Gateway — governed inference, SSE streaming, async jobs, and tamper-evident run records.

aetiaanthropicgatewayinferencellmopenaisdk
Versions collected1
Direct dependencies4From release 1.1.0
Last observed20 Oct, 20:57 UTC

README

Version 1.1.0 documentation

aetia-gateway-sdk

The official Python SDK for the Aetia LLM Gateway — a governed, versioned inference facade. It wraps authentication, HTTP, and SSE so you never hand-roll requests: typed models mirror the API contract exactly, and a contract test keeps the SDK and the gateway in lockstep (GATEWAY_CONTRACT_VERSION).

pip install aetia-gateway-sdk

Requires Python 3.11+. The client is async (built on httpx.AsyncClient).

Authentication — two modes

The gateway has two external front doors; the SDK supports both.

API key (aek_…)

A long-lived key, sent directly on every request.

import asyncio
from aetia_gateway_sdk import GatewayClient, ApiKey

async def main():
    async with GatewayClient("https://api.aetia.ai", ApiKey("aek_your_key")) as client:
        result = await client.infer(model="openai:gpt-4o-mini", input="Hello, world")
        print(result.output)

asyncio.run(main())

Client credentials (OAuth2 client-credentials)

Pass a client_id / secret; the SDK exchanges them at POST /api/v1/auth/service-token for a short-lived scoped bearer, caches it, and auto-refreshes it before expiry and once on a 401. A burst of concurrent requests coalesces onto a single token exchange.

from aetia_gateway_sdk import GatewayClient, ClientCredentials

creds = ClientCredentials(client_id="svc_...", secret="...")
async with GatewayClient("https://api.aetia.ai", creds) as client:
    result = await client.infer(model="openai:gpt-4o-mini", input="Hello")
    print(result.output, result.usage)

base_url is the host root (e.g. https://api.aetia.ai), not the /gateway prefix — the SDK builds the full /api/v1/... paths itself.

The surface

Synchronous inference

result = await client.infer(
    model="openai:gpt-4o-mini",
    input="Summarize the meeting notes.",
    options={"temperature": 0.2, "max_tokens": 256},  # provider params go here
    trace_id="my-trace-123",                            # echoed as correlation_id
)
result.output          # the model output
result.routed_alias    # the provider account the engine routed to
result.usage           # token accounting
result.finish_reason
result.correlation_id  # == trace_id (or a server-stamped id)

Unknown top-level fields are rejected client-side before any HTTP call — put provider parameters in options, not at the top level.

Streaming (SSE)

stream() is an async context manager + iterator. It yields the engine's delta events and, after iteration, exposes the terminal usage / finish_reason / correlation_id plus the assembled text.

async with client.stream(model="openai:gpt-4o-mini", input="Write a haiku") as stream:
    async for event in stream:
        ...  # each engine delta event (dict)
    print(stream.text)            # assembled output
    print(stream.usage, stream.correlation_id)

Streaming requires a provider-qualified model (alias:model_id). A non-streaming provider raises StreamingUnsupportedError at open time (never a silent degrade).

Async inference jobs

submitted = await client.submit_job(model="openai:gpt-4o-mini", input="long batch job")
status = await client.get_job(submitted.job_id)
if status.status == "succeeded":
    print(status.result)

Run records (tamper-evident WORM ledger)

receipt = await client.submit_run(
    "run-42",
    usage={"total_tokens": 1200},
    project="deep-research",   # arbitrary consumer fields ride along verbatim
)
receipt.ledger_event_id, receipt.record_hash, receipt.previous_hash  # inclusion proof

view = await client.get_run("run-42")   # tenant-scoped read-back
runs = await client.list_runs()

Catalog & usage

models = await client.list_models()   # list[GatewayModelEntry], tenant-scoped
usage = await client.usage()          # own-usage counts + honest rate-limit posture

Errors

Every non-2xx response raises a typed error (all subclasses of GatewayError), carrying status_code, the machine error_code, detail, correlation_id, and retry_after where present:

ClassHTTPMeaning
AuthenticationError401Missing/invalid/expired/rejected credential
PermissionDeniedError403Authenticated but missing scope / cross-tenant
NotFoundError404Unknown job/run for this tenant
RequestValidationError422Server-side request validation failed
RateLimitError429Rate limited (retry_after)
StreamingUnsupportedError400Streaming requested on a non-streaming provider
ServerError5xxUpstream/engine failure
StreamError—An error event mid-stream

Transient failures (429, and 5xx for idempotent requests) are retried with backoff that honors Retry-After.

Contract versioning

aetia_gateway_sdk.GATEWAY_CONTRACT_VERSION pins the semantic gateway contract this SDK targets. The v1 contract is additive-compatible; a breaking change moves the API to /v2 and the SDK to 2.x. The SDK's tests/test_contract.py asserts the SDK's models match the published external OpenAPI (GET /api/v1/gateway/openapi.json) in both directions, so drift fails the build.

Development

pip install -e "sdk/python[test]"
# The in-process tests run against a real backend + real auth (only the LLM is
# mocked); the contract test needs only aetia_webapp importable (no DB).
pytest sdk/python/tests

License

Proprietary — © Aetia.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
1.1.031 Aug 20264

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

NOT_FOUND
aetia-ai/aetia

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 20:57 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:f1a50e29148eabc313e6f58d37ee426887042c5463bb829ce498ffb5caa3ddbb