Metadata-Version: 2.4
Name: herald-py
Version: 0.6.0
Summary: Audit-grade agent observability for Python — capture, redact, sign, and ship every model call, tool invocation, and decision an AI agent makes.
Project-URL: Homepage, https://mmpworks.com/
Project-URL: Documentation, https://github.com/smuchow1962/Herald.Py#readme
Project-URL: Source, https://github.com/smuchow1962/Herald.Py
Project-URL: Issues, https://github.com/smuchow1962/Herald.Py/issues
Project-URL: Changelog, https://github.com/smuchow1962/Herald.Py/blob/main/CHANGELOG.md
Author-email: MMPWorks LLC <steve@mythmerchant.com>
License: Apache-2.0
License-File: LICENSE.md
Keywords: agent observability,ai governance,audit trail,llm observability,opentelemetry,otlp,tracing
Classifier: Development Status :: 1 - Planning
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Logging
Classifier: Topic :: System :: Monitoring
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: cryptography>=42.0
Requires-Dist: orjson>=3.10
Requires-Dist: pydantic-settings>=2.4
Requires-Dist: pydantic>=2.7
Requires-Dist: python-ulid>=2.7
Requires-Dist: tomli>=2.0; python_version < '3.11'
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.40; extra == 'anthropic'
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: hypothesis>=6.100; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-benchmark>=4.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Requires-Dist: twine>=5.1; extra == 'dev'
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.115; extra == 'fastapi'
Provides-Extra: langchain
Requires-Dist: langchain>=0.3; extra == 'langchain'
Provides-Extra: openai
Requires-Dist: openai>=1.50; extra == 'openai'
Provides-Extra: otlp
Requires-Dist: opentelemetry-api>=1.27; extra == 'otlp'
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.27; extra == 'otlp'
Requires-Dist: opentelemetry-sdk>=1.27; extra == 'otlp'
Description-Content-Type: text/markdown

# Herald

**Audit-grade agent observability for Python.**

> **Status:** v0.0.1 — design lock. The public API surface is defined; capture wiring lands in phase 1. Imports work, decorators are pass-through stubs, tests pass.

When an AI agent makes a wrong decision in production — denies the wrong refund, gives the wrong medical recommendation, executes the wrong trade — most teams cannot reconstruct what the agent saw, what it asked the model, what the model returned, or why it decided what it did. Herald is the recorder that captures all of it.

One line of Python installs it. From that point forward every model call, every tool invocation, every retry, every decision lands in a structured, queryable, replayable record. The recording is local-first (survives process crash), audit-grade (tamper-evident hash chain on the events that matter), and ships to a Herald backend for long-term storage and query.

Built on a high-performance .NET capture engine that already powers latency-sensitive workloads in trading, healthcare, and game development. The Python SDK is the front door for the language the agents are actually written in.

---

## Install

```bash
pip install herald-py
```

The PyPI distribution is `herald-py`; the import name is `herald` (`import herald`).

Optional extras for framework-specific auto-instrumentation:

```bash
pip install "herald-py[openai]"
pip install "herald-py[anthropic]"
pip install "herald-py[langchain]"
pip install "herald-py[fastapi]"
pip install "herald-py[otlp]"
```

---

## Quickstart

```python
import os
import herald
from anthropic import AsyncAnthropic

herald.configure(
    backend=os.environ["HERALD_BACKEND"],
    api_key=os.environ["HERALD_API_KEY"],
    service="refund-agent",
    environment="production",
    redact={"card_number": "last4", "email": "domain_only"},
)
herald.auto_instrument()

client = AsyncAnthropic()


@herald.tool(name="lookup_order")
async def lookup_order(order_id: str) -> dict:
    return await orders_service.fetch(order_id)


@herald.agent(name="refund-agent", version="3.1.0")
async def decide_refund(order_id: str) -> dict:
    order = await lookup_order(order_id)

    response = await client.messages.create(
        model="claude-opus-4-7",
        max_tokens=512,
        messages=[{"role": "user", "content": f"Decide refund for {order}"}],
    )

    decision = parse(response.content[0].text)

    herald.audit(
        event="refund_decision",
        decision=decision["outcome"],
        order_id=order_id,
        rationale=decision["rationale"],
    )

    return decision
```

What gets captured for one invocation of `decide_refund`:

- The agent run boundary (one `run_id` for everything below).
- Each `@herald.tool` call as a child span with input and output.
- The `anthropic.messages.create` call with prompt, response, token counts, and dollar cost.
- The `herald.audit(...)` event in the tamper-evident audit ledger.
- All HTTP, database, and retrieval calls inside the run via auto-instrumentation.

---

## What this is

Three nouns, three decorators:

| Decorator | Meaning |
|-----------|---------|
| `@herald.agent` | Top-level boundary of an agent run. Everything inside shares one `run_id`. |
| `@herald.tool` | Anything the agent can invoke (your code, an external API, a database query). |
| `@herald.llm_call` | Manual model invocation outside the auto-instrumented SDKs. |

Plus:

- `herald.configure(...)` — one-time setup at process start.
- `herald.auto_instrument()` — patches every supported library detected in the venv.
- `herald.span(...)` — context manager for arbitrary capture boundaries.
- `herald.record(...)` — emit an arbitrary structured event.
- `herald.audit(...)` — emit an audit-channel event with synchronous durability and chain-of-custody.

---

## Features

- **Async-native.** Built for `asyncio` from the ground up.
- **Fully typed.** PEP 561 marker shipped; `mypy --strict` clean.
- **OpenTelemetry-compatible.** Default wire format is OTLP/gRPC with the GenAI semantic conventions, so any OTel-aware backend can ingest Herald output without modification.
- **Auto-instrumentation.** One line patches OpenAI, Anthropic, LangChain, LangGraph, LlamaIndex, FastAPI, httpx, SQLAlchemy, and a long tail of agent-stack libraries.
- **Audit channel.** `herald.audit(...)` events bypass sampling, write synchronously to local disk, and carry a tamper-evident SHA-256 chain.
- **Local durability.** SQLite-backed ring buffer that survives process crashes; events drain to the backend asynchronously.
- **Replay.** Pull a captured run and re-execute the LLM portions against a different model or prompt to test fixes safely.
- **OSS escape hatch.** Apache-2 licensed; works against any OTLP backend, not just Herald.

---

## Status and roadmap

| Phase | Scope | State |
|-------|-------|-------|
| 0 — Design lock | Public API surface frozen, stub package on PyPI. | **In progress.** |
| 1 — Minimum viable SDK | `configure()`, `auto_instrument()` for OpenAI + Anthropic, three decorators, `audit()`, SQLite durability, OTLP export. | Planned. |
| 2 — First vertical integrations | LangChain, LangGraph, LlamaIndex, FastAPI middleware. Cost table. | Planned. |
| 3 — Server-side ingest | OTLP receiver in Herald.Server, audit ledger sink, run index, query API. | Planned. |
| 4 — Replay API | `Replayer.fetch_run()`, `Replayer.replay()`, diff computation. | Planned. |
| 5 — Managed cloud GA | Multi-tenant deployment, billing, dashboard. | Planned. |

The current release is **scaffolding only** — decorators are pass-through, no events leave the process. Public surface is the contract; behavior arrives in phase 1.

---

## Development

```bash
git clone https://github.com/smuchow1962/Herald.Py.git
cd Herald.Py
python -m venv .venv
.venv/Scripts/pip install -e ".[dev]"

.venv/Scripts/pytest -q
.venv/Scripts/ruff check .
.venv/Scripts/mypy
```

Targeting Python 3.10+. Built with hatchling. Ruff for lint and import sort, mypy in `--strict` mode for type checking, pytest with `pytest-asyncio` for tests.

---

## License

Apache-2.0. See [LICENSE.md](LICENSE.md).

Copyright 2026 MMPWorks LLC.
