Official Python SDK for the Ciralgo Platform API.
Version: 1.1.0 (mirrors openapi.json info.version).
pip install ciralgoRequires Python 3.9+.
from ciralgo import Client
client = Client(api_key="sk-cg-...") # or set CIRALGO_API_KEY in your env
response = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": "Say hello."}],
)
print(response["choices"][0]["message"]["content"])The SDK reads the API key from (in order):
- The
api_key=argument toClient(...)orAsyncClient(...). - The
CIRALGO_API_KEYenvironment variable.
If neither is set, AuthenticationError is raised at construction time.
The optional CIRALGO_BASE_URL env var overrides the default https://api.ciralgo.com. This is useful for staging or for self-hosted Ciralgo deployments.
The four public proxy operations from the Ciralgo OpenAPI spec (v1.1.0):
response = client.chat.completions.create(
model="anthropic/claude-sonnet-4-6",
messages=[
{"role": "system", "content": "You are a finance compliance assistant."},
{"role": "user", "content": "Summarise EU AI Act Article 15."},
],
temperature=0.2,
max_tokens=400,
tags={"project": "ai-act-summariser", "env": "prod"},
)for chunk in client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": "Stream me a haiku."}],
stream=True,
):
delta = chunk["choices"][0]["delta"].get("content", "")
print(delta, end="", flush=True)embedding = client.embeddings.create(
model="openai/text-embedding-3-small",
input="EU AI Act Article 15 covers accuracy, robustness and cybersecurity.",
)
print(len(embedding["data"][0]["embedding"])) # → vector dimensionusage = client.usage.get(from_date="2026-06-01", to_date="2026-06-30")
print(usage["total_cost_usd"], usage["calls"])response = client.anthropic.messages_create(
model="anthropic/claude-sonnet-4-6",
max_tokens=400,
system="You are an EU compliance assistant.",
messages=[{"role": "user", "content": "What is GDPR Article 32?"}],
)
print(response["content"][0]["text"])The SDK maps HTTP status codes to typed exceptions. Catch the specific class:
from ciralgo import Client
from ciralgo.errors import RateLimitError, UpstreamError, AuthenticationError
try:
response = client.chat.completions.create(...)
except RateLimitError as e:
time.sleep(e.retry_after or 5)
# retry
except UpstreamError as e:
# upstream LLM provider 5xx, pick a different model
...
except AuthenticationError:
# rotate / re-issue the key
raiseEvery exception carries:
code: stable string error code from the API envelope (e.g.rate_limit_exceeded)message: human-readabletrace_id: pass this to Ciralgo support to look up the request server-sidestatus_code: HTTP statusretry_after: only set on 429
import asyncio
from ciralgo import AsyncClient
async def main():
async with AsyncClient() as client:
# NOTE: async surface in v1.1.0 is the client construction +
# close lifecycle. Full async parity for chat / embeddings ships
# in v1.2.0.
pass
asyncio.run(main())The current client is hand-written. A codegen-based replacement is viable using openapi-python-client against the published Ciralgo OpenAPI spec. The hand-written client gives us control over:
- Streaming semantics (
stream=Truereturning an iterator). - The
X-Ciralgo-Tagsheader marshalling. - The typed exception hierarchy (codegen produces a single error class).
A future major bump (v2.0.0) can switch to codegen if the trade-offs
change.
From the SDK repo root:
pip install -e ".[dev]"
pytest
ruff check src
mypy srcPublishing to PyPI is handled by a GitHub Actions workflow triggered on
tags of the form sdk-py-v*. The workflow uses PyPI Trusted Publishing
(OIDC). No long-lived API token is stored in CI secrets.
The engineer-facing release runbook (version bump, tag push, environment approval, troubleshooting) is at docs/publish-runbook.md.
Apache-2.0