auditant
Compliance system-of-record for AI agents: every action your agents take, hash-chained, policy-checked, externally countersigned — and verifiable offline by someone who doesn't trust you.
Two lines
import auditant
auditant.init(api_key="ak_…", log_id="t_…/prod", agent_id="underwriter")
With OpenTelemetry present, init() registers a span processor and
activates whichever of four OpenInference instrumentors are installed —
LangChain (which is what sees LangGraph), CrewAI, OpenAI, Anthropic — so
LLM calls and tool executions become chained audit events automatically:
hashes, never payloads; token counts reported as observed-not-priced, never
as $0. When the OpenAI Agents SDK is importable, init() registers on its
trace-processor bus as well. Install the extras for what you run:
pip install "auditant[openinference]" # all four instrumentors
pip install "auditant[langchain]" # or one at a time: [crewai], [openai-agents], [gateway]
handle.activated lists what actually turned on. An instrumentor installed
for a framework that is not present counts as not activated — the SDK
never reports coverage of code it cannot see.
Without OpenTelemetry, init() still gives you a session on the chain
(lifecycle + heartbeats, so a quiet agent is distinguishable from a dead
emitter), the manual record() API, and the synchronous policy check:
handle = auditant.init(api_key="ak_…", log_id="t_…/prod", agent_id="underwriter")
verdict = handle.decide({"action": "wire_transfer", "amount": 50_000,
"input": {"to": "acct 7"}}) # hashed into the record, never sent
# {'effect': 'pending_approval', ...} → a human approves in the dashboard
# or from Slack, and the same call then returns 'allow'.
# async hosts: await handle.adecide({...})
Every decide() chains a policy_decision event before anything happens —
that is what the approval queue is built from. Evidence writes never block
your agent (queued, batched, spilled to disk on outage), and the policy
service failing means a recorded enforcement gap, never a silent allow.
Block → approve → resume, in your framework
Capture is automatic; enforcement is one more line, because something has
to stand in front of the tool. Both shims ask decide() before a guarded
tool runs, chain the answer, and express a hold in the framework's own
pause:
# LangGraph — interrupt() + a checkpointer
from auditant.langgraph import guard
tools = guard(handle, [wire_transfer, lookup_balance], amount="amount")
out = graph.invoke(state, config) # held ⇒ out["__interrupt__"]
# …a named human approves in the dashboard or from Slack…
out = graph.invoke(Command(resume=True), config) # re-asks, walks through
# OpenAI Agents SDK — needs_approval
from auditant.openai_agents import guard, resolve
agent = Agent(name="underwriter", tools=guard(handle, [wire_transfer], amount="amount"))
result = await Runner.run(agent, "wire $50,000 to acct 7")
while result.interruptions:
answer = await resolve(handle, result) # answered from the chain
if not answer.ready: await asyncio.sleep(30); continue
result = await Runner.run(agent, answer.state)
The resume value is never the approval: what lets the action through is
the human's answer on the chain, matched by session and action server-side.
A refusal reaches the model in the policy's words rather than as a crash,
and is chained as blocked. Monitor-mode rules and enforce=False record
everything and stop nothing.
The examiner's side
Every exported bundle is self-verifying: it embeds a dependency-free
verifier (node verify.mjs bundle.json) that recomputes the chain and
validates every countersignature — no account, no network, nothing from us.
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 auditant-0.3.0.tar.gz.
File metadata
- Download URL: auditant-0.3.0.tar.gz
- Upload date:
- Size: 49.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12d7e7aec0e7faf2fc07f1bc0a7887af4dc712fc54e1c012261a423fefa7d6c9
|
|
| MD5 |
f9ceaafef1e0ee59b84d2e400505725e
|
|
| BLAKE2b-256 |
40c940b3fcbd5911c1c7f615dddab5ceca3477de612d12987d019cfb2988ff53
|
File details
Details for the file auditant-0.3.0-py3-none-any.whl.
File metadata
- Download URL: auditant-0.3.0-py3-none-any.whl
- Upload date:
- Size: 37.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9fe60fcbe6fac47f46b238cafe9f38f3abc1fa7b5c0ae12b2e529210cd34e553
|
|
| MD5 |
2caad788e1a28c3626f9855235eee020
|
|
| BLAKE2b-256 |
252b5f611de444d1fba5921c3e4db2ab728f2776f10872a6c111873d11673438
|