Skip to main content

Kora Python SDK

Python SDK for the Kora authorization engine. Handles Ed25519 signing, nonce generation, canonical JSON serialization, idempotent retry, and offline seal verification.

Installation

pip install kora-sdk

Or install from source:

pip install -e sdk/python

Requirements: Python 3.9+, PyNaCl >= 1.5.0, requests >= 2.28.0

Quick Start

from kora import Kora

# Initialize with the secret key returned from agent creation
kora = Kora("kora_agent_sk_...")

# Authorize a spend
auth = kora.authorize(
    mandate="mandate_abc123",
    amount=50_00,        # EUR 50.00
    currency="EUR",
    vendor="aws",
    category="compute",  # required if mandate has category_allowlist
)

if auth.approved:
    print(f"Approved: {auth.decision_id}")
    print(f"Daily remaining: {auth.limits_after_approval['daily_remaining_cents']}")
else:
    print(f"Denied: {auth.reason_code}")
    print(f"Hint: {auth.denial.hint}")

Usage

Authorize a Spend

from kora import Kora

kora = Kora(
    "kora_agent_sk_...",
    base_url="http://localhost:8000",  # default
    ttl=300,          # default TTL in seconds
    max_retries=2,    # automatic idempotent retry on network error
)

result = kora.authorize(
    mandate="mandate_abc123",
    amount=50_00,
    currency="EUR",
    vendor="aws",
    category="compute",
)

Result Properties

result.approved        # bool — True if APPROVED
result.decision        # "APPROVED" or "DENIED"
result.decision_id     # UUID of the authorization decision
result.reason_code     # "OK", "DAILY_LIMIT_EXCEEDED", etc.
result.executable      # bool — True if payment can be executed
result.is_valid        # bool — True if TTL has not expired
result.is_enforced     # bool — True if enforcement_mode == "enforce"
result.enforcement_mode  # "enforce" or "log_only"

# On denial:
result.denial.hint            # Human-readable suggestion
result.denial.actionable      # Machine-readable corrective values
result.denial.failed_check    # Which pipeline step failed

# On approval:
result.limits_after_approval  # Remaining daily/monthly budget

# Evaluation trace:
result.evaluation_trace.steps        # List of pipeline step results
result.evaluation_trace.total_duration_ms  # Total evaluation time

# Notary seal:
result.notary_seal.signature    # Ed25519 signature (base64)
result.notary_seal.public_key_id
result.notary_seal.algorithm    # "Ed25519"

# Trace URL (for debugging denials):
result.trace_url  # e.g. http://localhost:8000/v1/authorizations/<id>/trace

Handle Denials

result = kora.authorize(
    mandate="mandate_abc123",
    amount=999_99,
    currency="EUR",
    vendor="aws",
)

if not result.approved:
    print(f"Denied: {result.reason_code}")
    print(f"Hint: {result.denial.hint}")

    # Machine-readable corrective values
    if result.reason_code == "DAILY_LIMIT_EXCEEDED":
        available = result.denial.actionable["available_cents"]
        print(f"Available budget: {available} cents")

    if result.reason_code == "VENDOR_NOT_ALLOWED":
        allowed = result.denial.actionable["allowed_vendors"]
        print(f"Allowed vendors: {allowed}")

    # Full trace URL for debugging
    print(f"Trace: {result.trace_url}")

Verify Notary Seal (Offline)

from base64 import b64decode

# Kora's public key (from your deployment)
kora_public_key = b64decode("...")

is_valid = kora.verify_seal(result, kora_public_key)
print(f"Seal valid: {is_valid}")

Simulation Mode

Test denial scenarios without affecting state. Requires an admin key with simulation_access=true.

result = kora.authorize(
    mandate="mandate_abc123",
    amount=100,
    currency="EUR",
    vendor="aws",
    simulate="DAILY_LIMIT_EXCEEDED",
    admin_key="kora_admin_...",
)

assert result.simulated is True
assert result.decision == "DENIED"
assert result.reason_code == "DAILY_LIMIT_EXCEEDED"
assert result.notary_seal is None  # no seal in simulation

OpenAI Function Tool Schema

Generate an OpenAI-compatible function tool definition for use with LLM agents:

tool = kora.as_tool("mandate_abc123")
# Returns:
# {
#     "type": "function",
#     "function": {
#         "name": "kora_authorize_spend",
#         "description": "Authorize a spend against a Kora mandate...",
#         "parameters": {
#             "type": "object",
#             "properties": {
#                 "amount_cents": {"type": "integer", "description": "..."},
#                 "currency": {"type": "string", "description": "..."},
#                 "vendor_id": {"type": "string", "description": "..."},
#             },
#             "required": ["amount_cents", "currency", "vendor_id"]
#         }
#     }
# }

# With category enum constraint:
tool = kora.as_tool("mandate_abc123", category_enum=["compute", "api_services"])

Use with OpenAI:

import openai

client = openai.OpenAI()
response = client.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "Buy $50 of AWS compute"}],
    tools=[kora.as_tool("mandate_abc123")],
)

Agent Self-Correction Pattern

from kora import Kora

kora = Kora("kora_agent_sk_...")

# First attempt — too large
auth = kora.authorize(mandate="mandate_abc123", amount=999_99, currency="EUR", vendor="aws")

if not auth.approved and auth.reason_code == "DAILY_LIMIT_EXCEEDED":
    # Read the actionable hint
    available = auth.denial.actionable["available_cents"]
    print(f"Budget available: {available} cents, retrying...")

    # Retry with corrected amount
    auth = kora.authorize(mandate="mandate_abc123", amount=available, currency="EUR", vendor="aws")
    print(f"Second attempt: {auth.decision}")  # APPROVED

API Reference

Kora(key_string, base_url=None, ttl=300, max_retries=2)

Parameter Type Default Description
key_string str required Agent secret key (kora_agent_sk_...)
base_url str http://localhost:8000 Kora API base URL
ttl int 300 Default TTL for decisions (seconds)
max_retries int 2 Automatic retries on network error

kora.authorize(**kwargs) -> AuthorizationResult

Parameter Type Required Description
mandate str yes Mandate ID
amount int yes Amount in cents
currency str yes 3-letter currency code
vendor str yes Vendor identifier
category str no Spending category
simulate str no Force denial reason code (simulation mode)
admin_key str no Admin key for simulation access

kora.verify_seal(result, public_key) -> bool

Verify the Ed25519 notary seal offline.

kora.as_tool(mandate, category_enum=None) -> dict

Generate OpenAI function tool schema.

Metadata

Release files for kora-sdk 1.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kora-sdk 1.3.0
File Size Uploaded
kora_sdk-1.3.0.tar.gz 28.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for kora-sdk 1.3.0
File Interpreter ABI Platform
kora_sdk-1.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 48.8 kB

Release files / kora_sdk-1.3.0.tar.gz

Download URL kora_sdk-1.3.0.tar.gz
Size 28.4 kB
Tags Source
SHA-256 checksum
How to use checksums
2f280c2a474c97e5b7fc17294eeba6c6791d865655691253d7df60108dd4b4f3
BLAKE2b-256 checksum
How to use checksums
b87a56da736dd7b6f657d4d9183a0830dc53d66661bd1618488189384ea6dc0f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.1

Release files / kora_sdk-1.3.0-py3-none-any.whl

Download URL kora_sdk-1.3.0-py3-none-any.whl
Size 20.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4eebaa77cb2c7f11c76ad45a89b598daa89222fe3f35f3a139290e13082010d4
BLAKE2b-256 checksum
How to use checksums
d3eadb8149d26c15337502a6e1539bf7fbc2cf8bf1ab7aacd2ecdae073b70519
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.1

Release history Release notifications | RSS feed

This release

1.3.0 This release

2 release files

1.2.0

2 release files

1.1.0

2 release 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