SOLWYN

How it works

Why Solwyn is a wrapper, not a proxy — the context-engine and intelligence-engine split, direct-to-provider calls, and the fail-open default.

Solwyn is a wrapper, not a proxy. When you write Solwyn(OpenAI()), you get back an object with the same surface as the client you passed in — and, since 0.6.0, one that passes the same type checks. Your LLM calls travel directly from your application to the provider — Solwyn is never in the request or response path. After each call returns, the SDK reads the token counts the provider already put on the response and forwards only those counts to Solwyn Cloud.

Your App + Solwyn SDK                    Solwyn Cloud
+-----------------------+                +------------------+
|  your code            |  token counts  |  PricingService  |
|    |                  |  (no prompts)  |  Budget state    |
|  Solwyn(OpenAI())     | -------------> |  Cost dashboard  |
|    |                  |                |  Alerts          |
|  LLM provider <------ -- direct call  +------------------+
+-----------------------+

Type-transparent wrappers

SDK v0.6.0+. Frameworks and type-checked code often gate on the provider's class. The wrapper is built to pass those gates without pretending to be something it is not:

from openai import OpenAI
from solwyn import Solwyn

client = Solwyn(OpenAI(), api_key="sk_proj_...")

isinstance(client, OpenAI)   # True  -- the wrapper is admitted wherever an OpenAI client is expected
isinstance(client, Solwyn)   # True
client.__class__ is OpenAI   # True
type(client) is Solwyn       # True  -- type() stays truthful

__class__ reports the wrapped provider class (so isinstance succeeds against it and against its base classes), while type() still returns Solwyn. Pydantic fields typed as the provider class (with arbitrary_types_allowed) accept the wrapper. Two edges are worth knowing: issubclass(type(client), OpenAI) is False, because only isinstance consults __class__; and wrapping a wrapper raises ConfigurationError rather than nesting.

Attribute writes and deletes forward to the provider client, so client.timeout = 5.0 configures the real client. Solwyn's own state lives under _solwyn_* names that never forward in either direction; every other private name belongs to the provider. copy.copy and copy.deepcopy return the same wrapper rather than cloning live reporter state, and pickling raises TypeError — construct a fresh client in the target process. See the Solwyn reference.

Two engines

The SDK and the cloud API split responsibilities cleanly:

  • The SDK is a context engine. After each LLM call, it reads the raw token counts from the provider's usage fields and normalizes them into a single breakdown. It does no pricing math itself.
  • The cloud API is the intelligence engine. It owns all pricing tables, computes dollar costs from those token counts, enforces budget limits, and powers the dashboard and alerts.

This split is why pricing updates require only an API deploy — never an SDK release. The counts the SDK sends are stable; the cost computed from them lives entirely server-side.

Calls go direct to the provider

Because Solwyn wraps rather than proxies, the control plane being slow or unreachable cannot slow down or block your LLM traffic by default. The request path is your process to the provider, full stop. Solwyn observes the result after the fact; it never sits between you and the model.

The control plane is off the hot path

New in 0.4.0. Wrapping was always direct-to-provider, but the SDK still spoke to Solwyn twice around each call: a blocking budget check before, and a blocking cost confirmation after. Both are now off the caller's thread.

  • Before the call. A run-scoped lease grants token authority once, then admits calls from memory and renews in the background. The per-call check remains for traffic outside that scope, now on a short 1-second timeout.
  • After the call. Settlement is built without I/O and handed to the background reporter. The provider's response is no longer withheld while Solwyn answers. See Spend delivery.
  • When Solwyn is down. A circuit breaker around Solwyn Cloud itself discovers an outage once per client instead of re-paying a timeout on every call.

The privacy boundary is unchanged by all of this — a lease carries token counts and the model names you configured, never content.

SDK v0.6.0+: the same pre-flight check now carries two more things back — relative price hints and run-control directives. Solwyn Cloud can attach hints for the providers in your failover chain, which CostPolicy uses to prefer a cheaper healthy provider — the SDK still does no price arithmetic, it only orders by the server's numbers. See Cost-aware routing; the directives are the next section.

The control plane can stop a run

SDK v0.6.0+. Budget enforcement decides whether one call may proceed. A run stop ends a whole unit of work: an operator presses Stop on a run in the dashboard, Solwyn Cloud denies that run's next check or lease renewal with a terminate directive, and the SDK raises RunStoppedError on the next call — and aborts any stream already open — until the run id is retired. The SDK also runs a local velocity detector that can flag or stop a run that is looping, without any server involvement. A stop is retained through an outage and is never softened by fail_open or alert_only. See Run control.

Fail-open by default

If Solwyn Cloud is unreachable, your LLM calls proceed normally with local tracking — there is no downtime from the control plane. This is the default (fail_open=True). Hard enforcement that can block calls is opt-in: set budget_mode="hard_deny" (every tier can, with one hard-cap project on Free), and optionally fail_open=False to deny calls when the budget service is unreachable. A run stop or a sticky hard deny already on record is preserved through an outage in either posture. See Budget Enforcement for the full enforcement model.

What this buys you

  • No prompt capture — only token counts and structural metadata leave your process. The SDK never reads, logs, or transmits your prompts or responses.
  • Provider-agnostic — wrap OpenAI, Anthropic, Google Gemini, Amazon Bedrock, or Together clients, or any OpenAI-compatible endpoint, with the same surface. See Providers.
  • Server-side pricing — the API owns every pricing table, so new models and rate changes ship without touching your code.

The exact wire contract

This page describes the shape of the design. For the precise, field-by-field list of what is and is not transmitted — the canonical MetadataEvent contract — see Privacy. The SDK is open source, so the claim is auditable.

On this page