Python SDK for Wytness — audit logging for AI agents with cryptographic signing and chain integrity
Project description
Wytness Python SDK
⚠️ Deprecated — use
wytness-agtinsteadThe Wytness v2 wrapper SDK ships as
wytness-agt, built on top of Microsoft's Agent Governance Toolkit (AGT) (MIT, released April 2026). AGT does identity Ed25519, IATP delegation, Merkle hash chain, and policy enforcement — primitives this SDK rolled itself.wytness-agtis a thin wrapper that adds the Wytness layers AGT deliberately leaves out: customer-held PII tokenisation, per-event Ed25519 envelope (non-repudiation), and bring-your-own-storage routing.Migrate when convenient. This package (
wytness-sdk) remains installable for now but is feature-frozen — no new features land here past 2026-12-31, and security-only patches are committed through 2027-06-30. After that the package goes read-only on PyPI.Install the v2 wrapper:
pip install wytness-agtThen call
wytness_agt.init(...)with your API key + signing key + PII keypair. The new install bundle is one copy-paste block from the operator's Keys page.See docs/agt-wrapper-design.md for the architecture, and the
wytness-agtREADME for the new usage.
Audit logging for AI agents. Every action your AI agent takes is cryptographically signed, hash-chained, and streamed to the Wytness platform for compliance and observability.
Installation
pip install wytness-sdk
One-time setup — generate and configure your signing key
The SDK refuses to construct an AuditClient until a signing keypair
is configured — it raises WytnessSetupError otherwise. This is by
design: pre-configuring ensures the matching public PEM is already
registered with the platform, so /ingest cannot 412 on signature
verification.
-
Generate the keypair at https://app.wytness.ai/keys. The private key is created in your browser and offered for download as the literal string
wyt_pk_sign_<base64>— Wytness never sees it. The matching public PEM is registered with the platform automatically. -
Configure it for the SDK. Pick one — env var is recommended:
Env var (recommended for every environment): set the downloaded value as the
WYTNESS_SIGNING_KEYenv var in your secrets manager /.env/ deployment platform's env config. Since 0.12.3 the SDK reads it automatically — no boilerplate in the constructor:client = AuditClient( agent_id="my-agent", http_api_key=os.environ["WYTNESS_API_KEY"], )
To pass the key explicitly instead,
signing_key=os.environ["WYTNESS_SIGNING_KEY"]still works and wins precedence over the env-var auto-read.File on disk (local prototyping only): save the downloaded file to
./keys/signing.key. The SDK reads this path by default. ⚠️ Addkeys/to your.gitignorefirst — the private signing key is the root of trust for the entire audit guarantee; if it leaks into git an attacker can fabricate events that look like they came from your agent. Treat it like a database password. -
Verify the local key matches what the portal has registered:
wytness-show-public # or: python -m wytness.show_public
Quick Start
from wytness import AuditClient, audit_tool
# Initialize the client
client = AuditClient(
agent_id="my-agent",
human_operator_id="user-123",
http_api_key="wyt_api_live_...", # from app.wytness.ai settings
)
# Decorate any tool your agent calls
@audit_tool(client=client)
def send_email(to: str, subject: str, body: str):
# Your tool implementation
pass
# Every call is automatically logged, signed, and chained
send_email(to="team@company.com", subject="Report", body="Weekly summary")
Features
- Response capture — AI agent responses are automatically captured, truncated to 5K chars, and PII-redacted
- PII redaction — emails, SSN, TFN, credit cards, and phone numbers are automatically redacted from responses and parameter values
- Cryptographic signing — every event is signed with Ed25519
- Hash chaining — tamper-evident chain of events per agent session
- Automatic secret redaction — secrets in parameter names are automatically redacted
- HTTP transport — stream events to api.wytness.ai over HTTPS
- File fallback — events are saved locally if the API is unreachable
HTTP Emitter (Recommended)
Send events directly to the Wytness API using your API key:
client = AuditClient(
agent_id="my-agent",
human_operator_id="user-123",
http_endpoint="https://api.wytness.ai",
http_api_key="wyt_api_live_...",
)
API
AuditClient(agent_id, **kwargs)
| Parameter | Type | Default | Description |
|---|---|---|---|
agent_id |
str |
required | Unique identifier for the agent |
agent_version |
str |
"0.1.0" |
Version of the agent |
human_operator_id |
str |
"unknown" |
ID of the human overseeing the agent |
signing_key |
str|None |
None |
Base64-encoded Ed25519 private key — typically os.environ["WYTNESS_SIGNING_KEY"]. Recommended in every environment (no risk of accidental git commit). Accepts the portal-emitted wyt_pk_sign_<base64> string with the prefix included. |
signing_key_path |
str |
"./keys/signing.key" |
Path to the Ed25519 private key on disk. SDK raises WytnessSetupError if no key exists at this path. Save the file downloaded from https://app.wytness.ai/keys here for local prototyping only — add keys/ to your .gitignore first. Ignored when signing_key is set. |
http_api_key |
str|None |
None |
API key for HTTP endpoint |
http_endpoint |
str |
"https://api.wytness.ai" |
HTTP API endpoint URL |
fallback_log_path |
str |
"./audit_fallback.jsonl" |
Local fallback file path |
@audit_tool(client, task_id="default", prompt=None, reasoning_summary=None, inputs_classification=None, auto_extract=True)
Decorator that wraps a function to automatically log audit events. Works with both sync and async functions. Captures:
- Function name, parameters (with secret redaction), and return value hash
- Response text (truncated to 5K chars, PII-redacted) — the function's return value as a string
- Execution duration, success/failure status, and error codes
- Cryptographic signature and hash chain link
- Per-process
agent_instance_id(since 0.13.0) — UUID persisted to./keys/.instance_id; the Wytness Agents page uses it to count distinct instances peragent_id.
Auto-captured fields by convention (since 0.13.0; disable with auto_extract=False):
prompt— picked from any wrapped-function argument named one ofuser_input,prompt,question,query,input_text,message,user_message(first match, truncated to 2000 chars).reasoning_summary— extracted by duck-typing the return value. Anthropic-style.contenttext blocks and OpenAI-style.choices[0].message.contentrecognised, truncated to 500 chars. Plain string returns ignored (no false positives).inputs_classification— set to"restricted"when any kwarg name containsssn/tfn/credit_card/card_number/passport(case-insensitive).
All three accept an explicit string OR a callable (args, kwargs) -> str that wins precedence over the convention.
client.session_id
Read-only property returning the UUID for this client instance.
client.flush(timeout=5.0)
Wait for pending HTTP requests to complete. Call before process exit in serverless/short-lived environments.
hash_value(value)
SHA-256 hash of any JSON-serialisable value. Use this when recording events manually to compute inputs_hash / outputs_hash.
from wytness import hash_value
result = my_tool(data)
outputs_hash = hash_value(result)
Logging
The SDK emits diagnostics (HTTP ingest errors, fallback replay info,
key-generation warnings, record-path errors) through Python's standard
logging module, under the wytness logger. Control verbosity the same
way you would for any other library:
import logging
# Silence the SDK completely:
logging.getLogger("wytness").setLevel(logging.CRITICAL)
# Or just silence the info-level replay messages, keep warnings + errors:
logging.getLogger("wytness").setLevel(logging.WARNING)
# Or route everything to your own handler:
logging.getLogger("wytness").addHandler(my_handler)
If you haven't configured Python's logging at all, SDK warnings and errors appear on stderr via the default last-resort handler.
License
MIT
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 wytness_sdk-0.14.0.tar.gz.
File metadata
- Download URL: wytness_sdk-0.14.0.tar.gz
- Upload date:
- Size: 308.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
05687a1bca4a85d033de647e6f92427a309c28e4d4b4ea4a3e125cd825d1380e
|
|
| MD5 |
7ad3699fca5094c045d75d7cccffcc28
|
|
| BLAKE2b-256 |
28a1794cb505e8501e0c16440dcca209471ced1fa79ba432538684d430b3c1b7
|
Provenance
The following attestation bundles were made for wytness_sdk-0.14.0.tar.gz:
Publisher:
publish-sdk.yml on imwickkd/wytness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wytness_sdk-0.14.0.tar.gz -
Subject digest:
05687a1bca4a85d033de647e6f92427a309c28e4d4b4ea4a3e125cd825d1380e - Sigstore transparency entry: 1596958895
- Sigstore integration time:
-
Permalink:
imwickkd/wytness@36200848cf3a5d55c3db06e8f8e872fdd7572e84 -
Branch / Tag:
refs/tags/sdk-v0.14.0 - Owner: https://github.com/imwickkd
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-sdk.yml@36200848cf3a5d55c3db06e8f8e872fdd7572e84 -
Trigger Event:
push
-
Statement type:
File details
Details for the file wytness_sdk-0.14.0-py3-none-any.whl.
File metadata
- Download URL: wytness_sdk-0.14.0-py3-none-any.whl
- Upload date:
- Size: 27.7 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 |
5b9d585bdee3aa2d9bcc53ed89d2a816f4c07429487fac6b6c1fcea736eca359
|
|
| MD5 |
15cb55937d739e94e64d7f9c36193a83
|
|
| BLAKE2b-256 |
f18bb89abb8013804025be27484c873b8d39fac8af148a9c29b07e3cd5d2446d
|
Provenance
The following attestation bundles were made for wytness_sdk-0.14.0-py3-none-any.whl:
Publisher:
publish-sdk.yml on imwickkd/wytness
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wytness_sdk-0.14.0-py3-none-any.whl -
Subject digest:
5b9d585bdee3aa2d9bcc53ed89d2a816f4c07429487fac6b6c1fcea736eca359 - Sigstore transparency entry: 1596958984
- Sigstore integration time:
-
Permalink:
imwickkd/wytness@36200848cf3a5d55c3db06e8f8e872fdd7572e84 -
Branch / Tag:
refs/tags/sdk-v0.14.0 - Owner: https://github.com/imwickkd
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-sdk.yml@36200848cf3a5d55c3db06e8f8e872fdd7572e84 -
Trigger Event:
push
-
Statement type: