Metadata-Version: 2.4
Name: agent-carbon
Version: 0.1.1
Summary: Carbon emissions tracking for LLM agent frameworks
Author: agent-carbon contributors
License: MIT
License-File: LICENSE
Keywords: ai,carbon,emissions,green-ai,langchain,llm,sustainability
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: langchain-core>=0.3.0
Requires-Dist: pydantic>=2.0
Provides-Extra: all
Requires-Dist: autogen-agentchat>=0.4.0; extra == 'all'
Requires-Dist: crewai>=0.70.0; extra == 'all'
Requires-Dist: langgraph>=0.2.0; extra == 'all'
Provides-Extra: autogen
Requires-Dist: autogen-agentchat>=0.4.0; extra == 'autogen'
Provides-Extra: crewai
Requires-Dist: crewai>=0.70.0; extra == 'crewai'
Provides-Extra: dev
Requires-Dist: langchain-openai>=0.2.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Provides-Extra: langgraph
Requires-Dist: langgraph>=0.2.0; extra == 'langgraph'
Description-Content-Type: text/markdown

# agent-carbon

**Carbon emissions tracking for LLM agent frameworks.**

Tokens ✓ · Cost ✓ · **CO₂e** — until now, missing.

`agent-carbon` is a drop-in callback that plugs into LangChain, LangGraph, CrewAI, and AutoGen the same way token/cost callbacks do — no code changes to your agent, no network calls, no telemetry.

---

## Install

```bash
pip install agent-carbon
```

With optional framework integrations:

```bash
pip install "agent-carbon[langgraph]"
pip install "agent-carbon[crewai]"
pip install "agent-carbon[autogen]"
```

---

## 3-line usage

```python
from agent_carbon import CarbonCallbackHandler

handler = CarbonCallbackHandler(region="us-east-1")
chain.invoke({"input": "..."}, config={"callbacks": [handler]})
print(handler.receipt)
```

---

## Sample receipt

```
CarbonReceipt(total_tokens=4823, total_gco2e=0.1802, total_wh=0.3650,
              savings_vs_frontier_gco2e=1.0241, calls=3)
```

```markdown
## Carbon Receipt

| Metric                          | Value                                 |
|---------------------------------|---------------------------------------|
| Total tokens                    | 4,823 (3,201 in / 1,622 out)          |
| Total energy                    | 0.3650 Wh                             |
| Total CO₂e                      | 0.1802 gCO₂e                          |
| Savings vs `claude-opus-4-6`    | 1.0241 gCO₂e                          |
| Region                          | us-east-1                             |
| LLM calls                       | 3                                     |
| Estimate                        | True                                  |
| Duration                        | 4.21s                                 |

> *Emissions estimated from token counts × model-specific energy factors
> (Wh/1M tokens) × regional grid intensity (gCO₂e/kWh).
> All values are approximate; see factors_meta.json for sources and caveats.*

### Per-call Breakdown

| # | Model               | In tok | Out tok | gCO₂e  | Wh     |
|---|---------------------|--------|---------|--------|--------|
| 1 | `claude-sonnet-4-6` | 1,234  |   512   | 0.0724 | 0.1465 |
| 2 | `claude-sonnet-4-6` | 1,489  |   601   | 0.0843 | 0.1707 |
| 3 | `claude-sonnet-4-6` |   478  |   509   | 0.0235 | 0.0476 |
```

---

## API reference

### `CarbonCallbackHandler`

```python
handler = CarbonCallbackHandler(
    region="us-east-1",           # optional — cloud region for grid intensity
    frontier_model="claude-opus-4-6",  # optional — savings comparison baseline
)
```

Pass it as a LangChain callback and read `.receipt` after the run:

```python
result = chain.invoke(input, config={"callbacks": [handler]})
receipt = handler.receipt          # CarbonReceipt
receipt.to_markdown()              # human-readable string
receipt.to_dict()                  # JSON-serializable dict
handler.reset()                    # clear for next run (keeps region/config)
```

### `@track_carbon` decorator

For plain functions that use LangChain under the hood:

```python
from agent_carbon import track_carbon

@track_carbon(region="us-west-2")
def run_my_chain(query, config=None):
    return chain.invoke({"input": query}, config=config)

result, receipt = run_my_chain("What is solar energy?")
```

### LangGraph helper

```python
from agent_carbon.integrations.langgraph import invoke_with_carbon

result, receipt = invoke_with_carbon(graph, state, region="us-west-2")
```

### CrewAI helper

```python
from agent_carbon.integrations.crewai import kickoff_with_carbon

result, receipt = kickoff_with_carbon(crew, region="eu-west-1")
```

### AutoGen wrapper

```python
from agent_carbon.integrations.autogen import CarbonModelClient

client = CarbonModelClient(base_openai_client, region="us-east-1")
# pass client to AssistantAgent(model_client=client)
print(client.receipt)
```

---

## Supported models

| Model | Provider |
|-------|----------|
| `gpt-5`, `gpt-5-mini`, `gpt-5-nano` | OpenAI |
| `claude-opus-4-6`, `claude-sonnet-4-6`, `claude-haiku-4-5` | Anthropic |
| `gemini-2.5-pro`, `gemini-2.5-flash` | Google |
| `llama-3.3-70b`, `llama-3.3-8b` | Meta |
| `mistral-large`, `mistral-small` | Mistral |

Unknown models emit `gco2e=0` and `wh=0` with `estimated=True` rather than raising. Add entries to `factors_meta.json` and call `agent_carbon.factors.FACTORS.update(...)` to extend the table at runtime.

---

## Region awareness

Pass any major AWS, GCP, or Azure region slug to get grid-adjusted CO₂e:

```python
# Oregon's clean grid (~135 gCO₂/kWh) vs. global avg (~494 gCO₂/kWh)
handler = CarbonCallbackHandler(region="us-west-2")
```

Omit `region` to use the IEA 2022 global average (494 gCO₂e/kWh). See `src/agent_carbon/regions.py` for the full table.

---

## Methodology & honesty

Every receipt includes:

- `estimate: true` — always. No precise published inference energy data exists for any major commercial LLM as of 2026.
- `methodology` — a one-line disclaimer describing the calculation.
- Per-entry `source` comments in `factors.py` and `factors_meta.json` citing the basis for each estimate.

Energy factors are derived from GPU hardware benchmarks for commercial-scale inference (high-batch-size, tensor-parallel, H100/A100 deployments). Estimates should be treated as order-of-magnitude guidance, not accounting figures.

---

## Contributing

Contributions to improve factor accuracy — especially from published energy audits or provider sustainability reports — are very welcome. Update both `src/agent_carbon/factors.py` and `factors_meta.json`, cite the source, and open a PR.

---

## License

MIT
