Metadata-Version: 2.4
Name: lanternfish
Version: 0.3.0
Summary: Lanternfish SDK: trace AI agent runs, decisions and releases with OpenTelemetry.
License-Expression: MIT
Project-URL: Documentation, https://github.com/TriTetra/agentlens-sdk/tree/master/lanternfish#readme
Project-URL: Source, https://github.com/TriTetra/agentlens-sdk
Keywords: ai-agents,observability,opentelemetry,llm,tracing
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Operating System :: OS Independent
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: opentelemetry-api<2,>=1.25.0
Requires-Dist: opentelemetry-sdk<2,>=1.25.0
Requires-Dist: requests<3,>=2.31.0
Provides-Extra: openai
Requires-Dist: opentelemetry-instrumentation-openai<1,>=0.40.0; extra == "openai"
Provides-Extra: anthropic
Requires-Dist: opentelemetry-instrumentation-anthropic<1,>=0.40.0; extra == "anthropic"
Provides-Extra: gemini
Requires-Dist: opentelemetry-instrumentation-google-generativeai<1,>=0.40.0; extra == "gemini"
Provides-Extra: groq
Requires-Dist: opentelemetry-instrumentation-groq<1,>=0.40.0; extra == "groq"
Provides-Extra: langchain
Requires-Dist: opentelemetry-instrumentation-langchain<1,>=0.40.0; extra == "langchain"
Provides-Extra: crewai
Requires-Dist: opentelemetry-instrumentation-crewai<1,>=0.40.0; extra == "crewai"
Provides-Extra: llamaindex
Requires-Dist: opentelemetry-instrumentation-llamaindex<1,>=0.40.0; extra == "llamaindex"
Provides-Extra: all
Requires-Dist: lanternfish[anthropic,crewai,gemini,groq,langchain,llamaindex,openai]; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"

# Lanternfish Python SDK

Record what your AI agent does: its LLM calls, its own steps, the decisions it makes and the release it runs on.
Lanternfish compares those runs over time and tells you what changed.

Built on OpenTelemetry. Works next to an existing OpenTelemetry or Logfire setup.

## Install

```bash
pip install "lanternfish[openai]"
```

Use the extra for each provider you call: `openai`, `anthropic`, `gemini`, `groq`, `langchain`, `crewai`,
`llamaindex`, or `all`. Requires Python 3.11+.

## Start

```bash
export LANTERNFISH_API_KEY="lfsk_..."            # Settings → API keys
export LANTERNFISH_ENDPOINT="https://your-lanternfish-endpoint"
```

```python
import lanternfish

lanternfish.instrument(agent="travel-agent")
```

From here on, calls to installed providers are recorded. The SDK never picks a destination by itself: without an
endpoint it stops with an error that says what to set.

## Record your own steps and decisions

```python
import lanternfish

@lanternfish.trace                                  # records arguments; capture_args=False for private data
def search_flights(destination: str) -> list[str]:
    ...

with lanternfish.set_user("user_42", session_id="sess_9"):   # removed again when the block ends
    with lanternfish.span("book-trip"):
        options = search_flights("Lisbon")
        with lanternfish.reasoning(name="pick_flight") as r:
            r.consider_option("KLM 1724", score=0.8, reason="Arrives before the meeting")
            r.decide("KLM 1724", confidence=0.8, reason="Arrives before the meeting")
```

A step that raises is marked failed, with the exception type and message.

## Releases

Every span carries the release it ran on: `release=` if you pass it, otherwise `LANTERNFISH_RELEASE`, otherwise the
commit your CI or host exposes (`GITHUB_SHA`, `VERCEL_GIT_COMMIT_SHA`, `RENDER_GIT_COMMIT`, …). To mark the moment a
release went live, call this from your deploy step:

```python
lanternfish.record_deployment("v1.8.2", metadata={"commit": "a1b2c3d", "environment": "production"})
```

## Options

| `instrument()` argument | If omitted | |
|---|---|---|
| `api_key` | `LANTERNFISH_API_KEY` | Project API key, sent only in the `x-api-key` header |
| `endpoint` | `LANTERNFISH_ENDPOINT` | Your Lanternfish API base URL |
| `agent` | — | Agent name on every run |
| `release` | `LANTERNFISH_RELEASE` or CI commit | Version of the running code |
| `environment` | `LANTERNFISH_ENVIRONMENT` | For example `production` |
| `include` | `[]` | Also record `"http"`, `"sql"`, `"redis"` calls |
| `capture_content` | `True` | Record prompt and completion text of LLM calls |

## What is recorded

- **LLM calls:** model, tokens, duration, errors and, unless `capture_content=False`, the prompt and completion text.
- **HTTP** (only with `include=["http"]`): method, host, path and status. Never bodies, headers or query strings.
- **SQL** (only with `include=["sql"]`): the statement with literals replaced by `?`. Never parameter values.

## Short scripts and serverless

Spans are sent in the background in batches. Call `lanternfish.flush()` before a short script or a serverless handler
returns; `lanternfish.shutdown()` runs on process exit by itself.

## Troubleshooting

```python
import logging
logging.basicConfig(level="INFO")
```

The `lanternfish` logger names the endpoint, lists the integrations it turned on, and logs every rejected batch with
the reason (invalid key, plan limit reached, endpoint unreachable). Sending never raises into your code; a temporary
error is retried once.

## License

MIT
