Skip to content

Quickstart

Get your first TRACE Trust Record in five minutes.

Install

pip install agentrust-trace

Generate a signing key

from agentrust_trace import generate_key
from cryptography.hazmat.primitives import serialization

key = generate_key()

# Save private key — keep secure, never commit or log
pem_private = key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.PKCS8,
    encryption_algorithm=serialization.NoEncryption(),
)
with open("trace-key.pem", "wb") as f:
    f.write(pem_private)

# Save public key — safe to distribute to verifiers
pem_public = key.public_key().public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo,
)
with open("trace-key.pem.pub", "wb") as f:
    f.write(pem_public)

In production, pass the PEM to TRACE_PRIVATE_KEY_PEM as an environment variable instead of writing it to disk. load_signing_key() reads this variable automatically.

Emit a Trust Record (standalone)

Use sign_record() to produce a Level 0 record without AGT or any other framework:

import time, json
from agentrust_trace import generate_key, sign_record

key = generate_key()

record = {
    "eat_profile": "tag:agentrust-io.com,2026:trace-v0.2",
    "iat": int(time.time()),
    "subject": "spiffe://trust.example.org/agent/my-agent",
    "model": {
        "provider": "anthropic",
        "model_id": "claude-sonnet-4-6",
        "version": "20251001",
    },
    "runtime": {
        "platform": "software-only",
        "measurement": "sha256:" + "0" * 64,
    },
    "policy": {
        "bundle_hash": "sha256:b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7"
                       "f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3",
        "enforcement_mode": "enforce",
    },
    "data_class": "internal",
    "build_provenance": {
        "slsa_level": 1,
        "digest": "sha256:e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
                  "c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6",
    },
    "appraisal": {
        "status": "none",
        "verifier": "https://verifier.example.org",
    },
    "transparency": "https://registry.agentrust-io.com/claim/placeholder",
}

signed = sign_record(record, key)

with open("session.trace.json", "w") as f:
    json.dump(signed, f, indent=2)

This produces a valid Level 0 record. For hardware-attested (Level 1+) records, use cMCP as the runtime — it handles TEE key generation and measurement automatically.

Emit with a persistent key

In production, load the signing key from TRACE_PRIVATE_KEY_PEM so the same key is used across process restarts. load_signing_key() reads that variable and falls back to an ephemeral key with a warning if the variable is not set:

import os, time, json
from agentrust_trace import load_signing_key, sign_record

# Export TRACE_PRIVATE_KEY_PEM before running, or set it in your deployment secrets.
# If unset, an ephemeral key is generated and a warning is emitted; records signed
# with an ephemeral key cannot be re-verified after the process exits.
key = load_signing_key()

record = {
    "eat_profile": "tag:agentrust-io.com,2026:trace-v0.2",
    "iat": int(time.time()),
    "subject": "spiffe://trust.example.org/agent/my-agent",
    "model": {
        "provider": "anthropic",
        "model_id": "claude-sonnet-4-6",
        "version": "20251001",
    },
    "runtime": {
        "platform": "software-only",
        "measurement": "sha256:" + "0" * 64,
    },
    "policy": {
        "bundle_hash": "sha256:b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7"
                       "f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3",
        "enforcement_mode": "enforce",
    },
    "data_class": "internal",
    "build_provenance": {
        "slsa_level": 1,
        "digest": "sha256:e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
                  "c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6",
    },
    "appraisal": {
        "status": "none",
        "verifier": "https://verifier.example.org",
    },
    "transparency": "https://registry.agentrust-io.com/claim/placeholder",
}

signed = sign_record(record, key)

with open("session.trace.json", "w") as f:
    json.dump(signed, f, indent=2)

Verify offline

import json
from agentrust_trace import verify_record, validate_json
from cryptography.exceptions import InvalidSignature

with open("session.trace.json") as f:
    signed_record = json.load(f)

# Schema check
validate_json(signed_record)  # raises jsonschema.ValidationError if malformed

# Signature check — verify against a pinned trusted key in production.
# allow_embedded_key=True trusts the cnf.jwk in the record itself, which
# only proves internal consistency, not that the record came from a trusted issuer.
try:
    verify_record(signed_record, allow_embedded_key=True)
    print("Signature valid (Ed25519)")
    print(f"  subject:     {signed_record['subject']}")
    print(f"  policy:      {signed_record['policy']['bundle_hash'][:24]}... "
          f"({signed_record['policy']['enforcement_mode']})")
    print(f"  data_class:  {signed_record['data_class']}")
    print(f"  appraisal:   {signed_record['appraisal']['status']}")
except InvalidSignature:
    print("Signature invalid")

Output:

Signature valid (Ed25519)
  subject:     spiffe://trust.example.org/agent/my-agent
  policy:      sha256:b2c3d4e5f6a7b8c9... (enforce)
  data_class:  internal
  appraisal:   none

verify_record() raises cryptography.exceptions.InvalidSignature if the record was tampered with after signing. appraisal.status is none here because no external verifier was contacted — see Verification Protocol for the full five-step flow.

What you now have

Claim What it proves
policy.bundle_hash Exact Cedar policy hash that governed the session
tool_transcript.hash Merkle-chained audit log of every tool invocation
subject Workload identity (SPIFFE or DID)
appraisal.status Verifier judgment: affirming / contraindicated
signature Ed25519 over the full record — verifiable offline

Add hardware attestation (Level 2)

For TEE-rooted records (AMD SEV-SNP, Intel TDX, NVIDIA H100), use cMCP as the runtime — it issues Level 2 TRACE records with a TEE-bound key and a SCITT transparency anchor automatically.

Integration guide: cMCP

Next steps