Metadata-Version: 2.5
Name: observra-sdk-python
Version: 0.1.7
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: dev
Requires-Dist: anthropic; extra == 'dev'
Requires-Dist: black; 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": "..."}])
```

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.

