Skip to main content

Signatrust — Python SDK

A verifiable, tamper‑evident receipt for every AI decision. Standard library only — no dependencies.

from signatrust import Signatrust

client = Signatrust(api_key=os.environ["SIGNATRUST_API_KEY"])

result = client.sign(
    model={"provider": "openai", "name": "gpt-4o", "version": "2026.4"},
    decision={
        "type": "loan_rejection",
        "input": user_input,      # hashed locally — raw data never leaves
        "output": agent_output,   # hashed locally
        "risk_level": "high",
        "human_review": True,
        "policies": ["eu-ai-act-high-risk"],
    },
)

receipt = result["receipt"]
assert client.verify(receipt["id"])["valid"]

Zero-Data-Access by default

Signatrust is designed so that the raw content of a decision, the subject's identity, and the reviewer's identity stay inside your environment. The SDK only ships cryptographic commitments (SHA-256) to our servers.

Field Sent to Signatrust Stays local
input / output raw text ✓ (via hash_locally=True, default)
input_hash / output_hash
Model id, risk level, policies, business event
Subject identity (patient MRN, applicant id, claim id) ✗ (never — you don't send it)
Reviewer identity, role, specialty ✗ (never — see Human review)
human_review_attestation_hash (SHA-256 of reviewer info)
Receipt id, receipt hash, signature ✓ (returned to you)

Constructor

Signatrust(api_key, base_url="https://signatrust.net", hash_locally=True, timeout=15.0)

Methods

  • sign(decision, model=None, metadata=None, trace=None, scope_declaration=None, human_reviewer=None) → seal a decision.
  • issue_receipt(...) → alias for sign (identical behaviour).
  • verify(receipt_id) → verify a stored receipt.
  • verify_receipt(receipt) → verify a receipt object you hold.
  • get_receipt(receipt_id) → fetch a sealed receipt.
  • trust_score(agent_id) → fetch an agent's Trust Score.
  • trace(trace_id=None, mode="every_tool_call") → open a trace scope for tool-call-level sealing.

Utilities also exported: fingerprint(content), new_trace_id(), human_reviewer_attestation(reviewer), and the ReceiptReferenceStore class.

Human review attestation — WHO reviewed and what is their specialty

Signatrust records whether a human reviewed a decision (human_review: True|False) and optionally a cryptographic commitment to the reviewer's identity and specialty (human_review_attestation_hash). The reviewer's actual name, role, and specialty stay on your side — they never enter our systems.

result = client.sign(
    decision={
        "type": "triage_recommendation",
        "input":  raw_prompt,   # hashed locally
        "output": raw_output,   # hashed locally
        "risk_level": "high",
        "policies": ["triage-protocol-v4", "stemi-fast-track"],
    },
    human_reviewer={
        "id":          "STAFF-7734",              # your internal staff/licence id
        "role":        "attending_physician",     # free-form role label
        "specialty":   "cardiology",              # discipline
        "reviewed_at": "2027-06-01T09:20:00Z",    # ISO-8601, defaults to now
        "note":        "STEMI protocol confirmed",
    },
)

# result["receipt"]["decision"]["human_review"] == True
# result["receipt"]["decision"]["human_review_attestation_hash"] == "sha256:<64 hex>"
# result["human_reviewer"] echoes the reviewer fields for your local storage.

What each side holds

Customer supplies to the SDK:                   Sent to Signatrust (enters signed receipt):
──────────────────────────────                  ──────────────────────────────
{                                               {
  "id": "STAFF-7734",                             "human_review": true,
  "role": "attending_physician",                  "human_review_attestation_hash":
  "specialty": "cardiology",                        "sha256:<64 hex>"
  "reviewed_at": "2027-06-01T09:20:00Z",        }
  "note": "STEMI protocol confirmed"            (no reviewer name / role /
}                                                specialty / note travels)

Years later, given the reviewer's original details (held by you or your customer's record system), anyone can recompute the same commitment via human_reviewer_attestation({...})["hash"] and match it against the historical value inside the sealed receipt — proving which reviewer signed off, without Signatrust ever having held that information.

ReceiptReferenceStore — linking receipts to your own records

Signatrust intentionally does not hold a subject → receipt_id map. The subject (patient, applicant, employee, claim) belongs to your domain; the receipt belongs to ours. The bridge lives on your side.

The SDK ships a minimal, dependency-free ReceiptReferenceStore that persists these bridges as append-only JSONL with mode 0o600 — a reference implementation you can adopt, adapt, or replace with your own database.

from signatrust import Signatrust, ReceiptReferenceStore

client = Signatrust(api_key=os.environ["SIGNATRUST_API_KEY"])
store  = ReceiptReferenceStore(file_path="/var/lib/hospital/signatrust-refs.jsonl")

result = client.sign(
    decision={...},
    human_reviewer={
        "id": "STAFF-7734", "role": "attending_physician", "specialty": "cardiology",
    },
)

# Attach the Receipt ID to your own internal record. Signatrust never sees this row.
store.attach(
    result,
    subject_ref="PT-84721",           # your internal patient/customer id
    case_ref="E-2027-551",            # your internal encounter/case id
    label="triage_recommendation",
    actor="TriageBot v4",
    action="STEMI fast-track routing",
    method_note="protocol=stemi-fast-track; prompt_id=triage-2027-Q3",
)

# Five years later, retrieve by any local identifier:
by_patient = store.find_by_subject("PT-84721")
by_case    = store.find_by_case("E-2027-551")
by_receipt = store.find_by_receipt_id("STR-A1B2C3...")

What each row contains (all local, never sent to Signatrust)

Field Purpose
receipt_id, receipt_hash The bridge to the Signatrust receipt.
subject_ref Your internal subject id (patient MRN, applicant id, claim id, employee id).
case_ref Optional secondary id (encounter, transaction, work-order).
label, actor, action Human-searchable descriptors in your vocabulary.
method_note Free-text: protocol id, prompt id, chain-of-custody id.
input_hash, output_hash Copies of the receipt commitments (convenience).
human_reviewer Full reviewer object — id, role, specialty, reviewed_at, note.
human_review_attestation_hash Copy of the commitment that entered the signed receipt.
tags Any non-sensitive tags for filtering.
recorded_at When your system wrote the row.

Deeper walkthrough: https://signatrust.net/receipt-reference.

Chain of custody — tool-call level sealing

By default, sign() seals the final decision only. For agentic workflows where intermediate tool calls influence the outcome, open a trace and seal every step — the full chain (search → db lookup → LLM decision → final response) becomes a verifiable, tamper-evident timeline sharing one trace_id.

trace = client.trace(mode="every_tool_call")

trace.step(
    step_type="tool_call",
    tool_name="search",
    decision={"type": "tool_result", "output": raw_search_json},
)

trace.step(
    step_type="tool_call",
    tool_name="db_lookup",
    decision={"type": "tool_result", "output": rows_json},
)

trace.step(
    step_type="final_response",
    decision={
        "type": "loan_decision",
        "input": user_application,
        "output": final_decision_json,
        "risk_level": "high",
    },
)

print(trace.trace_id, len(trace.receipts))  # 3

Receipt Mode

Mode Seals
final_decision_only (default of sign()) Only the final agent output.
every_tool_call One receipt per tool invocation.
every_agent_step One receipt per agent reasoning step.
custom You pick step_type per call.

Decision Boundary Disclosure (DBD)

Declare what your system evaluated and what it excluded — backed by versioned sector schemas. Silent omission is structurally impossible: every domain in the schema must be classified.

result = client.sign(
    decision={"type": "collision_assessment", "input": raw_in, "output": raw_out, "risk_level": "high"},
    scope_declaration={
        "sector_schema_id": "automotive_collision.v1",
        "domains_evaluated": [
            {"domain_id": "physics_impact_force", "status": "computed"},
            {"domain_id": "vehicle_structural_integrity", "status": "computed"},
        ],
        "domains_excluded": [
            {"domain_id": "occupant_biological_impact",
             "reason": "no_data_source_available", "excluded_by": "data_gap"},
            {"domain_id": "pedestrian_third_party_impact",
             "reason": "not_in_scope_of_this_module", "excluded_by": "design"},
            # ...all remaining domains
        ],
    },
)

DBD requires that every domain defined by the referenced sector schema appears in either domains_evaluated or domains_excluded — silent omission is rejected by the server.

Upgrading from earlier versions

Every field introduced in the SDK is additive and optional. Upgrading does not change the shape of receipts you have already sealed and it does not change any existing method signature.

  • human_reviewer, human_reviewer_attestation, ReceiptReferenceStore — new, opt-in.
  • decision["human_review_attestation_hash"] — optional field on the receipt body. None / missing values are dropped by canonicalisation, so a receipt sealed before this SDK version produces the exact same canonical bytes today as it did then. All historical receipts continue to verify unchanged.
  • trace and DBD (scope_declaration) remain unchanged; existing workflows keep working.

If a call site does not pass human_reviewer or scope_declaration, the SDK behaves exactly as in previous versions.

Missing something? Ask us to build it

If your stack, framework, or workflow needs an integration that isn't shipped yet — a specific SDK, a hosted connector, a native adapter for your platform, or a custom field mapping — send the details to partners@signatrust.net. We'll ship what you need.

Please include:

  • The runtime or framework (Node/Python/Go/Rust/Java/.NET, LangChain, LlamaIndex, CrewAI, n8n, Zapier, Make, …).
  • The subject records you'd want to bind receipts to (patient, applicant, claim, transaction, work-order, …).
  • Any human-review workflow (who signs off, what specialty, whether attestation must be verifiable later).
  • Whether you need on-prem, hybrid, or self-hosted verification tooling.

License

Apache-2.0

Download files

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

Source Distribution

signatrust-1.3.1.tar.gz (12.8 kB view details)

Uploaded Source

Built Distribution

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

signatrust-1.3.1-py3-none-any.whl (11.8 kB view details)

Uploaded Python 3

File details

Details for the file signatrust-1.3.1.tar.gz.

File metadata

  • Download URL: signatrust-1.3.1.tar.gz
  • Upload date:
  • Size: 12.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for signatrust-1.3.1.tar.gz
Algorithm Hash digest
SHA256 6eb06b892f60df18ace5c3fb2c56a9620acb173d5bcee8de22f6e53803e9a2b5
MD5 4572320fc8bab7d42f20bfe43c833853
BLAKE2b-256 12ea41e178cdbdc839156c8dea2f2433d653a5103b0c7633394a9791a1fefd31

See more details on using hashes here.

File details

Details for the file signatrust-1.3.1-py3-none-any.whl.

File metadata

  • Download URL: signatrust-1.3.1-py3-none-any.whl
  • Upload date:
  • Size: 11.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for signatrust-1.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b7354870ec16f83fd909de98402182d3d39d8dec49dc999a91c7d9e2cf495b9a
MD5 1401d2189dfa60f05ab403c1038c12a6
BLAKE2b-256 9cb93f88223b19bcc7dc8a5bc818a828585c7c0796b87db7c1c5ceae65942e55

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.3.1 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page