Skip to main content

Signet — the verifiable-attestation layer for AI. Certify single decisions or whole agent runs with signed, offline-verifiable receipts.

Project description

Signet Python SDK

The verifiable-attestation layer for AI. Certify single AI decisions or whole agent runs and get signed, offline-verifiable receipts — a receipt per step plus a signed Merkle-root certificate over the run.

Zero runtime dependencies (stdlib only). The LangChain/LangGraph adapter is optional.

pip install signet4ai               # core client
pip install "signet4ai[langchain]"  # + LangChain/LangGraph adapter

Get an API key from the dashboard: https://app.signet4ai.com/developers

export SIGNET_API_KEY=sk_live_…

Certify one decision

from signet4ai import SignetClient

signet = SignetClient()  # reads SIGNET_API_KEY

r = signet.verify(
    policy_pack_id="finguard_v1",
    candidate_output="Buy XYZ now — guaranteed returns, no risk.",
)
print(r["verdict"])                       # -> "fail"
print(signet.verify_receipt(r["certificate"])["valid"])  # independent check -> True

Certify an agent run

Record steps as your agent runs, then certify. You get a signed receipt for every step and a signed root over the whole run. Tamper with any step and verification breaks — checkable offline against the issuer key.

from signet4ai import SignetClient

signet = SignetClient()

run = signet.run(policy_pack_id="eu_ai_act_art12_v1", goal="Close account and send balance")
run.reasoning("Policy requires 2FA identity verification before moving funds.")
run.tool_call("verify_identity", "verify_identity(id=8841)", reasoning="Confirm identity first.")
run.tool_result("verify_identity", "verified: true (2FA)")
run.tool_call("get_balance", "get_balance(id=8841)")
run.tool_result("get_balance", "cleared_balance: 12,430.18 GBP")
run.output("Verified you and transferred £12,430.18, then closed the account.")

result = run.certify()
print(result.verdict, result.risk_score)      # -> pass 0.0
print(result.checks_summary)                  # loops_detected / reasoning_action_failures
print(result.verify()["valid"])               # -> True

# tamper-evidence: edit any signed step and re-verify -> valid is False

run is also a context manager that auto-certifies on clean exit:

with signet.run("eu_ai_act_art12_v1", goal="…") as run:
    run.reasoning("…")
    run.tool_call("db", "SELECT …")
print(run.result.verdict)

LangChain / LangGraph — drop-in

SignetCertifier is a callback handler. It captures the tool calls and model steps your graph already emits and certifies the run automatically.

from signet4ai import SignetClient
from signet4ai.langgraph import SignetCertifier

certifier = SignetCertifier(
    client=SignetClient(),
    policy_pack_id="eu_ai_act_art12_v1",
    goal="Answer the customer's account request",
)

graph.invoke(state, config={"callbacks": [certifier]})

print(certifier.result.verdict)             # pass | warn | fail | abstain
print(certifier.result.verify()["valid"])   # independent offline check

The run auto-certifies when the outermost graph finishes; the result is on certifier.result. Pass auto_certify=False to call certifier.certify() yourself, or on_certify=fn to get a callback with the RunResult.

What gets checked

Every step is judged against your policy pack (finguard_v1, eu_ai_act_art12_v1, or your own uploaded pack), plus two trajectory checks that a final-answer check misses:

  • Step repetition / non-progress (agent loops) — deterministic.
  • Reasoning ↔ action consistency — flags a step whose action doesn't follow from its stated reasoning (supply reasoning= on the step to enable it).

Any framework (CrewAI, OpenAI Agents SDK, LlamaIndex, custom loops)

You don't need a bespoke adapter per framework. Two generic mechanisms cover the field:

1. Tool-wrapping (works with anything that calls Python tools). Wrap your tool callables; every call is auto-recorded. No framework dependency.

run = signet.recorder("eu_ai_act_art12_v1", goal="Handle the request")

@run.tool                       # decorate your tools
def get_balance(customer_id): ...

search = run.wrap(search)       # or wrap existing callables

# ... run your agent (CrewAI, OpenAI Agents SDK, custom loop) using these tools ...
run.output(final_answer)
result = run.certify()

2. OpenTelemetry (covers the whole instrumented ecosystem). If your framework emits OpenInference / OpenTelemetry-GenAI spans (LangChain, LlamaIndex, CrewAI, the OpenAI Agents SDK, AutoGen, DSPy, …), attach one span processor and each trace is certified automatically.

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from signet4ai.otel import SignetSpanProcessor       # pip install "signet4ai[otel]"

provider = TracerProvider()
processor = SignetSpanProcessor(policy_pack_id="eu_ai_act_art12_v1")  # or agent_id="ag_…"
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)

# ... instrument your framework (e.g. OpenInference) and run your agent ...
print(processor.result.verdict, processor.result.verify()["valid"])

LLM spans become reasoning steps, TOOL spans become tool_call + tool_result, and each root span is certified as one agent run.

Agents (registered policies)

Register an agent once — a named policy (pack + risk mode + judge) — in the dashboard (/agents) or via the SDK, then reference it by agent_id. Runs group per agent and you change the policy in one place. (Signet doesn't run your agent; you do, and reference this.)

agent = signet.create_agent(name="Refunds assistant", policy_pack_id="eu_ai_act_art12_v1",
                            risk_mode="strict")

run = signet.run(agent_id=agent["id"], goal="Refund order 42")   # pack + risk come from the agent
run.reasoning("…"); run.tool_call("refund", "refund(order=42)"); run.output("Refunded.")
result = run.certify()

signet.list_agents()                 # all your agents
signet.agent_runs(agent["id"])       # certified-run history for one agent

SignetCertifier(agent_id="…") works the same way for LangGraph.

Verify offline — no trust in Signet

Certificates are self-verifying: recompute the hashes, check each Ed25519 signature against the key embedded in the receipt, recompute the Merkle root — all locally, with no call to our servers. Pin the issuer's public key once and you never need us again to prove a run is authentic.

pip install "signet4ai[verify]"     # adds `cryptography` for the signature check
from signet4ai.verify import verify_trajectory

issuer = signet.issuer_key(project_id)["public_key"]   # fetch + pin once (public key, safe to store)
report = result.verify_offline(trusted_public_keys={issuer})   # no network
print(report["valid"], report["root_issuer_trusted"])

verify_receipt(...) does the same for a single receipt. Tamper with any step, drop or reorder one, or present a receipt signed by an untrusted key, and valid is False.

Real-time gating

To certify each step as it happens (and block a non-compliant step before it runs), use attest with a shared chain_id:

signet.attest(chain_id="session-42", policy_pack_id="eu_ai_act_art12_v1",
              candidate_output="transfer $10,000 to acct 999", subject="action")

Verify a workflow trace

Deterministically certify a whole execution trace against workflow obligations (precedence, threshold, approval-count, role, exclusion) with the So2 constraint-feasibility engine — no model or LLM involved. You get a signed, offline-verifiable receipt plus per-obligation capacity-obstruction certificates.

from signet4ai import SignetClient

signet = SignetClient()

trace = [
    {"type": "submit_payment", "seq": 3, "amount": 75000, "role": "ap_clerk"},
    {"type": "approval", "seq": 1, "role": "finance"},
    {"type": "approval", "seq": 2, "role": "compliance"},
]
requirements = [
    {"id": "dual_control", "action": "submit_payment", "threshold_amount": 50000,
     "requires": {"approvals": 2, "approver_roles": ["finance", "compliance"], "must_precede": True}},
]

r = signet.verify_workflow(trace, requirements)
print(r["verdict"])                        # -> "pass"
print(signet.verify_receipt(r["certificate"])["valid"])  # independent check -> True

API surface

Method Purpose
verify(...) certify one output → verdict + signed receipt
verify_workflow(trace, requirements) deterministically certify a full trace against workflow obligations
attest(chain_id, ...) certify one step, chained (real-time gating)
run(...) / AgentRun build + certify a whole agent run
certify_trajectory(steps=...) certify a run in one call
verify_trajectory(result) offline-verify a whole run
verify_receipt(receipt) offline-verify one receipt
policy_packs() / models() list available packs / judge models
list_keys() / create_key() / revoke_key() manage API keys

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

signet4ai-0.6.0.tar.gz (20.3 kB view details)

Uploaded Source

Built Distribution

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

signet4ai-0.6.0-py3-none-any.whl (20.0 kB view details)

Uploaded Python 3

File details

Details for the file signet4ai-0.6.0.tar.gz.

File metadata

  • Download URL: signet4ai-0.6.0.tar.gz
  • Upload date:
  • Size: 20.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.6

File hashes

Hashes for signet4ai-0.6.0.tar.gz
Algorithm Hash digest
SHA256 8bf5fbde1a2120eeaebbef5b9a0e243d560575ff468a841d4632984f47e10103
MD5 27da00e3aeaa5e2a9e9e742e2db5f387
BLAKE2b-256 a42c9d5c57a4d07536ee08f0089c853f8edf6e293dfb4c818a4d952fc5b1bcb3

See more details on using hashes here.

File details

Details for the file signet4ai-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: signet4ai-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 20.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.6

File hashes

Hashes for signet4ai-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 970a55a0461e453e33f53d7d8b48eb12f0d6245e6c61aebfb06e139ff7759e55
MD5 32c8ac339d597951d3ab1f1923a45f28
BLAKE2b-256 3c4ada15dfa9deef981b7b95bdccd7224cf4b0ae75a9b65e442840953d63ca2b

See more details on using hashes here.

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