Metadata-Version: 2.4
Name: verica-observability
Version: 0.1.6
Summary: Two-line LLM tracing for Verica: init(token) and your OpenAI/Anthropic calls land as evaluable traces.
Project-URL: Homepage, https://verica.app
License-Expression: MIT
Keywords: evals,llm,observability,opentelemetry,tracing,verica
Requires-Python: >=3.9
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.27
Requires-Dist: opentelemetry-instrumentation-anthropic>=0.33
Requires-Dist: opentelemetry-instrumentation-google-genai>=0.1b0
Requires-Dist: opentelemetry-instrumentation-openai>=0.33
Requires-Dist: opentelemetry-sdk>=1.27
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Description-Content-Type: text/markdown

# verica-observability

Two-line LLM tracing for [Verica](https://verica.app): your OpenAI/Anthropic
calls land as evaluable traces.

## Install

```bash
pip install verica-observability
```

## Use

```python
import verica

verica.init(token=os.environ["VERICA_TOKEN"])

# Import the clients AFTER init so they are patched. OpenAI, Anthropic, and
# Gemini (the google-genai SDK) are all auto-traced, no extra code.
from openai import OpenAI
from anthropic import Anthropic
from google import genai
```

## Sessions (multi-turn)

Traces sharing a conversation id reassemble into a Verica session. In a server
handling many conversations, scope the id per request:

```python
with verica.conversation(f"chat-{chat_id}"):
    response = client.chat.completions.create(...)
```

Context-local (async- and thread-safe); it overrides the global
`conversation_id` from `init()`, and `verica.conversation(None)` suppresses the
attribute for the block. For a single-conversation script, passing
`conversation_id="..."` to `init()` is enough.

**Resend history exactly as sent.** Turns are stored as deltas: at ingest,
Verica matches the history you resend against what previous turns already
stored, and that match is exact (byte-identical text). If your app mutates
prior messages between requests (for example, appending "Respond in JSON" to
the last user message and stripping it from earlier turns when rebuilding the
history), no prefix ever matches and every turn falls back to storing, and
showing, the full conversation again. Keep injected instructions in the system
prompt, or resend them exactly as originally sent.

## Tags

Tags land on each trace (`traces.tags`): filter the workbench by them, and bind
criteria to them so evaluation preselects the right criteria per tag.

```python
verica.init(token=..., tags=["routina", "prod"])   # global, every trace

with verica.tags(["chat", "premium"]):              # adds to the globals
    client.chat.completions.create(...)
```

Per-request tags UNION with the globals (dedup, order preserved); nested scopes
accumulate. Context-local, async- and thread-safe. Values are coerced with
`str()`; the server caps at 20 tags x 120 chars.

## Serverless

Call `verica.flush()` (or `verica.shutdown()`) before the runtime freezes so
the span batch is exported.

## Options

| Option / env var                             | Default    | Notes                                                                   |
| -------------------------------------------- | ---------- | ----------------------------------------------------------------------- |
| `token` / `VERICA_TOKEN`                     | (required) | ingest-scoped API token                                                 |
| `capture_content` / `VERICA_CAPTURE_CONTENT` | `true`     | send prompt/response content                                            |
| `conversation_id`                            | (none)     | global `gen_ai.conversation.id`; per-request: `verica.conversation(id)` |
| `tags`                                       | (none)     | global tags; per-request: `verica.tags([...])`                          |
| `service_name` / `OTEL_SERVICE_NAME`         | `app`      | resource service.name                                                   |
| `debug` / `VERICA_DEBUG`                     | `false`    | log export errors                                                       |

Fail-open by design: if Verica is unreachable or the token is invalid, spans are
dropped and your app is never affected. Export errors are silent unless `debug`
is on.
