Skip to main content

Wytness — the blackbox recorder for AI agents. Customer-held PII keys, per-event Ed25519 signing, audit-ready evidence packs. Built on Microsoft's Agent Governance Toolkit.

Project description

wytness

Wytness wrapper for Microsoft's Agent Governance Toolkit (AGT). Adds the two security properties AGT does not ship:

  • Non-repudiation — per-event Ed25519 signature with a customer-held private key. Asymmetric verification: anyone with the public key can verify, no shared secret.
  • Zero-knowledge PII — HMAC-SHA256 pseudonyms + X25519 + ChaCha20-Poly1305 token-map encryption. Wytness never sees raw PII.

These compose with AGT's own primitives (Ed25519 agent identity, SHA-256 Merkle hash chain). See docs/agt-wrapper-design.md §2.5 for the full layered model.

Mirrors wytness_ai (TypeScript) — same wire format, same init() / shutdown() lifecycle, same env-var contract.

Status

v1.0.0 — first stable release. Coordinated launch with wytness 1.0.0 (TypeScript). WytnessAuditSink, WytnessEventSink, WytnessTransport, init(), shutdown(), the Ed25519 envelope (envelope_version: 2 — signature covers data + envelope id/time/type), the X25519 + ChaCha20-Poly1305 PII token-map with auto-attach, the typed exception hierarchy (WytnessSDKError + subclasses), the top-level stats() / health() / wire_status() accessors, and the AGT AuditLog monkey-patch all ship as working code. agent-governance-toolkit[full]==3.7.0 is a hard dependency since the wrapper monkey-patches AGT's AuditLog symbol on init({auto_wire=True}) (the default) so every audit entry AGT chains is automatically forwarded into the Wytness envelope path with full 3-layer evidence (AGT identity + AGT Merkle chain + Wytness envelope).

Tests: 68 pytest green covering config validation (XOR PII pairing guard, signing-key prefix/length tolerance, env-var fallback), envelope signing + tamper-detection, PII pseudonymisation + per-sink token-map encryption + auto-attach, transport batching + retry + dead-letter file + jittered backoff, init/shutdown idempotency, stats/health pre-init safety, and end-to-end framework-adapter compatibility against AGT 3.7.0's 12 integrations (LangChain, CrewAI, LangGraph, MCP, etc.). Backend dual-accepts envelope_version 1 + 2 during the deprecation window — see CHANGELOG.md for the v1 → v2 wire-format migration.

Install

pip install wytness-ai

agent-governance-toolkit[full]==3.7.0 is a hard dependency — installed automatically. No extras to remember. Python >=3.11.

Hello world

from wytness_ai import init, shutdown, AuditLog

init(
    api_key="wyt_...",
    signing_key="...",     # browser-generated Ed25519 (always required)
    pii_pubkey="...",      # browser-generated X25519 (optional, paired with pii_secret)
    pii_secret="...",      # browser-generated HMAC secret (optional, paired with pii_pubkey)
    pii_fields=["customer.email"],
)

# AGT owns identity + Merkle chain. The wrapper has already monkey-patched
# AuditLog — every entry below also flows to Wytness.
audit = AuditLog()
audit.log(
    event_type="tool_invocation",
    agent_id="my-first-agent",
    data={
        "customer": {"email": "alice@example.com"},
        "query": "best espresso",
    },
)

shutdown()

AuditLog is re-exported from wytness_ai for convenience, so a single import line covers both lifecycle and audit. The original from agentmesh.governance.audit import AuditLog is identical and still works.


PII is pseudonymised before AGT computes its chain hash (so AGT's hashes commit to the redacted bytes — chain verification still works), the canonical-JSON envelope is signed with your Ed25519 key, and the batch lands at `api.wytness.ai/ingest`. Failed POSTs land in `~/.wytness/wytness-deadletter.jsonl`.

`init()` reads `WYTNESS_API_KEY` / `WYTNESS_SIGNING_KEY` / `WYTNESS_PII_PUBKEY` / `WYTNESS_PII_SECRET` / `WYTNESS_ENDPOINT` from the environment when kwargs aren't supplied. Browser-generated keys come from the [Wytness dashboard's Keys page](https://app.wytness.ai/keys) (Signing Key, PII Encryption Key, and PII HMAC Key cards); the dashboard never sees your private halves.

A complete runnable example lives at [`examples/hello-world/`](examples/hello-world/) — it generates ephemeral demo keys if no `WYTNESS_*` env vars are set, so you can `python examples/hello-world/main.py` immediately after install.

### Manual wiring (no monkey-patch)

If you'd rather wire explicitly, pass `auto_wire=False` and use the audit sink directly. The sink accepts AGT `AuditEntry` instances + dicts shaped like one.

```python
from wytness_ai import init, get_transport
from wytness_ai.sinks import WytnessAuditSink

config = init(auto_wire=False, signing_key="...", api_key="...")
transport = get_transport()
sink = WytnessAuditSink(transport=transport, config=config)
sink.write({
    "event_type": "tool_invocation",
    "agent_id": "agent-1",
    "data": {"query": "…"},
})

Feature parity with wytness_ai (TypeScript)

Both SDKs ship the same wire format (snake_case canonical shape, identical envelope structure, byte-comparable for the same logical input). Behavioural surface differences:

Surface Python TypeScript Notes
AGT AuditLog auto-wire ✓ — patches agentmesh.governance.audit.AuditLog ✓ — patches AuditLogger.prototype.log from @microsoft/agent-governance-sdk Both default auto_wire=True / autoWire: true.
AGT GovernanceEvent auto-wire ✓ — registers WytnessEventSink on GovernanceEventProcessor ✗ — manual (getEventSink().emit(...)) AGT-TS 3.7.0 has no GovernanceEventProcessor registry. Tracked as V2-AGT-TS-EVENT-SINK; will wire automatically when Microsoft ships the registry.
Wire-format byte parity Cross-language fixture in sdk-typescript-agt/tests/integration/wireFormat.parity.test.ts.
Ed25519 envelope signing Identical canonical-JSON encoding + sig scope.
PII pseudonymisation Identical HMAC + X25519 + ChaCha20-Poly1305 primitives.
Framework adapter compatibility tests ✓ — 12 integrations × 3 axes (import / monkey-patch survival / PII scrub) ✗ — AGT-TS ships zero framework adapters in 3.7.0

Wire format

Each POST batch is a JSON array of CloudEvents envelopes:

[
  {
    "specversion": "1.0",
    "id": "<uuid>",
    "source": "wytness",
    "type": "AuditEntry",
    "datacontenttype": "application/json",
    "time": "2026-05-25T00:00:00.000Z",
    "data": {
      "timestamp": "2026-05-25T00:00:00.000Z",
      "agent_id": "my-first-agent",
      "event_type": "tool_invocation",
      "entry_hash": "<AGT-supplied SHA-256 hex>",
      "previous_hash": "<prior entry's hash>",
      "data": { "query": "…", "customer": { "email": "EMAIL_<token>" } }
    },
    "wytness_envelope": {
      "envelope_version": 1,
      "key_id": "<16 chars base64url SHA-256(pubkey)>",
      "signature_ed25519": "<base64 Ed25519 sig over canonicalJson(data)>",
      "pseudonymization_version": "1"
    }
  }
]

Content-Type: application/vnd.wytness.agt+json — every envelope is signed. Wytness has no unsigned mode; signing is the product's value prop.

License

MIT. Built on agent-governance-toolkit (MIT, Microsoft).

Project details


Download files

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

Source Distribution

wytness_ai-1.0.0.tar.gz (147.1 kB view details)

Uploaded Source

Built Distribution

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

wytness_ai-1.0.0-py3-none-any.whl (34.2 kB view details)

Uploaded Python 3

File details

Details for the file wytness_ai-1.0.0.tar.gz.

File metadata

  • Download URL: wytness_ai-1.0.0.tar.gz
  • Upload date:
  • Size: 147.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for wytness_ai-1.0.0.tar.gz
Algorithm Hash digest
SHA256 284d35224751abec9333a771d222452c71acd8a8ac5f69cb7717292529be8e8f
MD5 67afd602ade52da36d013ba40b4ccd9b
BLAKE2b-256 026e0c5855ea8b37e87ecb51cb32173ab9c7da9930754b540647e4a9e5b40de4

See more details on using hashes here.

Provenance

The following attestation bundles were made for wytness_ai-1.0.0.tar.gz:

Publisher: publish-wrapper-sdk.yml on imwickkd/wytness

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file wytness_ai-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: wytness_ai-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 34.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for wytness_ai-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 593dd8227042ab5df816c5d7df6e25b80b826eebe47f45a06ee44537ef134151
MD5 3cfbde627663ac228d5776c07d1e6778
BLAKE2b-256 5dd8412b96a30bfc848f794503a553c5627d4b9a08de9109688b539f3d71f2e2

See more details on using hashes here.

Provenance

The following attestation bundles were made for wytness_ai-1.0.0-py3-none-any.whl:

Publisher: publish-wrapper-sdk.yml on imwickkd/wytness

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

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