Python SDK for Verity — exactly-once effect protection for AI agents and autonomous systems
Project description
verity-sdk (Python)
Exactly-once effect protection for AI agents and autonomous systems.
The Python SDK for Verity — ensures real-world actions like payments, refunds, emails, and infrastructure provisioning happen exactly once, are safe to retry, and are fully auditable.
pip install verityinc-sdk
Quick Start
from verity import VerityClient
verity = VerityClient(
base_url="https://api.useverity.io/v1",
api_key="vk_live_xxxxxx",
namespace="payments",
)
# Protect a side effect — Verity guarantees it runs exactly once
charge = await verity.protect("charge-order-456", {
"act": lambda: stripe.Charge.create(amount=5000, currency="usd"),
})
If an agent crashes mid-flight, the next attempt either returns the cached result (if already committed) or uses observe() to detect the completed action in the external system — preventing duplicate charges.
With Crash Recovery (Observe)
charge = await verity.protect("charge-order-789", {
"observe": async_check_stripe,
"act": async_create_charge,
})
async def async_check_stripe():
"""Check if a prior agent already completed this charge."""
existing = stripe.Charge.list(metadata={"order_id": "789"})
return existing.data[0] if existing.data else None
async def async_create_charge():
return stripe.Charge.create(
amount=5000,
currency="usd",
metadata={"order_id": "789"},
)
Workflow Mode (Multi-Effect)
run = verity.workflow("refund_flow").case("order_123").run()
# effectKey = "order_123:notify_customer"
await run.protect("notify_customer", {
"act": lambda: email_service.send(to=customer.email, template="refund"),
})
# effectKey = "order_123:refund_payment"
await run.protect("refund_payment", {
"act": lambda: stripe.Refund.create(charge=charge_id),
})
If a crash occurs between steps, the retry run skips already-committed effects and resumes from where it left off.
Configuration
from verity import VerityClient
verity = VerityClient(
# Required
base_url="https://api.useverity.io/v1",
api_key="vk_live_xxxxxx",
# Optional
namespace="payments", # default namespace
agent_id="worker-1", # identifies this agent in audit logs
auto_renew=True, # auto-renew leases in background
renew_at_fraction=0.65, # renew at 65% of lease duration
request_timeout_ms=20_000, # HTTP timeout per request
# Conflict retry (when another agent holds the lease)
conflict_retry={
"enabled": True,
"max_attempts": 12,
"initial_delay_ms": 500,
"max_delay_ms": 15_000,
"jitter": True,
},
# Custom logger
logger=my_logger, # any logging.Logger instance
)
Error Handling
from verity import VerityClient
from verity.errors import (
CommitUncertainError,
LeaseConflictError,
EffectPreviouslyFailedError,
)
try:
await verity.protect("charge-order-456", {"act": charge})
except CommitUncertainError as e:
# Action SUCCEEDED but Verity couldn't confirm the commit.
# DO NOT RETRY — halt and reconcile manually.
print(f"Action ran but commit uncertain: {e.result}")
await alert_ops(e)
except LeaseConflictError:
# Another agent is processing this effect
print("Effect is being handled by another agent")
except EffectPreviouslyFailedError as e:
# Prior failure — admin reset required via Explorer
print(f"Prior failure: {e.cached_error}")
How It Works
Every call to protect() follows the lease → observe → act → commit protocol:
- Lease — acquire exclusive, time-bound access to the effect
- Observe (optional) — check the external system for a prior completion
- Act — execute the real-world side effect
- Commit — record the result in Verity's ledger
Agent A Verity Stripe
│ │ │
├── request_lease ──────────────►│ │
│◄── granted (fence_token: 1) ──┤ │
│ │ │
├── stripe.Charge.create ────────────────────────────────────────►
│◄── { id: "ch_xxx" } ──────────────────────────────────────────┤
│ │ │
├── commit(result) ─────────────►│ │
│◄── accepted ──────────────────┤ │
Parity with TypeScript SDK
This SDK provides full feature parity with the TypeScript SDK:
| Feature | TypeScript | Python |
|---|---|---|
protect() standalone |
verity.protect() |
await verity.protect() |
| Workflow builder | verity.workflow().case().run() |
verity.workflow().case().run() |
| Auto lease renewal | setInterval + unref() |
asyncio.create_task() |
| Conflict retry with backoff | ✅ | ✅ |
| Observe/Act pattern | ✅ | ✅ |
| Fence token validation | ✅ | ✅ |
| CommitUncertainError | ✅ | ✅ |
| Per-effect namespace | ✅ | ✅ |
| Key suffix | ✅ | ✅ |
| Custom logger | logger: { warn, error } |
logger: logging.Logger |
| Typed request bodies | Exported types | @dataclass exports |
Requirements
- Python >= 3.10
- httpx >= 0.27
- Zero other runtime dependencies
Development
# Install with dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Type check
mypy src/
# Lint
ruff check src/
License
Proprietary — Verity Systems, Inc.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file verityinc_sdk-0.1.1.tar.gz.
File metadata
- Download URL: verityinc_sdk-0.1.1.tar.gz
- Upload date:
- Size: 18.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ce0d37edf78afc9e2fa1c95345141104547e73b3a73787e4f8c48cfe75fa0995
|
|
| MD5 |
dce93e167726be33fb36afaf44a182fc
|
|
| BLAKE2b-256 |
5a26f0e85c4cbeb6399618f54c6c47f0e98d3bbd8ee2a5b8b1bd0ca01a806dba
|
File details
Details for the file verityinc_sdk-0.1.1-py3-none-any.whl.
File metadata
- Download URL: verityinc_sdk-0.1.1-py3-none-any.whl
- Upload date:
- Size: 16.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
93ca1d80a9fdb8c36f65a65b9cf7485ad9885cffb1d253bcde6d1a44dde4120d
|
|
| MD5 |
141e96bf7750b1844f0d448fb38246bc
|
|
| BLAKE2b-256 |
a475968c91d90746076ac9992bfd67e3a1a7ce24abc3a277d94a4f3f66abb730
|