Metadata-Version: 2.4
Name: useagentledger
Version: 0.1.0
Summary: AgentLedger Python SDK — track, attribute, and govern AI agent spend across OpenAI, Anthropic, and Gemini.
License: MIT
Project-URL: Homepage, https://useagentledger.com
Project-URL: Documentation, https://useagentledger.com/blog
Keywords: llm,cost-tracking,ai-agents,openai,anthropic,gemini,observability
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# AgentLedger Python SDK

Track, attribute, and govern AI agent spend across OpenAI, Anthropic, and Gemini — with per-agent / per-task / per-user / per-customer cost attribution, kill switches, loop detection, and ROI reporting.

Zero dependencies. Python 3.9+.

```bash
pip install useagentledger
```

(The import name is `agentledger`: `from agentledger import AgentLedger`.)

## Quick start

```python
from agentledger import AgentLedger

al = AgentLedger(api_key="al_live_...")  # provider keys read from env by default

response = al.run(
    agent="invoice-processor",
    task="extraction",
    customer="acme-corp",
    llm={
        "provider": "anthropic",
        "model": "claude-sonnet-4-6",
        "max_tokens": 1024,
        "messages": [{"role": "user", "content": "Extract line items from this invoice: ..."}],
    },
)
print(response["content"][0]["text"])
```

Every call is tracked automatically — token counts, latency, and attribution dimensions. Cost is computed server-side from AgentLedger's pricing table (134+ models), so the SDK never goes stale.

## Kill switch

`run()` checks AgentLedger's block list before every call (cached 5 seconds). If an alert rule has blocked this agent, task, user, or customer, the call raises **before** any provider spend happens:

```python
from agentledger import AgentLedger, AgentLedgerBlockError

try:
    al.run(agent="support-bot", customer="acme-corp", llm={...})
except AgentLedgerBlockError as e:
    print(f"Blocked: {e} (dimension={e.dimension}, value={e.dimension_value})")
```

The check **fails open** — if AgentLedger is unreachable, your LLM call proceeds normally. Governance never becomes a point of failure.

## Streaming

Pass `stream=True` and iterate the returned generator. Usage is captured from the stream's own events and tracked when the stream ends (even if you stop early):

```python
stream = al.run(
    agent="chat-assistant",
    user="user-42",
    llm={
        "provider": "openai",
        "model": "gpt-4o",
        "stream": True,
        "messages": [{"role": "user", "content": "Hello!"}],
    },
)
for event in stream:
    delta = event.get("choices", [{}])[0].get("delta", {}).get("content")
    if delta:
        print(delta, end="", flush=True)
```

Works for all three providers (Anthropic `message_start`/`message_delta` events, OpenAI usage chunk, Gemini `usageMetadata`).

## Sessions (multi-step agents)

Group a multi-step task into one session so loop detection and per-session cost work across steps:

```python
session_id = al.start_session(agent="research-bot", task="report")
for step in plan:
    al.run(agent="research-bot", session_id=session_id, llm={...})
al.end_session(session_id, success=True)
```

Calls without an explicit session are auto-grouped server-side (same agent + task within a 10-minute window).

## Track calls you make yourself

Already using the official `openai` / `anthropic` clients? Just report usage:

```python
result = openai_client.chat.completions.create(model="gpt-4o-mini", messages=msgs)

al.track(
    agent="summarizer",
    customer="acme-corp",
    provider="openai",
    model="gpt-4o-mini",
    input_tokens=result.usage.prompt_tokens,
    output_tokens=result.usage.completion_tokens,
)
```

`track()` runs on a background thread by default (zero added latency) and swallows all errors. Pass `background=False` to send synchronously.

## ROI units

Record completed business outcomes for cost-per-outcome reporting (`custom_event` count method):

```python
al.record_unit(agent="invoice-processor", unit_count=1)
```

## Configuration

```python
al = AgentLedger(
    api_key="al_live_...",
    base_url="https://api.useagentledger.com",   # or your self-hosted proxy
    provider_keys={                               # optional — env vars used otherwise
        "anthropic": "...",   # ANTHROPIC_API_KEY
        "openai": "...",      # OPENAI_API_KEY
        "gemini": "...",      # GOOGLE_API_KEY
    },
)
```
