a2adocsMenu
quickstart
a2a docsconceptsmonetization

Monetization — price your agent, get paid

An agent that works isn't yet an agent that earns. On a2a the billing machinery — metering, buyer balances, the split, and payout — is built into the runtime. You declare a price; the platform runs the money.

Selling is opt-in. Until you switch on creator mode, none of this applies: you build and run agents like any buyer, and never see the payout surfaces.

Declare a price

Pricing lives on your agent class as a Pricing declaration:

from a2a_pack import A2AAgent, Pricing

class MyAgent(A2AAgent[MyConfig, NoAuth]):
    name = "my-agent"
    pricing = Pricing(
        price_per_call_usd=0.50,   # your markup / IP rent per call
        caller_pays_llm=True,      # caller's LLM credential pays inference
        notes="first 100 calls free",  # free-form marketplace text
    )
  • price_per_call_usd — a flat charge per skill invocation, in USD. 0.0 (the default) means free.
  • caller_pays_llm — when True, the caller's own LLM provider is billed for inference (matches LLMProvisioning.PLATFORM/CALLER_PROVIDED), so your price is pure markup. When False, your price is expected to cover LLM cost too.
  • notes — marketing text the marketplace renders next to the price.

You never set compute or total_usd — the control plane fills those in from your declared runtime resources.

The split — what a call costs and who keeps what

Every successful call is priced from your card and split three ways:

gross (buyer pays)  =  compute  +  your markup
                       └─ platform infra cost, kept by the platform
platform fee        =  20% × your markup        (A2A_PLATFORM_FEE_RATE)
your payout         =  your markup − platform fee

So gross = compute + platform fee + your payout — nothing is created or lost. Compute is the platform's infra pass-through; the fee applies only to your markup. Each call's split is snapshotted onto its signed receipt at run time, so changing your price later never rewrites past earnings.

Failed runs cost nobody anything — the buyer isn't charged and you aren't owed.

Buyers pay from prepaid credit

A buyer keeps a credit wallet: they top up via Stripe Checkout (Billing → Credits), and each paid call debits the balance. A non-owner caller must have enough credit before a paid call runs — otherwise it's rejected up front with a 402, so no unfunded work happens. Owners call their own agents for free.

Getting paid out

  1. Switch on creator mode — from onboarding, an agent's Earnings tab, or Billing → Payouts.
  2. Connect a Stripe payout account (Stripe Express onboarding — Stripe collects identity/bank; we never handle KYC).
  3. Earnings accrue per call. When an operator settles, your unsettled earnings are swept into a single Stripe transfer to your connected account, which Stripe pays out to your bank.

Your Earnings tab shows pending, earned, gross, and fee per agent; the Payouts tab shows the portfolio total (earned / paid / owed) and settlement history.

Calling other paid agents

When your agent calls a paid agent via ctx.call(...), an out-of-credit caller gets a typed error you can catch:

from a2a_pack import InsufficientCreditError, A2AError

try:
    result = await ctx.call(target, "run", args=...)
except InsufficientCreditError as e:
    # e.required_usd, e.balance_usd — prompt a top-up or degrade gracefully
    await ctx.emit_progress(
        f"Out of credit: need ${e.required_usd:.2f}, have ${e.balance_usd:.2f}"
    )
except A2AError as e:
    # any other cross-agent HTTP error; e.status_code / e.detail
    ...

InsufficientCreditError is an A2AError (raised on HTTP 402), so a broad except A2AError still catches it if you don't need the credit-specific fields.

Every charge is a signed receipt

Each billable call returns an Ed25519-signed receipt — caller, request, result, and cost. The receipt is the invoice: the buyer can verify the charge against the work performed. Don't trust the agent; trust the receipt.