Configuration
import osfrom aura_sdk import AuraClient
async with AuraClient(api_key=os.environ["AURA_API_KEY"]) as aura: projects = await aura.list_projects()Arguments
Section titled “Arguments”All keyword-only: AuraClient("sk-aura-…") is a TypeError.
| Argument | Default | Does |
|---|---|---|
api_key |
required | Your company API key (sk-aura-…), sent as Authorization: Bearer |
region |
"eu" |
"eu" or "us" — a shorthand for that region’s API host. See Regions |
base_url |
the region host |
Which Aura to talk to, for a host no region names. Wins over region |
timeout |
30.0 seconds |
Per-request HTTP timeout — not the chat-turn wait |
transport |
None |
An httpx.AsyncBaseTransport to send through. See Bringing your own transport |
websocket_factory |
opens a real socket | How chat() opens the project event socket; tests pass a scripted fake |
The region hosts are exported as BASE_URL_BY_REGION,
so a log line or a health check can name the host without hard-coding it.
Closing it
Section titled “Closing it”AuraClient owns its HTTP connection pools, so it holds connections until you close it. Use it as
an async context manager:
async with AuraClient(api_key=key) as aura: ...Or close it yourself when the client outlives a single block — a module-level client shared by request handlers, for instance:
aura = AuraClient(api_key=key)try: ...finally: await aura.aclose()Leaving it to the garbage collector works until it doesn’t: connections stay open until the process exits, and under load you run out of them.
The key is always explicit
Section titled “The key is always explicit”The SDK reads no credential from the environment, so it can never pick up a key you did not pass
it. Reading os.environ[...] above is your code’s choice, not the SDK’s. What it does inherit is
what httpx inherits: the standard HTTP_PROXY / HTTPS_PROXY / NO_PROXY variables, when set.
Bringing your own transport
Section titled “Bringing your own transport”transport is the seam httpx offers for a test double, logging, retries or a proxy. Every request
the client makes goes through it — the /api/v1 calls and the byte uploads to storage alike. The
project WebSocket does not; that is websocket_factory.
In a test, httpx.MockTransport answers in-process:
import httpxfrom aura_sdk import AuraClient
def handler(request: httpx.Request) -> httpx.Response: assert request.headers["Authorization"] == "Bearer sk-aura-test" return httpx.Response(200, json={"projects": [], "total": 0, "limit": 200, "offset": 0})
async with AuraClient(api_key="sk-aura-test", transport=httpx.MockTransport(handler)) as aura: assert await aura.list_projects() == []Streaming falls back, once
Section titled “Streaming falls back, once”chat() opens the project WebSocket to follow a turn live, giving the connect five seconds and
pinging every 30 to keep it open through a long solve. When the socket cannot be opened — a proxy
that blocks WebSockets, say — the client remembers that for its lifetime and polls instead:
the reply is unaffected, but on_delta and on_tool_activity stay silent on that client. A new
AuraClient tries the socket again.
The fallback, and a socket dying mid-turn, are logged at DEBUG on the aura_sdk logger, which
configures no handlers of its own:
import logging
logging.basicConfig(level=logging.INFO)logging.getLogger("aura_sdk").setLevel(logging.DEBUG)Checking a key works
Section titled “Checking a key works”There is no dedicated ping; the cheapest real call is listing projects.
from aura_sdk import AuraApiError
try: await aura.list_projects()except AuraApiError as err: if err.status == 401: raise RuntimeError("AURA_API_KEY is missing or revoked") from err raise