Send Your First AI Agent Payment in 5 Minutes

This guide walks you through the complete Oris integration: registering an autonomous agent, creating a compliant wallet, attaching spending controls, and executing a gas-abstracted on-chain payment. Every step includes working code.

Prerequisites

Step 1: Install the SDK

pip install oris-sdk

For development against the latest source:

git clone https://github.com/oris-finance/oris-sdk-python.git
cd oris-sdk-python
pip install -e .

Step 2: Initialize the Client

from oris import OrisClient

client = OrisClient(
    api_key="oris_sk_live_your_key_here",
    api_secret="oris_ss_live_your_secret_here",
)

The SDK handles HMAC-SHA256 request signing, replay protection, and retry logic automatically. You never touch cryptographic headers directly.

You can also set credentials via environment variables:

export ORIS_API_KEY="oris_sk_live_..."
export ORIS_API_SECRET="oris_ss_live_..."

Step 3: Register Your Agent

Every AI agent that transacts through Oris needs a registered identity. This is the foundation of KYA (Know Your Agent) compliance.

agent = client.agents.register(
    name="DataProcurer-01",
    description="Autonomous agent that purchases datasets from on-chain providers",
)

agent_id = agent["id"]
print(f"Agent registered: {agent_id}")
print(f"KYA status: {agent['kya_status']}")  # "pending"

The agent starts in pending KYA status. No transactions are allowed until verification.

Step 4: Verify the Agent

KYA verification activates the agent for on-chain operations. The Oris compliance engine runs AML screening and risk assessment in the background.

result = client.agents.verify(agent_id)
print(f"KYA status: {result['new_status']}")  # "verified"

After verification, the agent can create wallets and send payments.

Step 5: Create a Wallet

Oris wallets are ERC-4337 smart accounts. They are deployed counterfactually: the address is computed immediately, but the on-chain contract is deployed with the first transaction. Gas is abstracted away.

wallet = client.wallets.create(
    agent_id=agent_id,
    chain="polygon",
)

print(f"Wallet ID: {wallet['id']}")
print(f"Chain: {wallet['chain']}")
print(f"Smart Account: {wallet['smart_account_address']}")

Supported chains: polygon, base, ethereum, arbitrum, optimism, avalanche, bsc, celo.

Step 6: Set a Spending Policy

Spending policies are programmable guardrails that enforce transaction limits before any funds move. Policy evaluation runs in under 10 milliseconds.

policy = client.policies.create(
    agent_id=agent_id,
    policy_name="procurement-limits",
    daily_limit_usd=500.0,
    per_tx_limit_usd=100.0,
    allowed_contracts=["0xDatasetProvider1", "0xDatasetProvider2"],
    enforcement_mode="enforce",
)

print(f"Policy active: {policy['is_active']}")

Enforcement modes:

Step 7: Simulate a Payment (Optional)

Before sending real funds, you can dry-run the policy engine to verify that a transaction would pass.

simulation = client.policies.simulate_payment(
    agent_id=agent_id,
    amount=50.0,
    stablecoin="USDC",
    chain="polygon",
    counterparty_address="0xDatasetProvider1",
)

print(f"Would pass: {simulation['passed']}")
print(f"Verdict: {simulation['verdict']}")

Step 8: Send a Payment

This is the core operation. A single method call triggers the full Oris pipeline: KYA verification, policy evaluation, Veris compliance pre-screening, balance reservation, and gas-abstracted ERC-4337 execution.

tx = client.payments.send(
    agent_id=agent_id,
    to_address="0xDatasetProvider1",
    amount=25.0,
    chain="polygon",
    token="USDC",
    purpose="dataset_purchase",
    category="compute_api",
)

print(f"Payment ID: {tx['id']}")
print(f"Status: {tx['status']}")

The payment is submitted asynchronously. The initial status is pending. The on-chain transaction hash is populated after settlement.

Step 9: Check Payment Status

Poll for the final on-chain confirmation:

import time

payment_id = tx["id"]

for _ in range(10):
    status = client.payments.get(payment_id)
    if status["status"] == "confirmed":
        print(f"Settled on-chain: {status['tx_hash']}")
        break
    time.sleep(3)

Complete Working Script

from oris import OrisClient
import time

client = OrisClient(
    api_key="oris_sk_live_your_key_here",
    api_secret="oris_ss_live_your_secret_here",
)

# Register and verify agent
agent = client.agents.register(
    name="DataProcurer-01",
    description="Purchases datasets from on-chain providers",
)
agent_id = agent["id"]
client.agents.verify(agent_id)

# Create wallet on Polygon
wallet = client.wallets.create(agent_id=agent_id, chain="polygon")
print(f"Wallet: {wallet['smart_account_address']}")

# Attach spending policy
client.policies.create(
    agent_id=agent_id,
    daily_limit_usd=500.0,
    per_tx_limit_usd=100.0,
)

# Send payment
tx = client.payments.send(
    agent_id=agent_id,
    to_address="0xRecipientAddress",
    amount=25.0,
    chain="polygon",
    token="USDC",
    purpose="dataset_purchase",
)

# Wait for on-chain confirmation
for _ in range(10):
    status = client.payments.get(tx["id"])
    if status["status"] == "confirmed":
        print(f"Transaction hash: {status['tx_hash']}")
        break
    time.sleep(3)

client.close()

What Happens Under the Hood

When you call client.payments.send(), the Oris infrastructure executes a 10-stage pipeline in under 2 seconds:

Agent Request
    |
    v
[1] KYA Gate -----------> Is agent verified and not suspended?
    |
    v
[2] Wallet Resolution ---> Find the agent's wallet on the target chain
    |
    v
[3] Protocol Tier Gate --> Does the agent's KYA level allow this protocol?
    |
    v
[4] Policy Evaluation ---> Check all active spending policies (< 10ms, Redis)
    |
    v
[5] Compliance Screen ---> Veris AML pre-screening (fail-closed)
    |
    v
[6] Balance Reserve -----> ACID reservation with row-level locking
    |
    v
[7] Transaction Record --> Persistent record with "pending" status
    |
    v
[8] Spending Counters --> Increment daily/weekly/monthly counters (Redis)
    |
    v
[9] ERC-4337 Submit -----> Alto bundler builds UserOp, signs via MPC, submits
    |
    v
[10] On-Chain Confirm ---> Bundler polls for receipt, updates status to "confirmed"

The developer sees none of this complexity. One method call, one response.

Async Usage

For high-throughput applications, use the async interface:

import asyncio
from oris import OrisClient

async def main():
    client = OrisClient(
        api_key="oris_sk_live_...",
        api_secret="oris_ss_live_...",
    )

    agent = await client.agents.aregister(
        name="HighFreqAgent",
        description="Handles 1000+ micropayments per minute",
    )
    await client.agents.averify(agent["id"])

    wallet = await client.wallets.acreate(agent_id=agent["id"], chain="base")

    tx = await client.payments.asend(
        agent_id=agent["id"],
        to_address="0xServiceProvider",
        amount=0.01,
        chain="base",
        token="USDC",
    )

    print(f"Payment submitted: {tx['id']}")
    await client.close()

asyncio.run(main())

Every sync method has an async counterpart prefixed with a: register() becomes aregister(), send() becomes asend().

Error Handling

The SDK raises typed exceptions for precise error handling:

from oris.exceptions import (
    OrisPaymentError,
    OrisAuthError,
    OrisRateLimitError,
    OrisValidationError,
)

try:
    tx = client.payments.send(
        agent_id=agent_id,
        to_address="0xBlockedAddress",
        amount=25.0,
        chain="polygon",
        token="USDC",
    )
except OrisPaymentError as e:
    print(f"Payment blocked: {e.message}")
    print(f"Error code: {e.error_code}")
    # POLICY_VIOLATED, PAYMENT_COMPLIANCE_BLOCKED, WALLET_FROZEN, etc.
except OrisAuthError:
    print("Invalid API credentials. Rotate your keys.")
except OrisRateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after} seconds.")
except OrisValidationError as e:
    print(f"Invalid request: {e.details}")

Next Steps