attestify-sdk — Python
Add governed lane execution to any Python codebase in a few lines.
Install
pip install attestify-sdk
Or directly from the repo while the package is in early access:
pip install "git+https://github.com/attestifyagent/attestify-os.git#subdirectory=sdk/python"
Quick start
import os
from attestify import create_client
client = create_client(api_key=os.environ["ATTESTIFY_API_KEY"])
result = client.run_lane(
input="Summarise the latest advances in quantum error correction.",
lane_id="researcher-v2",
session_id="my-session-001",
options={"verify": True, "write_memory": True},
)
print(result.output) # lane response text
print(result.receipt.run_id) # unique run identifier
print(result.receipt.evidence) # full EvidenceBundle dataclass
print(result.receipt.pricing) # cost breakdown
Features
create_client(api_key)— configure once, use anywhereclient.run_lane(input, ...)— single call handles sessions, retries, idempotency- Typed receipts —
RunReceiptandEvidenceBundledataclasses with full field coverage - Auto-routing — omit
lane_idand Attestify picks the best lane for the task - Idempotency — pass
idempotency_keyto guarantee exactly-once execution - Budget controls — pass
constraints={"max_cost_usdc": 0.05}to cap spend per run - Webhook support — pass
options={"webhook_url": "..."}for async delivery - Zero dependencies — stdlib only (
urllib,json,uuid) for everything above; Attestify Trust's local signing needs the optionaltrustextra (see below)
API Reference
create_client(api_key, base_url?, max_retries?, timeout_s?)
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key |
str |
required | Your Attestify API key (ATTESTIFY_API_KEY) |
base_url |
str |
https://attestifyos.com |
Override the endpoint |
max_retries |
int |
2 |
Retries on transient 5xx errors |
timeout_s |
float |
60.0 |
Per-attempt timeout in seconds |
client.run_lane(input, ...)
| Parameter | Type | Description |
|---|---|---|
input |
str |
Required. The task or intent |
lane_id |
str |
Optional — omit to auto-route |
session_id |
str |
Memory / conversation continuity ID |
idempotency_key |
str |
Prevents duplicate charges for the same key |
context |
dict |
Freeform context forwarded to the lane |
constraints |
dict |
Budget / SLA constraints (see below) |
options |
dict |
Runtime flags (see below) |
Returns RunLaneResult(output, receipt, raw).
constraints fields:
constraints={
"max_cost_usdc": 0.05, # abort if estimated cost exceeds this
"max_latency_ms": 10000, # abort if estimated latency exceeds this
"budget_id": "proj-abc", # link to a named budget envelope
}
options fields:
options={
"verify": True, # run output verification (default False)
"write_memory": True, # persist session memory (default False)
"include_memory": True, # inject prior memory into context
"webhook_url": "https://...", # async result delivery
}
client.authorize(...) — authority envelopes
Request a signed, server-enforced authority envelope before running one or more
governed actions. run_lane(envelope=...) attaches it; /api/run verifies the
signature, tenant/agent binding, expiry, live-policy epoch, and remaining
action count / spend cap before every run, and atomically consumes one action.
envelope = client.authorize(
agent_id="analyst-v1",
intent="batch-report-generation",
risk_class="low",
max_spend_usd=0.50,
action_count=20, # this envelope authorises up to 20 actions
expiry_window_s=300, # capped at 3600s server-side
)
result = client.run_lane(
lane_id="analyst-v1",
input="Summarise Q2 revenue trends.",
envelope=envelope,
)
The client caches non-Enterprise envelopes locally and reuses them until the
action count or expiry window is exhausted. If the agent's policy has
per_action_mode enabled, the server forces action_count=1 and
expiry_window_s=0 and the SDK never caches the result — every action gets a
fresh envelope. A stale envelope (policy changed since issue) is rejected with
HTTP 409; call authorize() again to obtain a fresh one.
client.get_receipt(loop_id)
Fetch a stored receipt by its loop_id.
receipt = client.get_receipt("loop_abc123")
print(receipt.verification) # grade, score, output_hash
print(receipt.settlement) # on-chain tx hash if x402 used
Returns RunReceipt.
Attestify Trust — no wallet, ever
Prove what a wallet-free agent did. client.trust is a completely separate
surface from everything above — no lanes, no x402, no gas, at any point.
The private signing key never leaves your process; only a public key and
signatures are ever sent to Attestify.
Needs the trust extra, since real Ed25519 signing isn't in Python's
standard library the way it is in Node's built-in node:crypto:
pip install "attestify-sdk[trust]"
import os
from attestify import create_client
attestify = create_client(api_key=os.environ["ATTESTIFY_API_KEY"])
# 1. Generate a keypair once, store the private key yourself (env var,
# secrets manager — the same way you'd hold any other API secret).
keypair = attestify.trust.generate_key_pair()
# 2. Register the agent and its key.
agent = attestify.trust.create_agent(display_name="Invoice Bot")
attestify.trust.register_key(agent.id, keypair.public_key)
# 3. Sign and submit evidence for real work the agent did.
receipt = attestify.trust.submit_evidence(
agent_id=agent.id,
schema="work-completion/v1",
payload={"summary": "Extracted 3 line items from a sample invoice"},
private_key=keypair.private_key,
action_basis="discretionary", # did this on its own initiative, not because it was told to
)
# 4. Anyone can verify it — no API key required.
result = attestify.trust.verify(receipt.id)
print(result.integrity_verified) # True
client.trust.generate_key_pair()
Generates a local Ed25519 keypair. No network call. Returns a
TrustKeyPair(public_key, private_key), both base64url-encoded.
client.trust.create_agent(display_name=None, framework=None, industry=None, country=None)
| Parameter | Type | Description |
|---|---|---|
display_name |
str |
Optional, private — never shown to a verifier |
framework |
str |
e.g. "langchain", "crewai" |
industry |
str |
Self-reported |
country |
str |
Self-reported |
Returns TrustAgent.
client.trust.register_key(agent_id, public_key)
Registers (or rotates) the Ed25519 signing key for an agent. Returns TrustKeyVersion.
client.trust.submit_evidence(agent_id, schema, payload, private_key, action_basis="explicit", nonce=None)
| Parameter | Type | Description |
|---|---|---|
agent_id |
str |
Required |
schema |
str |
Required — e.g. "work-completion/v1" |
payload |
dict |
Required — bounded to 16KB |
private_key |
str |
Required — from generate_key_pair() |
action_basis |
"explicit" | "discretionary" |
Default "explicit" |
nonce |
str |
Default: a random value — override only for a specific replay-defence need |
Canonicalizes and signs the event locally with private_key, then submits
it. Returns TrustReceipt — an immutable, signed record with a content
hash, not the raw evidence.
client.trust.verify(receipt_id)
Public, no API key sent. Independently recomputes the receipt's hash and
re-verifies the signature server-side on every call — not just an echo of
what's stored. Returns TrustVerifyResult(receipt, integrity_verified).
client.trust.get_receipt(receipt_id)
Your own tenant's full receipt detail (requires the API key that created
it). Use verify() instead for the public, redacted view anyone can check.
RunReceipt fields
| Field | Type | Description |
|---|---|---|
run_id |
str |
Unique run identifier |
loop_id |
str |
Persistent loop/session receipt ID |
lane_id |
str |
Lane that handled the run |
lane_name |
str |
Human-readable lane name |
output |
str |
Lane response text |
paid |
bool |
Whether x402 payment was used |
subscription_used |
bool |
Whether an API key subscription covered this run |
evidence |
EvidenceBundle |
Full governance evidence bundle |
verification |
dict | None |
Verification grade, score, output hash |
pricing |
dict |
Cost breakdown in USDC |
settlement |
dict | None |
On-chain settlement details |
receipt_url |
str |
Shareable receipt permalink |
Available lanes
lane_id |
Description |
|---|---|
researcher-v2 |
Deep research and synthesis |
analyst-v1 |
Data analysis and structured output |
coder-v1 |
Code generation and review |
writer-v1 |
Long-form and structured writing |
strategist-v1 |
Strategic planning and frameworks |
support-v1 |
Customer support and triage |
comedian-v1 |
Creative and entertainment tasks |
Omit lane_id entirely to let Attestify auto-route based on your input.
Environment variables
ATTESTIFY_API_KEY=atst_live_...
Async usage
The client is synchronous by design (zero dependencies). For async workflows:
import asyncio
from attestify import create_client
client = create_client(api_key=os.environ["ATTESTIFY_API_KEY"])
async def main():
result = await asyncio.to_thread(
client.run_lane,
input="Analyse Q2 revenue trends",
lane_id="analyst-v1",
)
print(result.output)
asyncio.run(main())
Metadata
Release files for attestify-sdk 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| attestify_sdk-0.2.0.tar.gz | 24.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| attestify_sdk-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 43.7 kB
Release files / attestify_sdk-0.2.0.tar.gz
| Download URL | attestify_sdk-0.2.0.tar.gz |
|---|---|
| Size | 24.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
141013f173a7016b53fbb4ac3334105c96f8732a71a4f2c53b8f7553273476be
|
|
BLAKE2b-256 checksum How to use checksums |
d0e03fb4290081f3ae6d23a62f974f294549f37ed4e85d9c1447b5d5bb194a31
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / attestify_sdk-0.2.0-py3-none-any.whl
| Download URL | attestify_sdk-0.2.0-py3-none-any.whl |
|---|---|
| Size | 19.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a2919d087e480cd3714146e44dd3e65949d354ef1ba660f413ed609f2087bff8
|
|
BLAKE2b-256 checksum How to use checksums |
56214a68ccac5cfeff8aa47aa7c62520147e9e5a9a5e85f21f54e11ff7251af1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|