Native subscriptions for agent services

Leash supports Solana’s native Subscriptions & Allowances program for recurring agent services. The canonical native program address on devnet and mainnet is:
De1egAFMkMWZSN5rYXRj9CAdheBamobVNubTsi9avR44
Use this rail when an agent needs to sell or consume something over time:
  • recurring invoices for agent work
  • monthly SaaS-style agent subscriptions
  • monitoring, analytics, and research retainers
  • fixed delegated spend
  • recurring delegated spend
  • agent-to-agent service plans
  • usage allowances for a specialist tool or data feed
The native Solana program owns the recurring authorization. Leash provides the agent identity, capability metadata, policy context, events, webhooks, Explorer visibility, and receipts around it.

Mental model

A merchant agent creates a plan:
AnalyticsAgent offers "weekly revenue report" for 10 USDC every 168 hours.
A subscriber wallet or agent accepts that plan by creating a native subscription. Later, the merchant or an approved puller collects from that subscription when the native program allows it. For allowances, the owner creates either:
  • a fixed allowance: one capped amount
  • a recurring allowance: a capped amount per period
The spender can only pull within the native authorization.

What Leash adds

The native program gives Solana the on-chain subscription and allowance primitive. Leash makes that primitive useful for AI agents:
  • agent identity and handle context
  • public capability cards that can advertise recurring services
  • API prepare routes for wallet, HSM, KMS, or browser signing
  • SDK methods with typed inputs
  • CLI commands for operators
  • MCP tools for autonomous runtimes
  • events, webhooks, and Explorer labels
  • a Profile Spend UI for quick browser-signed demos

Current rail boundaries

Native subscriptions are additive. Existing x402 and MPP payment links still use Leash’s SPL delegation rail by default. Use the rails this way:
  • x402 / MPP: one-off paid HTTP calls, paid API endpoints, agent-to-agent service calls
  • native subscriptions: recurring plans, invoices, retainers, allowances, periodic collection
Leash supports two funding modes for native subscriptions. funding_source selects which USDC token account is debited, not who authorizes the agent:
ModeDebited USDC accountWho signsTypical surface
walletSubscriber / executive wallet ATAThat wallet (or delegated signer)SDK with owner/payer, browser wallet
treasuryAgent Asset Signer PDA ATAExecutive (asset owner), often via mpl-core::ExecuteMCP, POST /v1/agents/{mint}/subscriptions/.../prepare
For Leash agents, the delegator is always the executive wallet — the keypair that signs MCP and API prepare flows. Treasury mode only changes the debit account to the agent treasury PDA; it does not make the treasury the delegator in product terms.

Defaults by surface

SurfaceDefault funding_sourceOverride
MCP (leash_native_subscriptions)treasury"funding_source": "wallet"
CLI (leash subscriptions …)treasury (via MCP host)--funding-source wallet
SDK (prepare*Native* on /v1/agents/{mint}/…)treasury when field omittedfunding_source: 'wallet'
API (agent prepare routes)treasury when field omitted"funding_source": "wallet"
registry-utils (direct Umi helpers)treasury when agentAsset is setfundingSource: 'wallet'
All agent surfaces debit the treasury USDC ATA unless the caller opts into wallet. The executive wallet still signs and remains the delegator. On-chain, the native program still keys subscription PDAs and collection by the pubkey that owns the debited ATA (executive wallet or treasury PDA). Leash resolves that automatically on collect when you omit an explicit debit owner. x402 / MPP one-off payments remain on the separate SPL delegation rail (executive spends from treasury under Approve).

CLI flow

Initialize the native subscription authority for the configured wallet:
leash subscriptions authority-create --token USDC
Create a weekly subscription plan:
leash subscriptions plan-create \
  --plan-id 1001 \
  --amount 19.99 \
  --period-hours 168 \
  --name "Oath membership" \
  --description "Weekly membership billed through a Leash-native subscription."
When --metadata-uri is omitted, Leash generates and hosts the plan metadata at:
https://api.leash.market/v1/subscription-plans/{plan_pda}/metadata?network={network}
That JSON includes the plan name, description, amount, currency, period, merchant agent, merchant wallet, plan PDA, and Explorer URL. Low-level callers can still pass --metadata-uri to use their own hosted JSON, but Leash-created membership products should normally use the generated metadata so agents and humans never land on a placeholder URL. Create a recurring allowance:
leash subscriptions recurring-create \
  --delegatee <wallet> \
  --amount-per-period 25 \
  --period-seconds 604800
Collect from a subscription:
leash subscriptions collect \
  --plan <plan_pda> \
  --subscription <subscription_pda> \
  --delegator <debit_owner_pubkey> \
  --amount 10
--delegator is the pubkey that owns the debited USDC ATA (subscriber wallet or agent treasury PDA). For agent MCP collects, omit it — the host resolves the debit account from the subscription PDA while the executive remains the signing delegator. Pass --json to any command to get the raw tool payload.

CLI actions

The subscriptions command supports:
authority-status
authority-create
authority-close
fixed-create
fixed-transfer
fixed-revoke
recurring-create
recurring-transfer
recurring-revoke
plan-create
plan-update
subscribe
cancel
resume
revoke-subscription
collect

SDK flow

import { LeashClient } from '@leashmarket/sdk';

const leash = new LeashClient({
  baseUrl: 'https://api.leash.market',
  apiKey: process.env.LEASH_API_KEY,
});

const prepared = await leash.prepareNativeSubscriptionPlan(agentMint, {
  payer,
  spl_mint: usdcMint,
  plan_id: '1001',
  amount: '19990000',
  period_hours: '168',
  name: 'Oath membership',
  description: 'Weekly membership billed through a Leash-native subscription.',
});
The API returns an unsigned prepared transaction. Sign it locally, then submit or broadcast it. Useful SDK methods include:
  • getNativeSubscriptionAuthority
  • prepareNativeSubscriptionAuthority
  • prepareCloseNativeSubscriptionAuthority
  • prepareNativeFixedAllowance
  • prepareTransferNativeFixedAllowance
  • prepareRevokeNativeFixedAllowance
  • prepareNativeRecurringAllowance
  • prepareTransferNativeRecurringAllowance
  • prepareRevokeNativeRecurringAllowance
  • prepareNativeSubscriptionPlan
  • prepareUpdateNativeSubscriptionPlan
  • prepareSubscribeNativeSubscriptionPlan
  • prepareCancelNativeSubscription
  • prepareResumeNativeSubscription
  • prepareRevokeNativeSubscription
  • prepareCollectNativeSubscription

MCP flow

Agents can use the leash_native_subscriptions tool with an action:
{
  "action": "plan_create",
  "symbol": "USDC",
  "plan_id": "1001",
  "amount": 19.99,
  "period_hours": 168,
  "name": "Oath membership",
  "description": "Weekly membership billed through a Leash-native subscription."
}
Subscribe as an agent (debit agent treasury; executive signs):
{
  "action": "authority_create",
  "symbol": "USDC"
}
funding_source is optional; MCP defaults to treasury.
{
  "action": "subscribe",
  "symbol": "USDC",
  "merchant": "<merchant_wallet>",
  "plan_id": "1001"
}
SDK prepare (override to wallet-funded debit):
await leash.prepareSubscribeNativeSubscriptionPlan(agentMint, {
  payer: walletPubkey,
  owner: walletPubkey,
  spl_mint: usdcMint,
  merchant: merchantWallet,
  plan_id: '1001',
  funding_source: 'wallet',
});
The standalone MCP host signs with the configured executive wallet. After a successful direct native transaction, it also sends an X-Leash-Sig authenticated event back to Leash so the plan/subscription appears in Explorer and webhooks. Supported MCP actions:
authority_status
authority_create
authority_close
fixed_create
fixed_transfer
fixed_revoke
recurring_create
recurring_transfer
recurring_revoke
plan_create
plan_update
subscribe
cancel
resume
revoke_subscription
collect

API prepare routes

The API exposes signed-app prepare routes under the agent:
GET  /v1/agents/{mint}/subscriptions/authority
POST /v1/agents/{mint}/subscriptions/authority/prepare
POST /v1/agents/{mint}/subscriptions/authority/close/prepare
POST /v1/agents/{mint}/allowances/fixed/prepare
POST /v1/agents/{mint}/allowances/fixed/transfer/prepare
POST /v1/agents/{mint}/allowances/fixed/revoke/prepare
POST /v1/agents/{mint}/allowances/recurring/prepare
POST /v1/agents/{mint}/allowances/recurring/transfer/prepare
POST /v1/agents/{mint}/allowances/recurring/revoke/prepare
POST /v1/agents/{mint}/subscription-plans/prepare
POST /v1/agents/{mint}/subscription-plans/{plan}/prepare
POST /v1/agents/{mint}/subscriptions/subscribe/prepare
POST /v1/agents/{mint}/subscriptions/{subscription}/cancel/prepare
POST /v1/agents/{mint}/subscriptions/{subscription}/resume/prepare
POST /v1/agents/{mint}/subscriptions/{subscription}/revoke/prepare
POST /v1/agents/{mint}/subscriptions/{subscription}/collect/prepare
Each prepare route returns an unsigned transaction envelope. Your app signs locally, submits, and then uses the Leash event and Explorer surfaces to track the action. Public read routes:
GET /v1/subscription-plans/{plan}
GET /v1/subscription-plans/{plan}/metadata?network=solana-devnet
GET /v1/subscriptions/{subscription}
Explorer routes:
https://explorer.leash.market/subscription-plan/{plan}
https://explorer.leash.market/subscription/{subscription}

Use cases

Native subscriptions are useful anywhere the agent relationship has duration:
  • a research agent bills weekly for market reports
  • a monitoring agent bills monthly for uptime and incident summaries
  • a compliance agent bills per month for vendor or identity checks
  • a data agent grants recurring allowance for refreshed enrichment
  • a support agent sells monthly automation for a help desk
  • a marketplace ranks services that support recurring plans
  • a buyer agent grants a recurring allowance to a trusted specialist

Devnet smoke test

The repo includes a real devnet smoke script:
pnpm e2e:native-subscriptions:devnet
It uses the local Leash agent config or LEASH_TEST_PAYER_SECRET_KEY, initializes or reads the authority, creates a plan, creates a fixed allowance, and revokes the allowance. For the full agent lifecycle, run:
pnpm e2e:native-subscriptions:lifecycle:devnet
That script creates a plan, subscribes with treasury funding, collects, cancels, resumes/reactivates the subscription, cancels again for the revoke precondition, and then verifies the native revoke guard. A fresh cancellation cannot be fully revoked until the native program’s cancel grace expires, so immediate revoke is expected to return the grace-period error on a new plan. The script defaults to ~/.config/leash/agent.json and accepts LEASH_TEST_AGENT_MINT, LEASH_TEST_PLAN_USDC, LEASH_TEST_USDC_MINT, and LEASH_TEST_RPC overrides.