Metadata-Version: 2.4
Name: rendfly
Version: 0.1.0
Summary: rendfly — agent observability. One line to see your agent's full execution tree.
Project-URL: Homepage, https://rendfly.com
Project-URL: Documentation, https://rendfly.com/docs/integrations/python-sdk
Author: rendfly
License-Expression: MIT
License-File: LICENSE
Keywords: agents,llm,observability,opentelemetry,tracing
Requires-Python: >=3.10
Requires-Dist: openinference-instrumentation-anthropic>=0.1.9
Requires-Dist: openinference-instrumentation-openai>=0.1.18
Requires-Dist: openinference-instrumentation>=0.1.18
Requires-Dist: openinference-semantic-conventions>=0.1.9
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.27.0
Requires-Dist: opentelemetry-sdk>=1.27.0
Provides-Extra: all
Requires-Dist: openinference-instrumentation-crewai>=0.1.8; extra == 'all'
Requires-Dist: openinference-instrumentation-langchain>=0.1.29; extra == 'all'
Provides-Extra: crewai
Requires-Dist: openinference-instrumentation-crewai>=0.1.8; extra == 'crewai'
Provides-Extra: dev
Requires-Dist: httpx>=0.27; extra == 'dev'
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff==0.15.22; extra == 'dev'
Provides-Extra: langgraph
Requires-Dist: openinference-instrumentation-langchain>=0.1.29; extra == 'langgraph'
Description-Content-Type: text/markdown

# rendfly

**See your agent's full execution tree. One line.**

rendfly is observability for LLM apps and AI agents. Add this SDK (or point your traffic at rendfly's proxy) and you get a live trace of every LLM call, tool call, and retrieval step your agent makes — with cost and latency at each step — so when something breaks in production you can see exactly where, and why.

Built on OpenTelemetry and OpenInference, so it plugs into infrastructure you likely already trust.

## Install

```bash
pip install rendfly
```

OpenAI and Anthropic are auto-instrumented out of the box — nothing extra to install. For CrewAI and LangGraph support:

```bash
pip install "rendfly[all]"
```

(Or install just what you need: `pip install "rendfly[crewai]"` / `pip install "rendfly[langgraph]"`.)

## Quickstart

```python
import rendfly
rendfly.init()                          # reads RENDFLY_API_KEY; endpoint default https://proxy.rendfly.com

from openai import OpenAI               # auto-instrumented, nothing else to write
OpenAI().chat.completions.create(...)   # -> llm span: tokens, model, cost-ready, redacted body

@rendfly.agent                          # span kind=agent
def support(q: str) -> str:
    plan = make_plan(q)                 # span kind=task
    with rendfly.span("vector-search", kind="retrieval") as s:
        s.set_attribute("top_k", 8)     # a step your LLM provider can't see
        return db.search(q)

@rendfly.task
def make_plan(q): ...

with rendfly.session("conv-123"):       # ties everything below to one conversation
    support("...")
```

Set `RENDFLY_API_KEY` (an `rfk_proj_...` project key from your rendfly project) in your environment and you're capturing traces. No key set — the SDK quietly runs as a no-op and your app behaves exactly as before; a missing or invalid key never crashes startup.

## Merge with your proxy traffic

If you already route your LLM calls through rendfly's proxy (swap `base_url` to `https://proxy.rendfly.com`, one line, no other code changes), the proxy is already capturing every LLM call it forwards. Wrapping a block of code in `rendfly.session("conv-123")` — using the same conversation id you already track — tells the SDK to stamp that same id on every span it creates inside the block.

The result is one merged execution tree per conversation, one trace: the LLM calls the proxy already saw, plus the tool calls, retrieval steps, and agent/task structure that only your code knows about. You don't have to choose one integration over the other or migrate anything — the SDK is purely additive on top of the proxy. Skip `rendfly.session(...)` and the SDK still works fine; you just get a standalone trace instead of a merged one.

## Security & data handling

By default, rendfly captures message bodies and tool arguments but scrubs every value client-side, before anything leaves your process — PII and secrets never cross the wire in the first place. Control how much is captured with `capture_content` in `rendfly.init()`:

| `capture_content` | Message bodies / tool args | Client-side scrub | Use |
|---|---|---|---|
| `redacted` (default) | captured, scrubbed | yes | balanced — see what the agent did, PII is stripped before export |
| `metadata` | not sent | n/a | regulated environments — only kind, model, tokens, latency, status, and tool names leave your process |
| `raw` | captured verbatim | no (server still redacts) | maximum fidelity, explicit opt-in |

`redacted` is the secure default: unless you deliberately set `capture_content="raw"`, nothing goes out unscrubbed.

A few more things worth knowing:
- Your API key is sent only as an `Authorization` header on export — it is never written into a span, a log line, or an exception message, and is masked to its last 4 characters in any diagnostic output.
- Traffic requires `https://` by default; `http://` is accepted only for `localhost`, and only if you explicitly pass `allow_insecure=True`.
- `redact_patterns`, `redact_keys`, and `redactor` let you extend or fully replace the built-in scrubbing rules (emails, card numbers, tokens, and more) with your own.
- `drop_spans` and `sampler` let you exclude a whole subsystem or sample volume, so sensitive code paths never get captured at all.
- Every entry point (decorators, `span()`, instrumentation, export) fails safe: an internal SDK error is logged and swallowed, never raised into your application or your LLM call path.

## Configuration reference

Every argument is optional and falls back to an environment variable where noted; secure defaults apply if you pass nothing.

```python
rendfly.init(
    api_key=None,                       # env RENDFLY_API_KEY
    endpoint=None,                      # env RENDFLY_ENDPOINT; default https://proxy.rendfly.com
    project=None,                       # optional label; your api_key already scopes the project
    instrument=True,                    # auto-detect + instrument installed supported libraries
    session_id=None,                    # optional default session id applied to every span
    capture_content="redacted",         # "redacted" (default) | "metadata" | "raw"
    redact_patterns=None,               # extra regex patterns for value scrubbing
    redact_keys=None,                   # extra attribute-key patterns to always drop
    redactor=None,                      # callable(str) -> str to fully override value scrubbing
    drop_spans=None,                    # callable(span) -> bool to exclude specific spans
    sampler=None,                       # OpenTelemetry sampler; default parent-based always-on
    max_attr_bytes=16384,               # per-value truncation cap, in bytes
    resource_attributes=None,           # extra resource attributes (never put secrets here)
    allow_insecure=False,               # permit http:// for localhost only — dev use only
    ca_bundle=None,                     # path to a private CA bundle, for on-prem collectors
    client_cert=None,                   # path to a client certificate, for mTLS
    console_debug=False,                # print post-redaction spans to console, key masked
)
```

## License

MIT — see [LICENSE](LICENSE).
