Skip to main content

Official Python SDK for Paegents - Payment infrastructure for AI agents with Service Catalog and Usage Escrow

Project description

Paegents Python SDK

Official Python SDK for integrating Paegents agent payments.

Installation

pip install paegents

Initialize

import os
from paegents import PaegentsSDK

sdk = PaegentsSDK(
    api_url=os.getenv('PAEGENTS_API_URL', 'https://api.paegents.com'),
    agent_id=os.environ['PAEGENTS_AGENT_ID'],
    api_key=os.environ['PAEGENTS_API_KEY'],
    owner_jwt=os.getenv('OWNER_JWT'),  # optional: owner-only endpoints
)

Agent runtime auth is api_key + agent_id. owner_jwt is only for owner-scoped routes such as policy management, dashboard setup, or owner-managed webhooks.

Security Model

All signing happens locally — private keys never leave your environment. Escrow funds are held by an on-chain smart contract, not by Paegents. Wallet addresses are screened for sanctions compliance before activation.

Keep API keys and private keys in environment variables. Never commit them to source control.

AP2 Quick Start

from paegents import build_card_payment_method

intent = sdk.create_ap2_intent_mandate(
    policy={"max_amount": {"value": 5000}, "currency": "usd"},
    metadata={"purpose": "compute credits"},
)

cart = sdk.create_ap2_cart_mandate(
    intent_mandate_id=intent.id,
    cart={"total": 2500, "currency": "usd"},
)

payment = sdk.ap2_pay(
    intent_mandate_id=intent.id,
    cart_mandate_id=cart.id,
    payment_method=build_card_payment_method(provider='stripe'),
)

if isinstance(payment, dict) and payment.get('approval_required'):
    print('Approval required:', payment['request_id'])
else:
    print('Payment status:', payment.status)

Bilateral Escrow Usage Agreements

Bilateral escrow is a two-step process: create the agreement, then activate the on-chain escrow.

Activation is required. Without completing activation, the agreement stays at accepted / activation_status=ready. The metered proxy will reject requests and no funds are deposited on-chain.

import os, time
from paegents import (
    sign_buyer_activation_intent,
    build_prior_allowance_funding_authorization,
    ActivateEscrowRequestV2,
    BuyerActivationIntentV2,
    FundingAuthorizationV2,
)

# Step 1: Create the agreement (auto-accepted for self-service)
agreement = sdk.create_usage_agreement(
    seller_agent_id='seller-agent-123',
    service_id='svc_abc123',
    quantity=1000,
    unit='api_calls',
    price_per_unit_cents=10,
    buyer_wallet_address=os.environ['AGENT_WALLET_ADDRESS'],
)

# Step 2: Fetch the activation package (terms, nonces, funding options)
package = sdk.get_activation_package(agreement.agreement_id)

# Step 3a: Sign the buyer activation intent locally (EIP-712)
intent = {
    "agreement_key": package.agreement_key,
    "platform_agreement_id_hash": package.platform_agreement_id_hash,
    "buyer": package.terms.buyer,
    "seller": package.terms.seller,
    "token": package.terms.token,
    "quantity": package.terms.quantity,
    "price_per_unit": package.terms.price_per_unit_atomic,
    "deposit_amount": package.terms.deposit_amount_atomic,
    "challenge_window_seconds": package.terms.challenge_window_seconds,
    "service_hash": package.terms.service_hash,
    "terms_hash": package.terms.terms_hash,
    "expiry": package.terms.expiry,
    "nonce": package.nonces.buyer_activation_nonce,
    "salt": package.terms.salt,
}

sig_result = sign_buyer_activation_intent(
    buyer_private_key=os.environ['AGENT_PRIVATE_KEY'],
    escrow_contract_address=package.funding.spender,
    chain_id=8453,  # Base mainnet
    intent=intent,
)

# Step 3b: Build funding authorization (prior USDC allowance)
funding = build_prior_allowance_funding_authorization(
    amount=package.terms.deposit_amount_atomic,
)

# Step 4: Submit activation to the server
sdk.activate_escrow(
    agreement.agreement_id,
    ActivateEscrowRequestV2(
        buyer_intent=BuyerActivationIntentV2(**intent),
        buyer_signature=sig_result['signature'],
        funding_authorization=FundingAuthorizationV2(**funding),
    ),
)

# Step 5: Poll until active (typically 10-30 seconds on Base)
while True:
    current = sdk.get_usage_agreement(agreement.agreement_id)
    if current.status == 'active':
        break
    time.sleep(3)

Optional: Metered Client

client = sdk.create_metered_client(agreement.agreement_id)

result = client.post('/generate', json={
    'prompt': 'hello world',
    'max_tokens': 150,
})

usage = client.get_usage_status()
print(usage.units_used, usage.units_remaining)

Policies and Approvals

Owner JWT is required for these endpoints.

import os

owner_jwt = os.environ['OWNER_JWT']

sdk.update_agent_policies(
    {
        'approvals': {'threshold_cents': 2000},
        'rails': {'allowed': ['card', 'stablecoin']},
        'spending': {'daily_limit_cents': 10000},
    },
    agent_id='agent-123',
    jwt_token=owner_jwt,
)

pending = sdk.list_approvals(status='pending', agent_id='agent-123', jwt_token=owner_jwt)
if pending.get('approvals'):
    sdk.approve_approval(pending['approvals'][0]['id'], agent_id='agent-123', jwt_token=owner_jwt)

Webhooks

import os

owner_jwt = os.environ['OWNER_JWT']

webhook = sdk.create_webhook(
    url='https://example.com/webhooks',
    event_types=['payment.*', 'agreement.*'],
    agent_id='agent-123',
    jwt_token=owner_jwt,
)

print(webhook.get('id'))

Verify Webhook Signatures

from paegents import verify_webhook_signature

verify_webhook_signature(signature_header, raw_body, os.environ['PAEGENTS_WEBHOOK_SECRET'])

Error Handling

from paegents import ApiError, PolicyDeniedError

try:
    sdk.ap2_pay(
        intent_mandate_id='intent_123',
        cart_mandate_id='cart_123',
        payment_method=build_card_payment_method(),
    )
except PolicyDeniedError as exc:
    print('Policy denied:', exc)
except ApiError as exc:
    print('API error:', exc)
except Exception as exc:
    print('Unexpected error:', exc)

Notes

  • Prefer SDK methods over manual HTTP calls.
  • Keep API keys and JWTs in environment variables.
  • Use idempotency keys on critical write operations.
  • Bilateral escrow settlement auto-pays on finalization. Buyer and seller do not need a second payout signature after the agreement is already funded and metered.
  • The platform fee is upfront-only in the current live model. Settlement should not perform a second per-call fee pull.

Support

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

paegents-2.9.0.tar.gz (45.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

paegents-2.9.0-py3-none-any.whl (34.3 kB view details)

Uploaded Python 3

File details

Details for the file paegents-2.9.0.tar.gz.

File metadata

  • Download URL: paegents-2.9.0.tar.gz
  • Upload date:
  • Size: 45.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for paegents-2.9.0.tar.gz
Algorithm Hash digest
SHA256 442bb38d9e7d45b4e61206fc62d339a0c719f0c755279b29d47cb5542157184e
MD5 563b7ffbe2346e378683bbf4c12b4300
BLAKE2b-256 f93a330b538316512cc15caa02e63d1fd4afa2b167b5bcd8ef21327e5b58cb9a

See more details on using hashes here.

File details

Details for the file paegents-2.9.0-py3-none-any.whl.

File metadata

  • Download URL: paegents-2.9.0-py3-none-any.whl
  • Upload date:
  • Size: 34.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for paegents-2.9.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8c0a78d9f69adc1a4f4cf2b948ffc1ee58e9aa2441728b27d5c73512daabb2ad
MD5 cad7ffda949296837f87ab8ef5939871
BLAKE2b-256 450b2ebeba2f1f9e6e339e3f253f61fe3cbd98dc4e2e0501cf23e4d093a38aec

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page