Skip to main content

agentaudit — Python SDK

Tamper-evident audit logging for AI agents, built for EU AI Act Article 12 record-keeping. Three lines of code get events flowing to your AgentAudit backend; a hash chain over every event makes tampering detectable after the fact.

pip install agentaudit-python   # PyPI distribution name; import is still `agentaudit`
import agentaudit

agentaudit.init(api_key="aa_live_sk_...", agent_id="my-support-agent")
agentaudit.log_event(event_type="decision", action="route_to_human")

Get your API key

From your AgentAudit dashboard: sign up, create a project, then go to Settings → API Keys → Create key. The raw key (starts with aa_live_sk_) is shown exactly once — copy it immediately. It is never recoverable after that; losing it means revoking it and creating a new one.

Store it as an environment variable, not in source:

import os
import agentaudit

agentaudit.init(api_key=os.environ["AGENTAUDIT_API_KEY"], agent_id="my-support-agent")

Three ways to log events

@agentaudit.trace — simplest, framework-agnostic

@agentaudit.trace
def search_documents(query: str, top_k: int = 5) -> list:
    return vector_db.similarity_search(query, k=top_k)

Logs a tool_call event per call: action is the function's qualified name, input_hash/output_hash are SHA-256 digests of the arguments and return value (never raw), metadata.duration_ms is execution time. A raised exception is logged as severity="critical" with metadata.error, and always still propagates — @trace only observes, it never changes what the wrapped function does. Works on sync and async functions.

LangChainHandler — for LangChain / LangGraph

from agentaudit.integrations import LangChainHandler  # pip install agentaudit-python[langchain]

chain.invoke(inputs, config={"callbacks": [LangChainHandler()]})

Handles on_llm_start/on_llm_end (and on_chat_model_start, which chat models call instead), on_llm_error, on_tool_start/on_tool_end, on_tool_error, and on_chain_error. LLM calls log model name and token usage only — no prompt or response content, hashed or otherwise. This is stricter than the SDK's default elsewhere: a callback wired into every LLM call in a chain has no per-call decision behind it, so it defaults to the safest reading. Tool calls are hashed, matching @trace.

All three error paths log the identical shape: event_type="error", severity="critical", metadata={"error": {"type": ..., "message": ...}}. on_tool_error fires even when the surrounding chain catches the exception and completes normally — a failure the chain recovered from is still worth an audit trail.

Not implemented: a start/end event for the chain run as a whole (that's session-grouping territory, not a per-call audit gap — every LLM call, tool call, and error inside the chain is already captured on its own).

agentaudit.log_event() — manual, for anything custom

agentaudit.log_event(
    event_type="decision",
    action="route_to_human",
    metadata={"reason": "low_confidence", "confidence_score": 0.23},
    severity="warning",
)

event_type is one of tool_call, llm_call, decision, data_access, error, custom. severity is one of info, warning, critical (default info). Pass inputs=/outputs= to get the same hashing guarantee @trace applies automatically.

Privacy

Inputs and outputs are SHA-256 hashed, never sent raw, by default (hash_inputs=True). metadata is the one exception — it is not hashed, because it's yours to control; whatever you put there is sent and stored as-is. Pass hash_inputs=False to init() to opt into raw logging instead; raw values then travel under the reserved keys metadata.raw_input and metadata.raw_output, since the event schema has no top-level field for them. init(environment=...) is likewise recorded as metadata.environment.

Delivery

Capture never blocks: log_event appends to an in-memory queue and returns (~0.05 ms). A daemon thread owning its own asyncio loop and httpx.AsyncClient drains that queue every flush_interval seconds, or as soon as batch_size events are waiting — whichever comes first. One implementation serves both sync and async callers; nothing touches your event loop if you have one.

  • flush(timeout=10.0) forces a send and blocks until it completes.
  • Failed batches are retried max_retries times with exponential backoff and jitter, then spilled to a JSONL file in the temp directory. The buffer is keyed to the API key and agent_id, so a restarted process finds its backlog.
  • While the backend is down, new events queue behind the buffered ones so delivery order matches production order. Buffered events replay first.
  • A repeated failure starts a cooldown between cycles, so a long outage does not cost a full retry budget every flush_interval. An explicit flush() ignores it.
  • Permanent failures (400 malformed event, 401 revoked key) are discarded rather than buffered — they would fail identically forever. A revoked key is latched after the first failure, so it fails once, not on a loop.
  • An atexit hook flushes whatever is queued at process exit.

Verify your integration

agentaudit.flush()
print(agentaudit.status())
# {'connected': True, 'events_sent': 47, 'events_queued': 0, 'events_buffered': 0,
#  'events_dropped': 0, 'last_flush': '2026-08-18T10:30:00.000Z', 'last_error': None}

events_dropped above zero means audit events were lost — check last_error, raise max_queue_size, or investigate why the backend is unreachable. Then open your AgentAudit dashboard's Timeline — you should see the same events there.

Configuration

agentaudit.init(
    api_key="aa_live_sk_...",
    agent_id="my-agent",
    environment="production",       # -> metadata.environment on every event
    batch_size=50,                  # events per batch (default: 50)
    flush_interval=5.0,             # seconds between flushes (default: 5.0)
    max_queue_size=10_000,          # max events in memory queue (default: 10000)
    timeout=10.0,                   # HTTP timeout in seconds (default: 10.0)
    max_retries=3,                  # retries per batch after the first attempt (default: 3)
    base_url="https://your-agentaudit-backend",  # where your team's backend runs
    debug=False,                    # print debug logs to stderr
    enabled=True,                   # set False to disable without removing code
)

Implemented (0.1.0): init, log_event, set_session, status, flush, shutdown, @trace, LangChainHandler, input/output hashing, event builder, bounded queue, batch sender, offline buffer, retries, atexit hook.

Metadata

Release files for agentaudit-python 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agentaudit-python 0.1.2
File Size Uploaded Provenance
agentaudit_python-0.1.2.tar.gz 36.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for agentaudit-python 0.1.2
File Interpreter ABI Platform
agentaudit_python-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 65.4 kB

Release files / agentaudit_python-0.1.2.tar.gz

Download URL agentaudit_python-0.1.2.tar.gz
Size 36.0 kB
Tags Source
SHA-256 checksum
How to use checksums
89c7c5b20dc5b59f3dcf67309d80cae3bf40a9712e03f4468a52a14d51955806
BLAKE2b-256 checksum
How to use checksums
a632b25ecd27fd9e0bba289e9f85142213e38a67294a3cc2ff15f6d3a3e6c28f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / agentaudit_python-0.1.2-py3-none-any.whl

Download URL agentaudit_python-0.1.2-py3-none-any.whl
Size 29.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b4a9086c82da956fcca000cc0c2d4e03931ea090af25d8447ec0fcfc9db0ef21
BLAKE2b-256 checksum
How to use checksums
7b93f49ef39bb69f6671eeae2fbe35819ee110e316d38c9ce3f74c4e55bc2ccd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Security for agentaudit-python 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page