Metadata-Version: 2.4
Name: humanhours
Version: 0.0.1
Summary: humanhours SDK: one HTTP call per AI agent task, automatic proof of hours and euros saved.
Project-URL: Homepage, https://humanhours.dev
Project-URL: Repository, https://github.com/triadgit/agent-metrics
License: MIT
Keywords: agents,ai,humanhours,roi,telemetry,tracking
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
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.9
Requires-Dist: httpx>=0.27.0
Description-Content-Type: text/markdown

# humanhours (Python)

The ROI meter for your AI agents. One HTTP call per task, automatic proof of hours and euros saved.

```sh
pip install humanhours
```

## 60-second quickstart

```python
from humanhours import Humanhours

hh = Humanhours(api_key="hh_live_...")

hh.track(
    agent_id="support-classifier",
    task_type="email_classification",
    outcome="success",
)
```

That's it. The dashboard at humanhours.dev shows the saved hours and euros.

## Decorator

```python
from humanhours import Humanhours, track

hh = Humanhours(api_key="...", default_agent_id="support-classifier")

@track(hh, task_type="email_classification")
def classify(subject: str) -> str:
    ...
```

The decorator times the function, captures the outcome (`success` on return, `failure` on raise), and reports automatically. Failures re-raise — your code keeps its normal control flow.

## Ambient client (context manager)

```python
with Humanhours(api_key="...") as hh:
    @track(task_type="contract_clause_review", agent_id="legal-clause-reviewer")
    def review_clause(text):
        ...
    review_clause("...")
```

`@track` without `client=` picks up the active `with` scope. Useful when you can't pass the client through a deep call tree.

## Read your numbers

```python
hh.summary(period="30d")
hh.agents()
hh.report("/time-saved", {"period": "30d", "group_by": "agent"})
```

## Errors

```python
from humanhours import Humanhours, HumanhoursError

try:
    hh.track(task_type="...", agent_id="...", outcome="success")
except HumanhoursError as e:
    if e.code == "unknown_task_type":
        ...
    raise
```

## Configuration

| Argument | Default | Notes |
|---|---|---|
| `api_key` | (required) | `hh_live_...` from the dashboard |
| `base_url` | `https://humanhours.dev` | Override for self-hosted or local dev |
| `default_agent_id` | `None` | Skip the field on every `track()` |
| `timeout` | `10.0` | Per-call seconds |
| `client` | `None` | Inject your own `httpx.Client` |

The decorator also reads `HUMANHOURS_API_KEY` / `HUMANHOURS_BASE_URL` from the environment as a fallback.

## License

MIT.
