# a2a-llm-tracker

**a2a-llm-tracker** is a Python package that helps AI agents and applications **track LLM usage and cost from a single place**, across providers like OpenAI, Gemini, Anthropic, and others.

It is designed for **agent-to-agent (A2A)** systems where:
- multiple agents make LLM calls
- multiple providers are used
- usage and cost need to be tracked centrally
- streaming, async, and sync calls must all be supported

The package is **LiteLLM-first**, giving you multi-provider support with minimal integration effort.

---

## Why a2a-llm-tracker?

LLM providers differ in:
- SDKs and APIs
- tokenization
- pricing models
- usage reporting (especially for streaming)

`a2a-llm-tracker` solves this by:
- wrapping LLM calls instead of guessing usage
- normalizing provider-reported usage into a single schema
- computing cost using configurable pricing
- attaching agent / user / session context
- writing usage events to pluggable storage backends

> **Exact cost is recorded only when providers report usage.**  
> This package does not fabricate billing data.

---

## Features

- ✅ Multi-provider support via LiteLLM
- ✅ Sync, async, and streaming calls
- ✅ Exact token usage when available
- ✅ Cost calculation with user-defined pricing
- ✅ Context propagation for agents and sessions
- ✅ JSONL and SQLite sinks
- ✅ No heavy work on import
- ✅ No vendor lock-in

---

## Installation

```bash
pip install a2a-llm-tracker[litellm]
```



## Quickstart

### 1️⃣ Set your API key
Example for OpenAI:

```bash
export OPENAI_API_KEY=sk-xxxxxxxx

```


## Import 

```
from a2a_llm_tracker import Meter, PricingRegistry, meter_context

```

## Create a tracker

```
from a2a_llm_tracker import Meter, PricingRegistry
from a2a_llm_tracker.sinks.jsonl import JSONLSink

pricing = PricingRegistry()
pricing.set_price(
    provider="openai",
    model="openai/gpt-4.1",
    input_per_million=2.0,
    output_per_million=8.0,
)

meter = Meter(
    pricing=pricing,
    sinks=[JSONLSink("usage.jsonl")],
    project="my-a2a-system",
)


```

## Wrap Litellm

```
from a2a_llm_tracker.integrations.litellm import LiteLLM

llm = LiteLLM(meter=meter)

```

### Use The package Sync

```
response = llm.completion(
    model="openai/gpt-4.1",
    messages=[
        {"role": "user", "content": "Say hello in one sentence."}
    ],
)

print(response)

```


### Use package for  Sync  streaming

```
for chunk in llm.completion(
    model="openai/gpt-4.1",
    messages=[{"role": "user", "content": "Write a short poem."}],
    stream=True,
):
    print(chunk, end="", flush=True)


```
Streaming output is yielded as usual

Usage is recorded after the stream finishes

If the provider does not return usage for streams, accuracy is marked as unknown




### Async Non Stereaming

```
response = await llm.acompletion(
    model="openai/gpt-4.1",
    messages=[{"role": "user", "content": "Async hello!"}],
)

```


### Async Steraming


```
stream = await llm.acompletion(
    model="openai/gpt-4.1",
    messages=[{"role": "user", "content": "Stream async output"}],
    stream=True,
)

async for chunk in stream:
    print(chunk, end="", flush=True)

```


### Agent and Session Context

```
from a2a_llm_tracker import meter_context

with meter_context(
    agent_id="planner-agent",
    session_id="session-123",
    user_id="user-456",
):
    llm.completion(
        model="openai/gpt-4.1",
        messages=[{"role": "user", "content": "Plan my day"}],
    )

```


### Pricing is fully user controlled

```
Pricing Model

Pricing is fully user-controlled.

pricing.set_price(
    provider="openai",
    model="openai/gpt-4.1",
    input_per_million=2.0,
    output_per_million=8.0,
)




```

This supports:

enterprise pricing

price changes over time

multiple vendors with different rates



## This package does not

What This Package Does NOT Do

❌ Guess exact billing from raw text

❌ Replace provider SDKs

❌ Upload data anywhere automatically

❌ Require a backend or SaaS



## Building this project

use the venv  to build the environment

```
python -m venv .venv

pip install -e .

```
### To build the project
```
python -m build 

```

### To publish the project 

```
python -m twine upload dist/*

```