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.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentaudit_python-0.1.1.tar.gz.
File metadata
- Download URL: agentaudit_python-0.1.1.tar.gz
- Upload date:
- Size: 36.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8ba91b88a6cdd0db72a81ea8de9b792c58e966733222e0d8e9d3c64780d0d79c
|
|
| MD5 |
c58d31323b7e5462bc8703c1881a1f8c
|
|
| BLAKE2b-256 |
7343455637eac7271fe763d55f63238c39868a9d9aff2a1c1facb93b98ea566c
|
File details
Details for the file agentaudit_python-0.1.1-py3-none-any.whl.
File metadata
- Download URL: agentaudit_python-0.1.1-py3-none-any.whl
- Upload date:
- Size: 29.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c17cdcb8a34f20ca606c6673bfc2a27a7a1d24a1bac9fb0e82505b8eeb3d4bc9
|
|
| MD5 |
e0428f3261a044aa8b33f7611369b175
|
|
| BLAKE2b-256 |
5afd346bd0f3b019fcf6f19f1cd753fcd847beb70418ed8d3eb74667fe9f741d
|