SDK Documentation
A Python package that wraps the Intent API, so integrating an agent never means hand-implementing ED25519 signing, certificate headers, or retry logic.
The PayReality SDK (payreality-python) is a client, not a platform change: it consumes the same /v1/principals, /v1/agents, /v1/intents, and /v1/decisions endpoints that exist on the API today. Nothing about the Runtime Authority Engine, the Compiler, OPA, or Evidence changes because the SDK exists; it just removes the parts a developer shouldn't have to hand-roll.
Install and register an agent
from payreality import Agent
agent = Agent(api_key="your-operator-key")
identity = agent.register(name="AP Automation Agent", principal="Finance Manager")
print(identity.agent_id) # server-assigned, never hand-picked
print(identity.certificate_id) # the certificate this agent signs withregister() generates an ED25519 key pair locally, uploads only the public key, and returns a ready-to-use identity in one call. Registration is idempotent per key: calling register() again with the same private key returns the cached identity instead of creating a duplicate agent, which makes it safe to call on every process start rather than something you need to guard yourself.
Submitting an action
decision = agent.authorize(
resource="Vendor Payment",
amount=8500,
currency="USD",
vendor="Acme Supplies",
)
if decision.outcome == "ALLOW":
... # proceed
elif decision.outcome == "HUMAN_REVIEW":
... # a person will resolve this in the Review Queueauthorize() signs the request with the agent's own certificate, exactly like every signed Intent the API accepts. There are exactly three outcomes: ALLOW, DENY, or HUMAN_REVIEW. An action the platform doesn't recognize is never silently allowed: it's escalated to a human, the same fail-closed behavior the Decision Engine applies everywhere.
What api_key actually authenticates
Agent(api_key=...) is the Operator Key: the same administrative credential every other mutating action on this platform uses (see Authentication). It's required for register(), rotate_keys(), and retire(), since creating, rotating, or retiring an agent identity is an administrative action. It is not required for authorize() or heartbeat(), which authenticate purely via the agent's own certificate signature, the same way a human employee's badge doesn't require their manager's key to walk through a door they're already authorized for.
Why the SDK is synchronous
agent.authorize(...) is called directly, no await. This matches the default surface most developers already expect from a first SDK release (Stripe, OpenAI, and Supabase all ship synchronous clients as their default), keeping the initial surface area matched to what most integrations actually need. An async client is a natural, additive future addition, not a redesign.
Retries and error handling
Connection failures, timeouts, and 5xx responses are retried automatically with capped exponential backoff. 401, 403, and any other 4xx (including 422 validation failures) are never retried, since none of these can succeed by trying again unmodified. Every failure, network or HTTP, is mapped onto a typed exception before it reaches your code: you never see a raw HTTP client exception or a bare status code.
For the full lifecycle methods (rotating keys, heartbeats, retiring an agent), see Integration Examples.