Metadata-Version: 2.4
Name: belvedir-loop
Version: 0.2.0
Summary: Belvedir Loop SDK — auto-instrument your Python AI agent for recursive self-improvement
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: traceloop-sdk<0.70,>=0.62
Requires-Dist: httpx>=0.27

# belvedir-loop

Belvedir Loop SDK for Python — auto-instrument your AI agent for recursive self-improvement.

The Python counterpart of [`@belvedir/loop`](https://www.npmjs.com/package/@belvedir/loop): same concepts (`initialize`, sessions, tasks, `flush`), Python idioms (context managers instead of callbacks).

## Install

```bash
pip install belvedir-loop
```

## Quick Start

Call `initialize()` once at process startup — before your agent starts making LLM calls. Instrumentation (via OpenLLMetry) patches the installed LLM client libraries at the class level, so clients created earlier are still traced, but initializing first is the safe default:

```python
import os
import belvedir_loop as loop

loop.initialize(
    api_key=os.environ["BELVEDIR_API_KEY"],
    app_name="my-agent",
)
```

There is no `instrumentModules` equivalent — Python has no bundler, so auto-instrumentation always sees your installed `anthropic` / `openai` / LangChain / etc. packages.

## Sessions — link traces so Belvedir can find tasks

This is what powers Tasks & Groups. Wrap each agent run in `session` so every LLM and tool span is linked under one session id. Optionally wrap distinct units of work in `task()` for sharper task boundaries:

```python
with loop.session(session_id=chat_id, user_id=user.id):
    with loop.task("send_email"):
        agent.run("email danny the report")
```

Both are plain context managers; they propagate across `await` boundaries, so they work inside `async def` bodies too. Without `session` you still get raw traces, but they can't be grouped into sessions or segmented into tasks. (`with_session` is an alias for `session`, mirroring the JS SDK's `withSession`.)

## Short-lived processes — flush before exiting

Spans are exported in batches. Scripts, batch jobs, and serverless handlers can exit before the batch ships — call `flush()` before returning:

```python
loop.flush()
```

Or pass `disable_batch=True` to `initialize()` to export every span immediately (useful for local testing).

## Configuration

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `api_key` | str | required | Your Belvedir API key (`fr_live_...`) |
| `base_url` | str | `https://platform.belvedir.ai` | Belvedir platform URL |
| `app_name` | str | `belvedir-loop-app` | Your application name |
| `disable_batch` | bool | `False` | Export each span immediately instead of batching |

## API

| Function | Description |
|----------|-------------|
| `initialize(...)` | Patches your LLM clients and starts exporting spans. Call once, at startup. |
| `session(session_id, user_id=None, metadata=None)` | Context manager: every span produced inside is linked under the session id. Required for Tasks & Groups. `with_session` is an alias. |
| `task(name)` | Context manager: optional boundary hint wrapping one unit of agent work in a named span, so segmentation knows where a task starts and ends. |
| `flush()` | Forces pending spans to export. Call before a short-lived process exits. Never raises. |

## Supported Providers

Anything OpenLLMetry instruments, including OpenAI, Anthropic, Cohere, Azure OpenAI, Amazon Bedrock, Google Vertex AI, Replicate, HuggingFace, and frameworks like LangChain and LlamaIndex.

## Local Development

If running Belvedir locally:

```python
loop.initialize(
    api_key="your-key",
    base_url="http://localhost:3000",
    app_name="my-app",
    disable_batch=True,  # send spans immediately
)
```

## Troubleshooting

**Traces arrive but no tasks or groups form.**
Work must run inside `session`. Tasks appear ~30s after a session goes quiet.

**No traces at all.**
`base_url` must be a host that serves the ingest API (`https://platform.belvedir.ai`, the default; `https://belvedir.ai` still works; the pre-rename `platform.fractalresearch.ai` is retired) — any other host 404s and spans drop silently. For short-lived processes, make sure `flush()` runs before exit. Initialization and export failures never raise; they log warnings under the `belvedir.loop` logger, so check your logs.
