Metadata-Version: 2.4
Name: actaclad-agentguard
Version: 1.1.0
Summary: Agent Guard observability SDK for Python
Author: Agent Guard
Project-URL: Homepage, https://agentgaurd-a0acc6egbhced0dc.centralindia-01.azurewebsites.net
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: opentelemetry-sdk>=1.20.0
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.20.0
Requires-Dist: traceloop-sdk>=0.33.0; python_version >= "3.10"
Provides-Extra: auto
Requires-Dist: traceloop-sdk>=0.33.0; python_version >= "3.10" and extra == "auto"
Provides-Extra: legacy
Requires-Dist: langfuse>=2.0.0; extra == "legacy"
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.2.0; extra == "langchain"
Requires-Dist: langchain-openai>=0.1.0; extra == "langchain"
Requires-Dist: langfuse>=2.0.0; extra == "langchain"

# AgentGuard SDK for Python

Install the package:

```bash
pip install agentguard
```

The distribution is named `agentguard` and exposes the onboarding API as
`import agentguard`.

### Python version

- **Python 3.10+** — full auto-instrumentation. `pip install agentguard` pulls
  `traceloop-sdk`, so OpenAI / Anthropic / Gemini calls are traced with no
  per-call code.
- **Python 3.8 / 3.9** — installs and runs in **manual mode**. `traceloop-sdk`
  requires 3.10, so it is skipped automatically (PEP 508 marker) and the SDK
  falls back to manual export. Auto-instrumentation of providers is **not**
  available; use `track()` and `record_generation()`. Gemini **sync** is still
  traced by the SDK on 3.9; Gemini **batch** always uses `record_generation()`
  (see below). To force the extra explicitly on 3.10+:
  `pip install "agentguard[auto]"`.

You normally leave `AGENTGUARD_MODE=auto` (the default) — the SDK downgrades to
manual only when traceloop is unavailable. `context()` / `track()` are optional
enrichment on top of either mode, not a switch into manual mode.

## Environment

```bash
AGENTGUARD_HOST=https://agentgaurd-a0acc6egbhced0dc.centralindia-01.azurewebsites.net
AGENTGUARD_PUBLIC_KEY=pk-lf-...
AGENTGUARD_SECRET_KEY=sk-lf-...
APP_ENV=production
AGENTGUARD_MODE=auto
```

Optional:

```bash
# Drop infrastructure spans (DB, HTTP client, framework) at the exporter and
# keep only LLM/observation spans — reduces storage/egress. Default: false
# (full end-to-end agent traces are preserved).
AGENTGUARD_DROP_INFRA_SPANS=true
```

Compatibility env vars are also accepted:

```bash
AGENTGUARD_BASE_URL=https://agentgaurd-a0acc6egbhced0dc.centralindia-01.azurewebsites.net
AGENT_GUARD_BASE_URL=https://agentgaurd-a0acc6egbhced0dc.centralindia-01.azurewebsites.net
AGENT_GUARD_PUBLIC_KEY=pk-lf-...
AGENT_GUARD_SECRET_KEY=sk-lf-...
```

Use API keys from an existing AgentGuard project. The Python SDK does not create
console organizations or projects; create or select the project in the console,
then copy its public and secret keys into the environment.

## Layer 1 — Base Observability

Initialize once at startup before creating LLM clients:

```python
import agentguard

agentguard.init(service_name="my-service")
```

Then make LLM calls exactly as before:

```python
from openai import OpenAI

resp = OpenAI().chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello"}],
)
```

Optional Cohere/Mistral instrumentor warnings during startup are ignored by the
SDK. They do not block OpenAI or Gemini tracing when those clients are installed
and initialized after `agentguard.init()`.

## Layer 2 — Tenant Context

Set business/channel once per request:

```python
with agentguard.context(
    business_id="caratlane",
    channel="instagram_dm",
    session_id=conversation_id,
):
    handle_message(message)
```

## Layer 3 — Feature Attribution

Wrap each feature-level LLM call:

```python
def handle_message(message):
    with agentguard.track("sentiment"):
        sentiment = run_sentiment(message)

    with agentguard.track("reply"):
        reply = run_reply(message)
```

`track()` emits groupable tags and filterable metadata:

- `business:*`
- `channel:*`
- `feature:*`
- `biz_channel:*`
- `biz_feat:*`
- `chan_feat:*`
- `biz_chan_feat:*`

## Gemini — sync vs batch

**Sync** calls (`client.models.generate_content(...)`) auto-trace on Python 3.9+.
**Batch** calls (`client.batches.create(...)`) are asynchronous — there are no
tokens at submit time, so auto-instrumentation cannot capture them. Record the
cost with `record_generation()` when you fetch the results:

```python
for line in batch_results:                  # each line carries usage_metadata
    um = line.response.usage_metadata
    agentguard.record_generation(
        feature="transcription",
        model="gemini-2.5-flash",           # must be in the pricing table or cost shows 0
        input_tokens=um.prompt_token_count,
        output_tokens=um.candidates_token_count,
    )  # business/channel/session inherit the surrounding context()
```

`record_generation()` also covers any call auto-instrumentation can't reach —
custom/REST providers or an SDK without an instrumentor. Cost is computed
server-side from the model name; standard models work out of the box, new or
custom model names are added once in the AgentGuard console.

## Manual Smoke Test

Use `manual` mode to test export without real LLM calls:

```bash
AGENTGUARD_MODE=manual python examples/smoke_test_agentguard.py \
  --business-id caratlane \
  --channel instagram_dm \
  --flow-id checkout-flow \
  --feature-id sentiment
```

PowerShell:

```powershell
$env:AGENTGUARD_MODE="manual"
python examples/smoke_test_agentguard.py `
  --business-id caratlane `
  --channel instagram_dm `
  --flow-id checkout-flow `
  --feature-id sentiment
```

## Legacy API Compatibility

The older `agentguard_sdk` module is still included:

```python
from agentguard_sdk import AgentGuard
```

New onboarding docs should use:

```python
import agentguard
```
