Agent Execution Verification System — transparent audit SDK for AI agents
Project description
AEVS SDK
Agent Execution Verification System — transparent audit SDK for AI agents.
Intercepts tool calls from supported frameworks, builds tamper-evident receipts (HMAC-signed, hash-chained), and sends them to the AEVS backend. Zero changes to your agent code.
Compatibility
- Python 3.10+
- Framework adapters:
aevs[langchain]for LangChain / LangGraph tool interceptionaevs[mcp]for MCP tool interception (requiresmcp>=1.20)
Installation
pip install aevs
With framework extras:
pip install aevs[langchain] # LangChain / LangGraph support
pip install aevs[mcp] # MCP tool support
Quick Start
import aevs
aevs.configure(api_key="aevs_sk_<key_id>_<hex_secret>")
aevs.enable()
# Every tool call from this point is intercepted.
# No changes to tools, agents, or LLM setup.
API
aevs.configure(api_key=..., **options) # Set configuration (required before enable)
aevs.enable() # Auto-detect frameworks and start intercepting
aevs.enable(frameworks=["langchain"]) # Or specify explicitly
aevs.disable() # Unpatch all frameworks, restore originals
aevs.flush() # Force-send buffered receipts to backend
aevs.get_session_id() # UUID minted at enable(); stamped on every receipt
aevs.is_healthy() # False after sustained buffer write failures
Configuration Options
| Parameter | Default | Description |
|---|---|---|
api_key |
(required) | SDK key from customer creation (aevs_sk_<id>_<hex>) |
agent_id |
None |
Agent UUID to tag receipts with |
base_url |
https://api.aevs.fetch.ai/v1 |
AEVS backend URL |
signing_timeout_ms |
2000 |
HTTP timeout for receipt submission |
float_handling |
"decimal_string" |
How floats are serialized (decimal_string or raise) |
float_precision |
6 |
Decimal places for float serialization |
max_payload_bytes |
1048576 |
Max receipt payload size (1 MB) |
buffer_path |
~/.aevs/buffer.db |
SQLite buffer file path |
max_buffer_records |
10000 |
Max buffered receipts before eviction |
drain_interval_ms |
5000 |
Background flush interval |
max_reference_entries |
1000 |
Reference ID registry capacity |
Reference IDs
Every intercepted tool call gets a reference_id (UUID v4) embedded in its receipt. The SDK keeps these in a bounded FIFO registry.
response = await agent.ainvoke({"messages": [("user", query)]})
refs = aevs.get_reference_ids(clear=True)
# [{"seq": 1, "tool_name": "search", "reference_id": "abc-...", "run_id": "def-..."}, ...]
Verify any reference_id via the public backend endpoint (no auth required):
GET /v1/receipts/verify/{reference_id}
Reference ID Registry
aevs.get_reference_id(run_id) # Lookup by framework run_id
aevs.get_reference_ids(clear=True) # Get all entries, then clear
aevs.clear_reference_ids() # Drop all entries
Session IDs
Each enable() mints a fresh UUIDv4 session id. The id is stamped
on every receipt produced in that session and participates in the hash
chain anchor — two SDK processes that share an API key cannot fork the
chain by construction.
aevs.enable()
session = aevs.get_session_id()
# "5db7d195-f84c-4f90-ae12-d74d001d3f9d"
aevs.disable()
aevs.get_session_id()
# None
Useful for log correlation: every receipt carries session_id, so
filtering receipts by session in the AEVS backend isolates a single
SDK run.
Data & privacy
AEVS receipts may include tool inputs and outputs, which can contain secrets or PII depending on what your tools return (e.g. prompts, retrieved documents, API responses).
- Receipts are buffered locally in an encrypted SQLite database (default
~/.aevs/buffer.db). - Receipts are submitted to the AEVS backend over HTTPS by default (
base_url).
You are responsible for ensuring your tool layer does not emit sensitive data you cannot store or transmit. If needed, redact at the tool boundary (before data reaches the agent runtime).
Threat model / non-goals
- AEVS is tamper-evident, not tamper-proof. It helps detect modification/reordering of receipts after the fact; it does not secure a fully compromised host process.
- The SDK signs requests with a key derived from your API key secret; protect the API key like any other credential.
Development
Prerequisites
- Python 3.10+
- Poetry
Setup
git clone https://github.com/fetchai/AEVS-sdk.git && cd AEVS-sdk
make install # poetry install --all-extras
Common commands
The Makefile wraps the everyday workflow. Run make help to see the
full list.
make test # run the test suite
make test-cov # tests with coverage (HTML report in ./htmlcov)
make lint # ruff check
make format # ruff format + auto-fix
make typecheck # mypy --strict on src/
make check # lint + typecheck + tests (the CI gate)
make build # build sdist + wheel into ./dist
You can still call the underlying tools directly:
poetry run pytest tests/test_integration.py -v
poetry run ruff check src/ tests/
poetry run mypy src/
Contributing
See CONTRIBUTING.md for the full guide — branch naming, Conventional Commits, the PR checklist, and release flow.
Reporting Security Issues
Please do not open a public GitHub issue for security problems. See SECURITY.md for the disclosure process.
Architecture
Agent (LangChain / MCP)
│
▼ tool call intercepted
ReceiptBuilder ──▶ HMAC sign + hash chain
│
▼
LocalBuffer (SQLite, encrypted at rest)
│
▼ background drainer
AEVSClient ──▶ POST /v1/receipts ──▶ AEVS Backend
- Interception: Framework-specific patches capture tool inputs/outputs
- Signing: Each receipt is HMAC-signed (HKDF-derived keys) with a hash chain linking sequential calls
- Buffering: Receipts are encrypted and stored locally in SQLite, flushed in the background
- Resilience: Buffer survives process restarts; flush retries on transient failures
Project Structure
aevs-sdk/
├── src/aevs/
│ ├── __init__.py Public API (configure, enable, disable, flush)
│ ├── _api.py Core state management, enable/disable, flush
│ ├── _drainer.py Background flush of buffered receipts
│ ├── _version.py Package version
│ ├── config.py Configuration dataclass + validation
│ ├── exceptions.py SDK exception types
│ ├── adapters/ Framework-specific interceptors
│ │ ├── base.py Base adapter interface
│ │ ├── langchain.py LangChain / LangGraph interceptor
│ │ └── mcp.py MCP tool interceptor
│ ├── core/
│ │ ├── buffer.py Encrypted SQLite local buffer
│ │ ├── client.py HTTP client (sync + async)
│ │ ├── receipt.py ReceiptBuilder — HMAC, hash chain
│ │ ├── serializer.py Canonical JSON serialization
│ │ ├── signer.py Request signing (HKDF + HMAC)
│ │ └── types.py Typed payload shapes
│ └── crypto/
│ ├── chain.py Hash chain helpers
│ ├── hkdf.py HKDF key derivation
│ └── hmac_auth.py HMAC authentication
├── tests/ Test suite
├── pyproject.toml Poetry packaging + tool config
├── poetry.lock
├── LICENSE
└── README.md
Project details
Release history Release notifications | RSS feed
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 aevs-0.1.0.tar.gz.
File metadata
- Download URL: aevs-0.1.0.tar.gz
- Upload date:
- Size: 33.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e8784b6dd24596d7ce3ac3962bd8defea677a1c354a4499fd24655ccf33b1032
|
|
| MD5 |
67dfc72dea6a04be9bb3ee5852cd123a
|
|
| BLAKE2b-256 |
86a6454d0efdfb280ce05b188553c64c143c597b55a20a7839ca793eb70693d0
|
Provenance
The following attestation bundles were made for aevs-0.1.0.tar.gz:
Publisher:
release.yml on fetchai/AEVS-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aevs-0.1.0.tar.gz -
Subject digest:
e8784b6dd24596d7ce3ac3962bd8defea677a1c354a4499fd24655ccf33b1032 - Sigstore transparency entry: 1459561689
- Sigstore integration time:
-
Permalink:
fetchai/AEVS-sdk@6329f8e4a7028a24979086a3e398d3c9a754ee83 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/fetchai
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6329f8e4a7028a24979086a3e398d3c9a754ee83 -
Trigger Event:
push
-
Statement type:
File details
Details for the file aevs-0.1.0-py3-none-any.whl.
File metadata
- Download URL: aevs-0.1.0-py3-none-any.whl
- Upload date:
- Size: 38.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e641c7a15a27a9f55cb0db9db20da3868d5f1feaa8dbdaa1652d6ef69038c98c
|
|
| MD5 |
172cba38a565b486e7b98f9dc87d44a3
|
|
| BLAKE2b-256 |
fcf60762939c552398d23a19ad12bbb41664a762f52dfc3bec7545e0cebb3133
|
Provenance
The following attestation bundles were made for aevs-0.1.0-py3-none-any.whl:
Publisher:
release.yml on fetchai/AEVS-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aevs-0.1.0-py3-none-any.whl -
Subject digest:
e641c7a15a27a9f55cb0db9db20da3868d5f1feaa8dbdaa1652d6ef69038c98c - Sigstore transparency entry: 1459561792
- Sigstore integration time:
-
Permalink:
fetchai/AEVS-sdk@6329f8e4a7028a24979086a3e398d3c9a754ee83 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/fetchai
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6329f8e4a7028a24979086a3e398d3c9a754ee83 -
Trigger Event:
push
-
Statement type: