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_retriestimes with exponential backoff and jitter, then spilled to a JSONL file in the temp directory. The buffer is keyed to the API key andagent_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 explicitflush()ignores it. - Permanent failures (
400malformed event,401revoked 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
atexithook 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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| agentaudit_python-0.1.2.tar.gz | 36.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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.