Metadata-Version: 2.5
Name: observra-sdk-python
Version: 0.1.8
Summary: Observra Python SDK - drop-in traced, guardrailed LLM clients routed through the Observra gateway
Project-URL: Homepage, https://observra.in
Author: Aviasole
Maintainer: Aviasole
License: Apache-2.0
License-File: LICENSE
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx>=0.24
Requires-Dist: opentelemetry-api<2,>=1.20
Requires-Dist: opentelemetry-sdk<2,>=1.20
Requires-Dist: pydantic<3,>=2
Provides-Extra: anthropic
Requires-Dist: anthropic==0.120.2; extra == 'anthropic'
Provides-Extra: cerebras
Requires-Dist: cerebras-cloud-sdk==1.91.0; extra == 'cerebras'
Provides-Extra: dev
Requires-Dist: anthropic; extra == 'dev'
Requires-Dist: black; extra == 'dev'
Requires-Dist: cerebras-cloud-sdk==1.91.0; extra == 'dev'
Requires-Dist: cohere==7.0.0; extra == 'dev'
Requires-Dist: crewai; extra == 'dev'
Requires-Dist: google-generativeai==0.8.6; extra == 'dev'
Requires-Dist: langchain-core<2.0,>=0.2; extra == 'dev'
Requires-Dist: langchain-google-genai; extra == 'dev'
Requires-Dist: langchain<2.0,>=0.2; extra == 'dev'
Requires-Dist: langgraph<2.0,>=1.2.10; extra == 'dev'
Requires-Dist: llama-index-core; extra == 'dev'
Requires-Dist: llama-index-llms-openai-like==0.3.5; extra == 'dev'
Requires-Dist: mistralai==2.5.2; extra == 'dev'
Requires-Dist: mypy; extra == 'dev'
Requires-Dist: openai; extra == 'dev'
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: pytest-asyncio; extra == 'dev'
Requires-Dist: respx; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Requires-Dist: semantic-kernel==1.38.0; extra == 'dev'
Requires-Dist: together==2.24.0; extra == 'dev'
Provides-Extra: examples
Requires-Dist: python-dotenv==1.2.2; extra == 'examples'
Provides-Extra: gemini
Requires-Dist: google-genai==2.16.0; extra == 'gemini'
Provides-Extra: langchain
Requires-Dist: langchain-core<2.0,>=0.2; extra == 'langchain'
Requires-Dist: langchain<2.0,>=0.2; extra == 'langchain'
Provides-Extra: langgraph
Requires-Dist: langgraph<2.0,>=1.2.10; extra == 'langgraph'
Provides-Extra: openai
Requires-Dist: openai==1.109.1; extra == 'openai'
Provides-Extra: semantic-kernel
Requires-Dist: google-generativeai==0.8.6; extra == 'semantic-kernel'
Requires-Dist: semantic-kernel==1.38.0; extra == 'semantic-kernel'
Description-Content-Type: text/markdown

# observra

Zero-touch tracing and gateway routing for LLM SDKs — configure once, keep writing the provider SDK's own client exactly as before.

## Install

```bash
pip install observra
```


## Configure

Only `gateway_key` is required — `gateway_url` defaults to the production gateway (`https://gateway.observra.in`):

```python
import observra

observra.configure(gateway_key="obs_live_xxx")
```

Or via environment variable (no explicit `configure()` call needed):

```bash
export OBSERVRA_GATEWAY_KEY="obs_live_xxx"
```

## Use

No wrapper client — write plain provider SDK code exactly as you already would. `configure()` transparently patches the SDK (Gemini) and, for every known provider host, patches `httpx` itself (OpenAI, Anthropic — and Gemini too, for non-SDK callers), so any request to those hosts routes through the gateway and gets traced/guardrailed, no matter which library actually made the call:

```python
from google import genai

client = genai.Client(api_key="AIza...")  # your own Gemini key, forwarded as-is

response = client.models.generate_content(
    model="gemini-2.0-flash",
    contents="Summarize this support ticket: ...",
)
print(response.text)
```

```python
from openai import OpenAI

client = OpenAI(api_key="sk-...")  # your own OpenAI key
response = client.chat.completions.create(model="gpt-4o-mini", messages=[{"role": "user", "content": "..."}])
```

```python
from anthropic import Anthropic

client = Anthropic(api_key="sk-ant-...")  # your own Anthropic key
response = client.messages.create(model="claude-3-5-sonnet-20241022", max_tokens=1024, messages=[{"role": "user", "content": "..."}])
```

Cerebras works through its native SDK, raw HTTPX, or any HTTPX-based OpenAI-compatible
client. Configure Observra before constructing the client:

```python
import observra
from cerebras.cloud.sdk import Cerebras

observra.configure(gateway_key="obs_live_xxx")
client = Cerebras(api_key="csk-...")
response = client.chat.completions.create(
    model="gpt-oss-120b",
    messages=[{"role": "user", "content": "..."}],
)
```

The OpenAI SDK works too with `base_url="https://api.cerebras.ai/v1"`. Sync and async
HTTPX clients route to `/cerebras` automatically. Cerebras' optional aiohttp backend
is not intercepted; use its default HTTPX backend.

TokenRouter works with the OpenAI SDK by setting
`base_url="https://api.tokenrouter.com/v1"`. Requests are automatically routed through
the Observra gateway at `/tokenrouter`; the upstream `/v1` prefix is removed because the
gateway handles TokenRouter's provider versioning.
Raw HTTPX requests to the same TokenRouter host are handled identically.

Same for async clients, and for any framework integration that builds one of these internally — e.g. LangChain's `ChatGoogleGenerativeAI` routes through the gateway automatically too, no extra step. See `examples/raw_http_gemini.py` for the same guarantee at the raw-HTTP level — no provider SDK at all, just `httpx` pointed straight at Google's real endpoint.

Inside a LangChain agent — `instrument()` additionally traces every step (agent/chain/tool boundaries) under one trace, on top of the LLM-call-level tracing `configure()` already gives you:

```python
observra.instrument()
```

Guardrails (PII/secret detection on prompts and responses) run on every call automatically — violations are recorded as span events (`guardrail.violation`), the payload itself is never blocked or altered.

See [`examples/`](examples/) for full runnable scripts, and traces show up in your Observra dashboard's Request Flow view.
