Metadata-Version: 2.4
Name: aitracer-sdk
Version: 0.4.0
Summary: Official Python SDK for AITracer — tracing, verification, governance, cost intelligence, and integrations
Author: Hira Barton, Noir Stack
License: MIT
Project-URL: Homepage, https://aitracer.app
Project-URL: Documentation, https://aitracer.app/docs
Project-URL: Repository, https://github.com/no1rstack/aitracer
Keywords: aitracer,tracing,llm,observability,governance,openai,agents,otlp
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.31.0
Requires-Dist: urllib3>=2.0.0
Provides-Extra: async
Requires-Dist: httpx>=0.27.0; extra == "async"
Provides-Extra: dev
Requires-Dist: pytest>=7.4.0; extra == "dev"
Requires-Dist: types-requests>=2.31.0; extra == "dev"
Requires-Dist: httpx>=0.27.0; extra == "dev"

# AITracer Python SDK

This directory is the official **Python** package in the [**AITracer monorepo**](https://github.com/no1rstack/aitracer) (`python/aitracer-sdk/`). The **TypeScript** SDK lives at [`packages/sdk`](../../packages/sdk) (`npm install @noirstack/aitracer-sdk`); **starters** are under [`starters/`](../../starters/) and **examples** under [`examples/python-sdk/`](../../examples/python-sdk/).

Official Python entrypoint for **[AITracer](https://aitracer.app)** — tracing, verification, governance signals, cost intelligence, and first-party integrations (OpenAI Agents, OTLP/JSON, Guardrails).

Install from PyPI (package name **`aitracer-sdk`**, import as **`aitracer`**):

```bash
pip install aitracer-sdk
```

**Current version:** `0.3.0`

---

## Configure

Use an **workspace API key** (`akt_…`) and your app **base URL** (same origin as the AITracer web app).

```python
from aitracer import AITracerClient, configure

configure(api_key="akt_xxx", base_url="https://your-app.example.com")

# Or construct a client explicitly:
client = AITracerClient(api_key="akt_xxx", base_url="https://your-app.example.com")
```

The client uses **retries**, **timeouts**, and **`Authorization: Bearer`** on all requests.

---

## Basic tracing

Native ingest maps to **`POST /api/traces`**.

```python
from aitracer import trace, configure

configure(api_key="akt_xxx", base_url="https://your-app.example.com")

trace.record(
    workflow="customer-support-agent",
    model="gpt-4.1",
    input_data={"query": "Status?"},
    output_data={"answer": "Shipped."},
    metrics={"promptTokens": 50, "completionTokens": 20, "latencyMs": 400},
)
```

---

## Async tracing

For **FastAPI**, **async agents**, and event loops, install **`httpx`**:

```bash
pip install 'aitracer-sdk[async]'
```

```python
import asyncio
from aitracer import AsyncAITracerClient, configure_async, trace

async def main():
    configure_async(api_key="akt_xxx", base_url="https://your-app.example.com")
    await trace.arecord(
        workflow="async-job",
        model="gpt-4.1",
        input_data={"q": "hello"},
        output_data={"a": "world"},
    )

asyncio.run(main())
```

`AsyncAITracerClient` uses **async retries** with exponential backoff on timeouts, connection errors, and **429 / 502 / 503 / 504**.

---

## Batch ingestion

**Sync** (thread pool, preserves order):

```python
from aitracer import trace, configure

configure(api_key="akt_xxx", base_url="https://your-app.example.com")

trace.batch_record(
    [
        {"workflow": "bulk-1", "model": "gpt-4o-mini", "input_data": {"i": 1}},
        {"workflow": "bulk-2", "model": "gpt-4o-mini", "input_data": {"i": 2}},
    ],
    max_workers=8,
)
```

**Async** (bounded concurrency):

```python
await trace.batch_arecord(
    [{"workflow": "a", "model": "gpt-4o"}, {"workflow": "b", "model": "gpt-4o"}],
    concurrency=8,
)
```

---

## CLI

After install, the **`aitracer`** command is available:

```bash
aitracer init                    # print starter AITRACER_* env vars
export AITRACER_API_KEY=akt_...
export AITRACER_BASE_URL=https://your-app.example.com
aitracer test-ingest             # POST a minimal trace
aitracer verify <trace_id>       # best-effort lookup (depends on auth mode)
```

---

## HTTP errors & observability

`AITracerHTTPError` includes **`request_id`**, **`correlation_id`**, **`url`**, **`attempts_made`**, and a **`response_body`** excerpt. Use **`exc.diagnostics()`** for structured logging.

---

## Verification

Many deployments embed **verification records** on the **trace ingest response** (there is often no standalone public verification URL).

```python
from aitracer import verify

records = verify.records_from_response(ingest_response)
digest = verify.hash("your-trace-id")
```

---

## Governance (Guardrails / policy)

Normalized guardrail and policy outcomes → **`POST /api/integrations/openai-guardrails`**.

```python
from aitracer import governance, configure

configure(api_key="akt_xxx", base_url="https://your-app.example.com")

governance.report_policy_event(
    guardrail_name="pii",
    trigger_type="pii_detected",
    trigger_source="user_input",
    action_taken="blocked",
    trace_id="optional-public-trace-slug",
)
```

---

## Cost intelligence

There is often **no standalone cost HTTP API**; token and spend fields are carried on **trace / execution** payloads. Helpers aggregate what you already ingested or listed:

```python
from aitracer import cost

summary = cost.from_ingest_response(ingest_response)
rollup = cost.aggregate(list_of_trace_dicts)
spend_by_model = cost.get_model_spend(list_of_trace_dicts)
```

---

## OpenAI Agents integration

**`POST /api/integrations/openai-agents`**

```python
from aitracer.integrations.openai_agents import register_tracing, export_spans

cfg = register_tracing(
    base_url="https://your-app.example.com",
    api_key="akt_xxx",
)
export_spans({"traceId": "...", "spans": [...]}, config=cfg)
```

---

## OTLP integration

**`POST /api/integrations/otlp/v1/traces`** (JSON encoding).

```python
from aitracer.integrations.otlp import export_resource_spans, collector_exporter_yaml_snippet
from aitracer import AITracerClient

client = AITracerClient(api_key="akt_xxx", base_url="https://your-app.example.com")
export_resource_spans({"resourceSpans": [...]}, client=client)

print(collector_exporter_yaml_snippet(base_url="https://your-app.example.com", api_key="akt_xxx"))
```

---

## Documentation

- Product docs: [https://aitracer.app/docs](https://aitracer.app/docs)
- Developer reference (OpenAPI): [https://aitracer.app/developers](https://aitracer.app/developers) (or `/developers` on your deployment)

---

## Examples

Runnable samples live in [`examples/`](./examples/) (set `AITRACER_API_KEY` and optional `AITRACER_BASE_URL`).

---

## Local smoke install

```bash
./scripts/smoke-install-test.sh local
```

---

## Roadmap (toward “production hardening”)

Shipped in **0.3.0**: async client, batch ingest, richer HTTP errors, CLI stubs, `trace.astream` / `webhooks` placeholders, `contrib/` for framework adapters.

Still the main leverage points for **enterprise** adoption:

| Area | Status |
|------|--------|
| **Async** (`AsyncAITracerClient`, `trace.arecord`, `batch_arecord`) | Implemented (`[async]` extra) |
| **Batch** (`trace.batch_record`) | Implemented |
| **Streaming** (`trace.astream`) | Not implemented — needs platform ingest contract |
| **Framework wrappers** (LangChain, LlamaIndex, CrewAI, FastAPI middleware, …) | `contrib/` placeholder only |
| **CLI** | `init`, `test-ingest`, `verify` |
| **Error observability** | Request/correlation IDs, URL, attempts, `diagnostics()` |
| **Pydantic models** | Optional future extra (validation / IDE ergonomics) |
| **Webhooks** | `handle_verification_webhook` placeholder |
| **MCP / enterprise policy** | Future layers on top of stable `client` / `trace` APIs |

---

## License

MIT — see repository for details.
