Metadata-Version: 2.4
Name: adeptiv-ai-evaluator-sdk
Version: 1.55.0.dev1
Summary: Adeptiv GenAI tracing SDK for LLMs, agents, and AI workflows
Author-email: Adeptiv AI <contact@adeptiv-ai.com>
License: Apache-2.0
Description-Content-Type: text/markdown
Requires-Dist: opentelemetry-api
Requires-Dist: opentelemetry-sdk
Requires-Dist: opentelemetry-exporter-otlp-proto-common
Requires-Dist: opentelemetry-instrumentation-logging
Requires-Dist: websockets<17,>=13
Provides-Extra: openai
Requires-Dist: openinference-instrumentation-openai; extra == "openai"
Provides-Extra: openai-agents
Requires-Dist: openinference-instrumentation-openai-agents; extra == "openai-agents"
Provides-Extra: anthropic
Requires-Dist: openinference-instrumentation-anthropic; extra == "anthropic"
Provides-Extra: litellm
Requires-Dist: openinference-instrumentation-litellm; extra == "litellm"
Provides-Extra: langchain
Requires-Dist: openinference-instrumentation-langchain; extra == "langchain"
Provides-Extra: llama-index
Requires-Dist: openinference-instrumentation-llama-index; extra == "llama-index"
Provides-Extra: vertexai
Requires-Dist: openinference-instrumentation-vertexai; extra == "vertexai"
Provides-Extra: bedrock
Requires-Dist: openinference-instrumentation-bedrock; extra == "bedrock"
Provides-Extra: google-genai
Requires-Dist: openinference-instrumentation-google-genai; extra == "google-genai"
Provides-Extra: mistralai
Requires-Dist: openinference-instrumentation-mistralai; extra == "mistralai"
Provides-Extra: groq
Requires-Dist: openinference-instrumentation-groq; extra == "groq"
Provides-Extra: dspy
Requires-Dist: openinference-instrumentation-dspy; extra == "dspy"
Provides-Extra: crewai
Requires-Dist: openinference-instrumentation-crewai; extra == "crewai"
Provides-Extra: haystack
Requires-Dist: openinference-instrumentation-haystack; extra == "haystack"
Provides-Extra: smolagents
Requires-Dist: openinference-instrumentation-smolagents; extra == "smolagents"
Provides-Extra: autogen
Requires-Dist: openinference-instrumentation-autogen; extra == "autogen"
Provides-Extra: instructor
Requires-Dist: openinference-instrumentation-instructor; extra == "instructor"
Provides-Extra: all
Requires-Dist: openinference-instrumentation-openai; extra == "all"
Requires-Dist: openinference-instrumentation-openai-agents; extra == "all"
Requires-Dist: openinference-instrumentation-anthropic; extra == "all"
Requires-Dist: openinference-instrumentation-litellm; extra == "all"
Requires-Dist: openinference-instrumentation-langchain; extra == "all"
Requires-Dist: openinference-instrumentation-llama-index; extra == "all"
Requires-Dist: openinference-instrumentation-vertexai; extra == "all"
Requires-Dist: openinference-instrumentation-bedrock; extra == "all"
Requires-Dist: openinference-instrumentation-google-genai; extra == "all"
Requires-Dist: openinference-instrumentation-mistralai; extra == "all"
Requires-Dist: openinference-instrumentation-groq; extra == "all"
Requires-Dist: openinference-instrumentation-dspy; extra == "all"
Requires-Dist: openinference-instrumentation-crewai; extra == "all"
Requires-Dist: openinference-instrumentation-haystack; extra == "all"
Requires-Dist: openinference-instrumentation-smolagents; extra == "all"
Requires-Dist: openinference-instrumentation-autogen; extra == "all"
Requires-Dist: openinference-instrumentation-instructor; extra == "all"

# Adeptiv GenAI Tracing SDK

**Adeptiv GenAI** is a lightweight, vendor-neutral **OpenTelemetry tracing SDK** for **LLMs, agents, and AI workflows**.

It captures **latency, execution flow, hashes, and metadata** for all AI use cases.

---

## Key Features

-  **Trace-only observability** (no response normalization)
- Works with **any LLM** (OpenAI, Anthropic, Gemini, local models)
- Supports **chat, summarization, agents, tools, RAG**
- **Sync & async** compatible
- **Enterprise-safe** (hashing, redaction, previews)
- **OpenTelemetry compatible**
---

This ensures **zero lock-in** and **maximum compatibility**.

---

## Installation

```bash

pip install adeptiv-ai-evaluator-sdk

```

# Adeptiv GenAI Tracing SDK


Tracing an LLM Call

```python


SDK configuration

config.endpoint = "wss://<adeptiv host>/ws/sdk/" # Adeptiv endpoint (set before the key)
config.api_key = "" #project Key 
config.project_name = "customer-support-bot" # Project Name


from adeptiv_evaluator_sdk import trace_llm

@trace_llm(model="gpt-4o", operation="chat", workflow_id="")
def chat(prompt):
    return llm.invoke(prompt)

chat("Hello world")

```


```python
# Adeptiv GenAI Tracing Agents SDK

from adeptiv_evaluator_sdk import trace_llm

@trace_agent("support_agent", model="gpt-4o",workflow_id="")
async def run_agent(query):
    return await agent.run(query)


```


---

## Containment

When a containment rule in Adeptiv acts on an agent (pause it, block a tool,
allow only approved models, slow it down), the SDK enforces it inside your
process. Only the agent the rule acted on is affected; every other agent keeps
working.

The SDK keeps the use case's policy in memory and refreshes it in the
background (every 15 s by default), so a check costs about a microsecond and
never makes a network call. An action stays until someone resumes the agent in
Adeptiv; if Adeptiv cannot be reached, the last policy stays in force. If the
policy has never been fetched, nothing is enforced: an Adeptiv outage never
stops your agents.

Every `@trace` call is checked (`contained=True` is the default); pass
`contained=False` for a call that must never be stopped. Name agents the way
they are named in Adeptiv:

```python
from adeptiv_evaluator_sdk import trace, ContainmentError

@trace(operation="agent", agent_name="Refund Agent")
def refund_agent(question):             # pause, approved models, slow down
    ...

@trace(operation="tool")
def issue_refund(order_id):             # blocked for the current agent?
    ...

@trace(operation="chat", model="gpt-4.1")
def ask_model(prompt):                  # outside the approved models?
    ...

try:
    reply = refund_agent(question)
except ContainmentError as exc:        # AgentPaused, ToolBlocked, ModelNotApproved, RateLimited
    reply = exc.fallback_message       # "A team member will reply to you shortly." or the rule's message
```

A refused call still shows on its span, marked with the action. A contained
agent call makes its agent the current one, so contained tool and model calls
inside it are checked for that agent.

For a tool dispatcher or a model call you cannot trace, check it before it
runs; the agent is the one of the enclosing contained agent call:

```python
from adeptiv_evaluator_sdk import guard_tool, guard_model

for call in response.tool_calls:
    guard_tool(call.name)              # raises ToolBlocked if this tool is blocked
    run_tool(call)
guard_model("gpt-4.1")                 # raises ModelNotApproved outside the approved list
```

| Setting | Env var | Default |
|---|---|---|
| `containment_enabled` | `ADEPTIV_CONTAINMENT` | `true` |
| `containment_initial_wait_seconds` | `ADEPTIV_CONTAINMENT_INITIAL_WAIT` | `1` (first call of a process only) |
| `containment_max_wait_seconds` | `ADEPTIV_CONTAINMENT_MAX_WAIT` | `10` (slow-down wait before `RateLimited`) |

Inside a `@trace` span, a refused or delayed call marks it with `adeptiv.containment.action`,
`adeptiv.containment.outcome` (`blocked` / `delayed`) and
`adeptiv.containment.event_id`, so Adeptiv can show the containment held.

---

### LangChain and LangGraph

Nothing to add in a LangGraph app: once the SDK is initialised, every graph
node, tool and model call is checked before it runs. The node name is the
agent, so a pause on "Recommendation Agent" stops the node
`recommendation_agent` and leaves the other nodes running. A refused call
raises out of `graph.invoke`, so one `@trace` around the chatbot is enough:

```python
@trace(operation="agent", name="StoreChatbot")
def chatbot(text):
    try:
        return graph.invoke({"messages": [text]})
    except ContainmentError as exc:
        return exc.fallback_message
```

"Slow it down" is not applied to graph nodes.

## Transport

Traces and the containment policy share **one WebSocket per process** to
Adeptiv, opened in the background. You give the SDK two things: the endpoint
and your project API key.

```python
from adeptiv_evaluator_sdk import init_telemetry

init_telemetry(
    api_key="<project api key>",
    endpoint="wss://<adeptiv host>/ws/sdk/",
)
```

or `ADEPTIV_API_KEY` and `ADEPTIV_ENDPOINT` in the environment. The key is
sent once, on the `Authorization` header when the connection opens.

Containment changes are pushed as they happen. While the connection is down
your app never waits on it: trace batches are held in memory (up to 32 MB,
gzipped) and sent when it is back, and the last containment policy stays in
force.

| Setting | Env var | Default |
|---|---|---|
| `endpoint` | `ADEPTIV_ENDPOINT` | none (required) |
| `api_key` | `ADEPTIV_API_KEY` | none (required) |
| `realtime_ack_timeout_seconds` | `ADEPTIV_REALTIME_ACK_TIMEOUT` | `10` (then the batch is held and sent again) |
| `realtime_connect_timeout_seconds` | `ADEPTIV_REALTIME_CONNECT_TIMEOUT` | `5` |
| `realtime_max_backoff_seconds` | `ADEPTIV_REALTIME_MAX_BACKOFF` | `60` (reconnect backoff cap) |
