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.

Download files

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

Source Distribution

agentaudit_python-0.1.1.tar.gz (36.0 kB view details)

Uploaded Source

Built Distribution

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

agentaudit_python-0.1.1-py3-none-any.whl (29.4 kB view details)

Uploaded Python 3

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

Hashes for agentaudit_python-0.1.1.tar.gz
Algorithm Hash digest
SHA256 8ba91b88a6cdd0db72a81ea8de9b792c58e966733222e0d8e9d3c64780d0d79c
MD5 c58d31323b7e5462bc8703c1881a1f8c
BLAKE2b-256 7343455637eac7271fe763d55f63238c39868a9d9aff2a1c1facb93b98ea566c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for agentaudit_python-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c17cdcb8a34f20ca606c6673bfc2a27a7a1d24a1bac9fb0e82505b8eeb3d4bc9
MD5 e0428f3261a044aa8b33f7611369b175
BLAKE2b-256 5afd346bd0f3b019fcf6f19f1cd753fcd847beb70418ed8d3eb74667fe9f741d

See more details on using hashes here.

Supported by

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