# DriftBalloon SDK

> LLM output drift detection and observability for production AI applications

## Overview

DriftBalloon monitors your LLM outputs and detects when model behavior drifts from baseline. It stays completely out of your critical path — logging is fire-and-forget, and your app keeps working even if DriftBalloon is unreachable.

## Installation

```bash
pip install driftballoon
```

## Quick Start

```python
from driftballoon import DriftBalloon

db = DriftBalloon(api_key="db_sk_xxx")

# After each LLM call, log the response (fire-and-forget)
response = openai.chat.completions.create(model="gpt-4o", messages=[...])
db.log(
    name="support-agent",
    response=response.choices[0].message.content,
    model="gpt-4o",
).submit()

# Check which prompt version is active ("a" or "b")
active = db.get_active_prompt("support-agent")

# Check if baseline is ready
status, count = db.get_baseline_status("support-agent")
```

## API Reference

### DriftBalloon(api_key, base_url=None, sync_interval=30.0, auto_start=True)

Main client class. Can be used as a context manager.

- `api_key`: Your DriftBalloon API key (starts with `db_sk_`)
- `base_url`: API base URL (defaults to `https://api.driftballoon.com`)
- `sync_interval`: Config sync interval in seconds (default 30)
- `auto_start`: Start background sync automatically (default True)

### log(name, response, prompt=None, model=None) -> LogTask

Log an LLM response for drift detection. Returns a `LogTask`.

- `.submit()` — fire-and-forget (non-blocking, queued for background submission)
- `.invoke()` — synchronous (blocks until the server confirms receipt)

### get_active_prompt(name) -> "a" | "b" | None

Get the currently active prompt version from cached config.

### get_config(name) -> PromptConfig | None

Get the full prompt configuration from the local cache.

### get_baseline_status(name) -> (status, count)

Check if the baseline is ready (`"learning"` or `"ready"`) and how many samples have been collected. Baseline needs ~30 samples.

### start()

Start the background sync thread (called automatically when `auto_start=True`).

### stop()

Stop background sync and flush remaining queued logs.

## Features

- **Semantic drift detection** — detects when LLM responses shift meaning or topic
- **Length drift detection** — catches abnormally short or long responses
- **Fire-and-forget logging** — `log().submit()` is non-blocking; your app never waits on DriftBalloon
- **Prompt status tracking** — check which prompt version is active via `get_active_prompt()`
- **Local config cache** — prompt configs are cached and synced every 30s
- **Offline resilience** — your app keeps working if DriftBalloon is unreachable
- **Retry with backoff** — failed log submissions are retried automatically

## Environment Variables

```bash
DRIFTBALLOON_API_KEY=db_sk_xxx
DRIFTBALLOON_BASE_URL=https://api.driftballoon.com  # optional
```

## Links

- Homepage: https://driftballoon.com
- Documentation: https://docs.driftballoon.com
- Dashboard: https://driftballoon.com/dashboard
- GitHub: https://github.com/driftballoon/driftballoon-python
