Skip to main content

AI Agent Control Plane SDK — hard spending caps, automatic failover, per-agent cost attribution

Project description

Solwyn Python SDK

Budget enforcement, circuit breaking, and usage tracking for OpenAI, Anthropic, and Google LLM clients.

CI PyPI version Python 3.11+ License

Solwyn wraps your existing LLM client. Calls go directly to the provider — the SDK only reports metadata (token counts, latency, model name) to the Solwyn API. Prompts and responses never leave your application.

Installation

pip install solwyn

For improved token estimation with OpenAI models:

pip install solwyn[openai]

Quick Start

from openai import OpenAI
from solwyn import Solwyn

client = Solwyn(
    OpenAI(),
    api_key="sk_solwyn_...",
    project_id="proj_abc12345",
)

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello!"}],
)

client.close()

Or use as a context manager:

with Solwyn(OpenAI(), api_key="sk_solwyn_...", project_id="proj_abc12345") as client:
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Hello!"}],
    )

Providers

OpenAI

from openai import OpenAI
from solwyn import Solwyn

client = Solwyn(OpenAI(), api_key="sk_solwyn_...", project_id="proj_abc12345")
response = client.chat.completions.create(model="gpt-4o", messages=[...])

Anthropic

from anthropic import Anthropic
from solwyn import Solwyn

client = Solwyn(Anthropic(), api_key="sk_solwyn_...", project_id="proj_abc12345")
response = client.messages.create(model="claude-sonnet-4-20250514", max_tokens=1024, messages=[...])

Google Gemini

from google import genai
from solwyn import Solwyn

client = Solwyn(genai.Client(api_key="..."), api_key="sk_solwyn_...", project_id="proj_abc12345")
response = client.models.generate_content(model="gemini-2.0-flash", contents="Hello!")

Async

from openai import AsyncOpenAI
from solwyn import AsyncSolwyn

async with AsyncSolwyn(
    AsyncOpenAI(),
    api_key="sk_solwyn_...",
    project_id="proj_abc12345",
) as client:
    response = await client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Hello!"}],
    )

Streaming

Pass stream=True as you normally would. Solwyn wraps the stream transparently and reports usage when it completes:

stream = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello!"}],
    stream=True,
)

for chunk in stream:
    print(chunk.choices[0].delta.content or "", end="")

Budget Enforcement

Set budget_mode to control spending:

client = Solwyn(
    OpenAI(),
    api_key="sk_solwyn_...",
    project_id="proj_abc12345",
    budget_mode="hard_deny",
)
Mode Behavior
alert_only Log a warning when budget is exceeded (default)
hard_deny Raise BudgetExceededError and block the call
from solwyn import BudgetExceededError

try:
    response = client.chat.completions.create(model="gpt-4o", messages=[...])
except BudgetExceededError as e:
    print(f"Budget limit: ${e.budget_limit}, usage: ${e.current_usage}")

Configuration

Parameter Env Var Default Description
api_key SOLWYN_API_KEY required Solwyn API key
project_id SOLWYN_PROJECT_ID required Project identifier
api_url SOLWYN_API_URL https://api.solwyn.ai Solwyn API endpoint
fail_open SOLWYN_FAIL_OPEN True Allow LLM calls when Solwyn API is unreachable
budget_mode SOLWYN_BUDGET_MODE alert_only Budget enforcement mode
fallback_provider SOLWYN_FALLBACK_PROVIDER None Failover provider when primary circuit breaks

Use env vars to avoid passing credentials in code:

export SOLWYN_API_KEY="sk_solwyn_..."
export SOLWYN_PROJECT_ID="proj_abc12345"
client = Solwyn(OpenAI())  # picks up from environment

Error Handling

All SDK errors inherit from SolwynError:

Exception Raised when
BudgetExceededError Budget exceeded in hard_deny mode
ProviderUnavailableError Circuit breaker is open and no fallback exists
ConfigurationError Invalid API key or project ID format

Provider errors (e.g., openai.RateLimitError) pass through unmodified.

Data Transparency

The SDK sends a MetadataEvent after each LLM call. This is everything it transmits:

Field Type Description
project_id str Project identifier
model str Model name (e.g., gpt-4o)
provider str openai, anthropic, or google
input_tokens int Input token count
output_tokens int Output token count
token_details object Breakdown: cached, reasoning, audio tokens
latency_ms float Call duration in milliseconds
status str success, error, or budget_denied
is_failover bool Whether a fallback provider was used
sdk_instance_id str Per-process UUID for deduplication
timestamp datetime When the call completed (UTC)

The SDK never captures, logs, or transmits prompts or responses. This is enforced by structural tests and the privacy module.

Requirements

Python 3.11+

Contributing

make install          # install in dev mode
make install-hooks    # install pre-commit hook
make check            # lint + format + typecheck
make test             # run unit tests

Links

License

Apache 2.0 — see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

solwyn-0.1.0.tar.gz (118.0 kB view details)

Uploaded Source

Built Distribution

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

solwyn-0.1.0-py3-none-any.whl (42.2 kB view details)

Uploaded Python 3

File details

Details for the file solwyn-0.1.0.tar.gz.

File metadata

  • Download URL: solwyn-0.1.0.tar.gz
  • Upload date:
  • Size: 118.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for solwyn-0.1.0.tar.gz
Algorithm Hash digest
SHA256 fa1c1501091ed293f9b64b7e84c9fba520542787c67e80eec11d35ce4258e05b
MD5 6323f23c7ab206f8774557743bae17c3
BLAKE2b-256 cedaef2fb563018a277069ecdc3f1be5d3c34c326c86e0774dd7eb85b1ac030c

See more details on using hashes here.

Provenance

The following attestation bundles were made for solwyn-0.1.0.tar.gz:

Publisher: publish.yml on solwyn-ai/solwyn-python

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

File details

Details for the file solwyn-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: solwyn-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 42.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for solwyn-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b323d65dcc111178d0ca16b79c945978390ec46b19701c6fd81e54fefb95c5d2
MD5 d6c9552cdc60cfd6c72f9a4c8bc0b5f9
BLAKE2b-256 cc997a14103b90cb97fea7a56371e396513c4ef46acc1d43d4afd380df8b7b0f

See more details on using hashes here.

Provenance

The following attestation bundles were made for solwyn-0.1.0-py3-none-any.whl:

Publisher: publish.yml on solwyn-ai/solwyn-python

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