Skip to main content

Overview

AgentSystems Notary creates cryptographically verifiable audit trails for AI systems.

Why

When AI behavior is questioned by customers, auditors, regulators, insurers, etc., you need to prove what actually happened. Traditional logs don’t work: you control them, so third parties have to trust you didn’t modify them. Tamper-evident logging removes that trust requirement.

How it works

Raw LLM interactions stay in your storage. No third party sees them during normal operation. But cryptographic hashes of each interaction are written to independent storage (Arweave or the AgentSystems API) at the same time. If there’s ever an audit or dispute, you provide the raw logs. The auditor re-hashes them and compares against the stored hashes. A match indicates the logs are unaltered. A mismatch indicates tampering or corruption. You control your data, but can’t alter it without detection. What gets logged:
  • To your storage: input prompt, response text, agent metadata, session IDs, timestamps
  • To ledger: SHA-256 hash + metadata (e.g. namespace, session ID, timestamps)

Hash storage options

Hashes (not raw data) can be written to either storage option:
StorageBest ForFeatures
Decentralized (Arweave)No vendor lock-inPublic append-only ledger, open-source verification, no account needed
CustodiedManaged complianceWrite-once storage, verification UI, signed attestations for audits
Custodied plans offer WORM-compliant hash storage, managed signing, and signed attestations.

Prerequisites

pip install agentsystems-notary langchain langchain-anthropic python-dotenv

Example (decentralized)

1

Generate signing key

openssl genrsa -out arweave-key.pem 4096
For production, use AWS KMS or another cloud key management service.
2

Create .env file

Create a .env file in your project root:
# AWS S3 for raw payload storage
ORG_AWS_S3_BUCKET_NAME=your-bucket
ORG_AWS_S3_ACCESS_KEY_ID=AKIA...
ORG_AWS_S3_SECRET_ACCESS_KEY=...
ORG_AWS_S3_REGION=us-east-1

# Path to signing key
ARWEAVE_PRIVATE_KEY_PATH=./arweave-key.pem

# Anthropic
ANTHROPIC_API_KEY=sk-ant-...
3

Run the example

import os

from agentsystems_notary import (
    LangChainNotary,
    ArweaveHashStorage,
    AwsS3StorageConfig,
    LocalKeySignerConfig,
    RawPayloadStorage,
)
from langchain_anthropic import ChatAnthropic
from dotenv import load_dotenv

load_dotenv()

# Your S3 bucket for raw LLM payloads
s3_config = AwsS3StorageConfig(
    bucket_name=os.environ["ORG_AWS_S3_BUCKET_NAME"],
    aws_access_key_id=os.environ["ORG_AWS_S3_ACCESS_KEY_ID"],
    aws_secret_access_key=os.environ["ORG_AWS_S3_SECRET_ACCESS_KEY"],
    aws_region=os.environ["ORG_AWS_S3_REGION"],
)
raw_payload_storage = RawPayloadStorage(storage=s3_config)

# Local RSA key for signing
signer = LocalKeySignerConfig(
    private_key_path=os.environ["ARWEAVE_PRIVATE_KEY_PATH"],
)

# Arweave for decentralized hash storage
arweave_storage = ArweaveHashStorage(
    namespace="tenant_a1b2c3d4",
    signer=signer,
)

# Create notary callback
notary = LangChainNotary(
    raw_payload_storage=raw_payload_storage,
    hash_storage=[arweave_storage],
    debug=True,
)

# Attach to model
model = ChatAnthropic(
    model="claude-sonnet-4-5-20250929",
    api_key=os.environ["ANTHROPIC_API_KEY"],
    callbacks=[notary],
)

response = model.invoke("What is the capital of France?")
print(response.content)
The namespace is written to the public ledger. Use an anonymous tenant identifier, not a company name.

Verification

Decentralized (Arweave): Download raw payloads from your storage bucket, then verify with the open-source CLI:
npm install -g agentsystems-verify
agentsystems-verify --logs logs.zip
The CLI re-hashes each payload and compares against the hashes stored on Arweave. Alternatively, the Verify UI supports both decentralized and custodied verification.

Configuration

Resources


Connect these docs to Claude, VSCode, and more via MCP for real-time answers.