Metadata-Version: 2.4
Name: zoklens
Version: 2026.6.1
Summary: ZokLens Python SDK — LLM & Agent Observability via OpenTelemetry
Author-email: ZokLens Team <dev@zoklens.com>
License: Apache-2.0
Project-URL: Homepage, https://zoklens.com
Project-URL: Documentation, https://docs.zoklens.com/sdk/python
Project-URL: Repository, https://github.com/zokforce/zoklens-sdk-python
Keywords: llm,observability,tracing,agent,opentelemetry,zoklens
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software 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: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Monitoring
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: opentelemetry-api>=1.20.0
Requires-Dist: opentelemetry-sdk>=1.20.0
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.20.0
Provides-Extra: openai
Requires-Dist: openai>=1.0.0; extra == "openai"
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.20.0; extra == "anthropic"
Provides-Extra: all
Requires-Dist: openai>=1.0.0; extra == "all"
Requires-Dist: anthropic>=0.20.0; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"

# ZokLens Python SDK

LLM & Agent Observability via OpenTelemetry. Track every LLM call, agent step, and chain interaction with 3 lines of code.

## Quick Start

```bash
pip install "zoklens>=2026.6,<2027"
```

For production, freeze or lock the resolved version before deploy.

```python
import zoklens

# 1. Initialize
zoklens.init(
    api_key="zok_xxx",                    # from ZokLens Console → API Keys
    endpoint="https://api.zoklens.com",   # or your self-hosted URL
    project="my-agent",
)

# 2. Auto-instrument LLM SDKs (one line)
zoklens.instrument(providers=["openai-compatible", "anthropic"])

# 3. Your existing code — zero changes needed
import openai
client = openai.OpenAI()
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello!"}],
)
# ✅ Trace automatically captured: model, tokens, cost, latency
```

## Features

## Version Compatibility

Do not auto-upgrade the SDK at runtime. Do not add startup-time package installs,
runtime self-updaters, or automatic `pip install -U zoklens` scripts to customer
applications. Add the SDK through your normal package manager, commit the
lockfile, and upgrade through an explicit dependency change with tests. The
`2026.x` SDK family is the current compatibility window; patch and minor
releases stay backward compatible for the telemetry protocol unless release
notes say otherwise.

Every trace includes SDK metadata so ZokLens can detect outdated clients:

- `zoklens.sdk.version`
- `zoklens.sdk.language`
- `zoklens.sdk.protocol_version`
- `zoklens.sdk.compatibility_family`

### Auto-Instrumentation

Automatically patches LLM SDKs to capture traces — zero code changes to your LLM calls.

```python
zoklens.instrument(providers=["openai-compatible"])  # OpenAI, DeepSeek, Gemini-compatible, custom gateways
zoklens.instrument(providers=["anthropic"])          # Anthropic SDK
zoklens.instrument(providers=["deepseek"])           # Alias for OpenAI-compatible DeepSeek setups
```

**Captured attributes**:

- Canonical GenAI: `gen_ai.request.model`, `gen_ai.response.model`, `gen_ai.provider.name`, `gen_ai.usage.input_tokens`, `gen_ai.usage.output_tokens`, `gen_ai.usage.total_tokens`
- Compatibility aliases: `llm.model`, `llm.request.model`, `llm.response.model`, `llm.provider`, `llm.tokens.input`, `llm.tokens.output`, `llm.tokens.total`, `llm.duration_ms`

When both request and response models are present, ZokLens uses the response
model for display because it reflects the actual provider result. The SDK
preserves exact provider model strings and does not write `"unknown"` as a model.

### Custom Spans

Track any operation in your agent pipeline:

```python
with zoklens.span("retrieval", metadata={"query": "cost trends", "top_k": 5}):
    docs = retriever.search(query)

with zoklens.span("generation", metadata={"model": "gpt-4o"}):
    response = llm.generate(prompt)
```

### Session Tracking

Group related spans under a session with user context:

```python
with zoklens.session(user_id="u123", session_id="s456"):
    # All spans inside automatically get user_id and session_id
    with zoklens.span("step-1"):
        ...
    with zoklens.span("step-2"):
        ...
```

### Shutdown

Flush pending spans before exit:

```python
zoklens.shutdown()
```

## How It Works

```
Your App                          ZokLens
┌─────────────────────┐         ┌──────────────┐
│  import zoklens      │         │              │
│  zoklens.init(...)   │  OTLP  │  Trace Store │
│  zoklens.instrument()│────────→│  Cost Calc   │
│                      │  HTTP  │  AI Copilot  │
│  llm.chat(...)       │         │              │
└─────────────────────┘         └──────────────┘
```

The SDK uses OpenTelemetry under the hood:

- Configures a `TracerProvider` with a custom `ZokLensSpanExporter`
- Exports traces via **OTLP/HTTP** to `POST /api/v1/otel/v1/traces`
- Authenticates with `X-API-Key` header for tenant isolation

## SDK vs Proxy

| | Proxy (Sprint 10) | SDK (Sprint 12) |
|---|---|---|
| Setup | Change `BASE_URL` | `import zoklens` |
| Code changes | Zero | 3 lines |
| Trace depth | HTTP layer | Span/chain level |
| Custom attributes | ❌ | ✅ user_id, session, metadata |
| Agent internals | ❌ | ✅ step/tool/chain tracking |
| Best for | Quick start | Agent developers |

Both can be used simultaneously.

## Requirements

- Python ≥ 3.9
- OpenTelemetry SDK (installed automatically)

## License

Apache-2.0
