# veloscope

Lightweight AI agent observability — traces, quality scores, and cost tracking in 2 lines.

```python
import veloscope
veloscope.init(api_key="vs_...")
```

## Installation

```bash
pip install veloscope
```

## Quick Start

```python
import veloscope

veloscope.init(api_key="vs_your_key_here")  # or set VELOSCOPE_API_KEY env var

@veloscope.trace("my-agent")
def run_agent(query: str) -> str:
    result = retrieve_docs(query)
    return generate_answer(result)

@veloscope.span("retrieve-docs", span_type="tool")
def retrieve_docs(query: str) -> list[str]:
    ...
```

Every call to `run_agent()` creates a trace. Nested `@span` calls are linked automatically. No configuration beyond `init()`.

## Environment Variable

```bash
export VELOSCOPE_API_KEY=vs_your_key_here
```

```python
veloscope.init()  # picks up key from env automatically
```

## API

### `veloscope.init(api_key=None, api_url=None, auto_patch=True)`

Initializes the SDK. Call once at startup. If no API key is provided (and `VELOSCOPE_API_KEY` is not set), the SDK silently no-ops — safe to leave in production code.

| Parameter | Default | Description |
|-----------|---------|-------------|
| `api_key` | `None` | Your Veloscope API key |
| `api_url` | Veloscope cloud | Override for self-hosted |
| `auto_patch` | `True` | Auto-instrument openai/anthropic clients |

### `@veloscope.trace(name=None)`

Marks a function as the root of a trace. Each call creates a new trace ID.

### `@veloscope.span(name=None, span_type="custom")`

Marks a function as a span within the current trace. Must be called inside a `@trace`-decorated function (or a function called by one). Orphan spans (no active trace) are silently skipped.

**`span_type` values:** `"llm"`, `"tool"`, `"retrieval"`, `"custom"`

### `veloscope.flush()`

Manually flush all buffered spans to the API. Called automatically on process exit and every 5 seconds by a background thread.

## Graceful Degradation

- No API key → SDK is a no-op, zero overhead
- API unreachable → spans are silently dropped, your code continues
- Exceptions in instrumented functions propagate normally

## License

MIT
