Skip to main content

Audit-grade agent observability for Python — capture, redact, sign, and ship every model call, tool invocation, and decision an AI agent makes.

Project description

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

pip install herald-py

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

Optional extras for framework-specific auto-instrumentation:

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

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

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.

Copyright 2026 MMPWorks LLC.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

herald_py-0.1.1.tar.gz (16.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

herald_py-0.1.1-py3-none-any.whl (14.9 kB view details)

Uploaded Python 3

File details

Details for the file herald_py-0.1.1.tar.gz.

File metadata

  • Download URL: herald_py-0.1.1.tar.gz
  • Upload date:
  • Size: 16.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for herald_py-0.1.1.tar.gz
Algorithm Hash digest
SHA256 8b55237e08feec0a25f4f0d63f7757a9756fb5a4c5d758b25ec414a00e41fdf2
MD5 135e63ae2f3fb45885153f8bc55b9577
BLAKE2b-256 ea1aaedff0444ac07cf00f841ad6009e8af5ffcc4bbb43fda4995f47b8822258

See more details on using hashes here.

Provenance

The following attestation bundles were made for herald_py-0.1.1.tar.gz:

Publisher: release.yml on smuchow1962/Herald.Py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file herald_py-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: herald_py-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 14.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for herald_py-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f6c148899634b59fbc5e848a4958b8a499db2f79ad387a17b6ecc0ff3b1d60e3
MD5 d1f87225f73a48751228f7d98ae66887
BLAKE2b-256 ef8884210a4ec76234e165eefd8faefaa8d67fda3366436a94faca4d1ac47bfb

See more details on using hashes here.

Provenance

The following attestation bundles were made for herald_py-0.1.1-py3-none-any.whl:

Publisher: release.yml on smuchow1962/Herald.Py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page