Skip to main content

Agent Cloud Billing

Billing service for cloud agent resource consumption. Extends the EndpointCredits credit system with per-agent, per-customer metering across six resource types.

Refs #1981, #1983


Overview​

Agent Cloud Billing tracks every resource an agent consumes on behalf of a customer. Each usage event is recorded in the agent_resource_usage table with a calculated credit cost. Credits are deducted from the customer's balance in credit_transactions.

Agent performs work
|
v
record_usage() called with resource_type + quantity
|
v
Credit cost calculated (quantity * credits_per_unit)
|
v
AgentResourceUsage row inserted
|
v
deduct_credits() removes credits from customer balance

Resource Types and Pricing​

Six resource types are metered. Each has a fixed credit-per-unit rate.

Resource TypeCredits per UnitUnitDescription
compute2secondsAgent CPU execution time
memory_ops5operationsZeroMemory read/write operations
vector_search8queriesVector similarity search queries
storage0.001bytesObject/file storage consumption
a2a3messagesAgent-to-agent communication messages
postgresql20queriesDedicated PostgreSQL queries

Cost Examples​

OperationQuantityCalculationCredit Cost
60 seconds of compute6060 * 2120.000
10 memory operations1010 * 550.000
5 vector searches55 * 840.000
1 MB storage (1,048,576 bytes)10485761048576 * 0.0011048.576
25 agent-to-agent messages2525 * 375.000
3 PostgreSQL queries33 * 2060.000

All credit costs are calculated as Decimal values and quantized to 3 decimal places.


AgentResourceUsage Model​

The agent_resource_usage table stores every metered event.

ColumnTypeDescription
idUUIDPrimary key
agent_idVARCHAR(255)Agent identifier (indexed)
customer_idUUIDForeign key to users.id (indexed)
resource_typeVARCHAR(32)One of the six resource types
quantityNUMERICAmount of resource consumed
unitVARCHAR(32)Unit of measurement (seconds, operations, etc.)
credit_costNUMERICCalculated credit cost for this usage
period_startDATETIMEStart of the metering period
period_endDATETIMEEnd of the metering period
metadataJSONOptional additional context
created_atDATETIMERecord creation timestamp

Service API​

AgentCloudBillingService​

Instantiated with a SQLAlchemy Session. All methods operate within the caller's transaction.

from app.services.agent_cloud_billing_service import AgentCloudBillingService

service = AgentCloudBillingService(db=session)

calculate_credit_cost(resource_type, quantity)​

Calculate the credit cost for a given resource type and quantity without recording usage.

Parameters:

  • resource_type (str) -- One of: compute, memory_ops, vector_search, storage, a2a, postgresql
  • quantity (Decimal) -- Amount of resource consumed

Returns: Decimal -- credit cost quantized to 3 decimal places

Raises: ValueError if the resource type is unknown

cost = service.calculate_credit_cost("vector_search", Decimal("15"))
## cost = Decimal("120.000")

record_usage(agent_id, customer_id, resource_type, quantity, period_start, period_end, metadata=None)​

Record a resource usage event and calculate its credit cost. Inserts a row into agent_resource_usage and flushes (but does not commit -- the caller controls the transaction).

Parameters:

  • agent_id (str) -- Agent identifier
  • customer_id (str) -- Customer UUID as string
  • resource_type (str) -- One of the six valid resource types
  • quantity (float) -- Amount consumed (must be positive)
  • period_start (datetime) -- Start of metering period
  • period_end (datetime) -- End of metering period (must be after start)
  • metadata (dict, optional) -- Additional context

Returns: Dictionary with the recorded usage details:

{
"id": "uuid-string",
"agent_id": "aurora",
"customer_id": "customer-uuid",
"resource_type": "compute",
"quantity": 120.0,
"unit": "seconds",
"credit_cost": 240.0,
"period_start": "2026-06-01T00:00:00",
"period_end": "2026-06-01T01:00:00"
}

Raises:

  • ValueError if resource_type is unknown
  • ValueError if period_end is not after period_start
  • ValueError if quantity is not positive

deduct_credits(customer_id, credits, description)​

Deduct credits from a customer's balance via the credit_transactions table. Checks the current balance before deducting and returns False if insufficient.

Parameters:

  • customer_id (str) -- Customer UUID as string
  • credits (float) -- Number of credits to deduct (positive value)
  • description (str) -- Reason for the deduction

Returns: True if deduction succeeded, False if insufficient balance

Raises: ValueError if credits is not positive

success = service.deduct_credits(
customer_id="customer-uuid",
credits=240.0,
description="Agent aurora compute: 120s execution"
)

get_agent_usage_summary(agent_id, period_start, period_end)​

Retrieve aggregated usage for a specific agent over a time period, grouped by resource type.

Parameters:

  • agent_id (str) -- Agent identifier
  • period_start (datetime) -- Start of query period
  • period_end (datetime) -- End of query period

Returns:

{
"agent_id": "aurora",
"period_start": "2026-06-01T00:00:00",
"period_end": "2026-06-01T23:59:59",
"total_credit_cost": 510.0,
"total_records": 42,
"by_resource_type": {
"compute": {
"total_quantity": 300.0,
"total_credit_cost": 600.0,
"unit": "seconds",
"record_count": 15
},
"vector_search": {
"total_quantity": 50.0,
"total_credit_cost": 400.0,
"unit": "queries",
"record_count": 12
}
}
}

get_customer_cloud_spend(customer_id, period_start, period_end)​

Retrieve total cloud spend for a customer across all agents, grouped by agent and resource type.

Parameters:

  • customer_id (str) -- Customer UUID as string
  • period_start (datetime) -- Start of query period
  • period_end (datetime) -- End of query period

Returns:

{
"customer_id": "customer-uuid",
"period_start": "2026-06-01T00:00:00",
"period_end": "2026-06-30T23:59:59",
"total_credit_cost": 1250.0,
"total_records": 87,
"by_agent": {
"aurora": {
"total_credit_cost": 800.0,
"record_count": 52,
"by_resource_type": {
"compute": {
"total_quantity": 200.0,
"total_credit_cost": 400.0,
"unit": "seconds",
"record_count": 20
}
}
},
"sage": {
"total_credit_cost": 450.0,
"record_count": 35,
"by_resource_type": {}
}
}
}

Budget Alerts and Cost Management​

Monitoring Spend​

Use get_customer_cloud_spend to monitor a customer's total spend across all agents. Compare against budget thresholds to trigger alerts:

spend = service.get_customer_cloud_spend(
customer_id="customer-uuid",
period_start=month_start,
period_end=month_end,
)

if spend["total_credit_cost"] > budget_threshold:
# Trigger budget alert notification
pass

Pre-flight Balance Checks​

Before executing expensive operations, check whether the customer has sufficient credits:

estimated_cost = service.calculate_credit_cost("postgresql", Decimal("10"))
## Check balance before proceeding
can_deduct = service.deduct_credits(
customer_id="customer-uuid",
credits=float(estimated_cost),
description="Agent sage: 10 PostgreSQL queries"
)
if not can_deduct:
# Reject the operation or notify the customer
pass

Per-Agent Cost Attribution​

Use get_agent_usage_summary to attribute costs to individual agents. This enables:

  • Identifying which agents consume the most resources
  • Optimizing expensive agents (e.g., reducing unnecessary vector searches)
  • Billing breakdowns for customers running multiple agents

Data Lake Integration​

Agent resource usage is exported to the data lake as the platform/agent_resource_usage partition. This enables historical analysis and trend detection via the lake query endpoint:

SELECT agent_id, resource_type, SUM(credit_cost) as total_cost
FROM platform_agent_resource_usage
GROUP BY agent_id, resource_type
ORDER BY total_cost DESC

See docs/api/DATA_LAKE_API.md for lake query details.


Pydantic Schemas​

AgentResourceUsageCreate​

Request schema for creating a usage record.

FieldTypeRequiredConstraints
agent_idstryes1-255 chars
customer_idUUIDyes
resource_typeenumyesOne of the 6 resource types
quantityDecimalyesMust be > 0
unitenumyesMatching unit for type
credit_costDecimalyesMust be >= 0
period_startdatetimeyes
period_enddatetimeyesMust be after period_start
metadatadictnoDefault: empty dict

AgentResourceUsageResponse​

Response schema returned by API endpoints.

Includes all fields from AgentResourceUsageCreate plus:

FieldTypeDescription
idUUIDRecord primary key
created_atdatetimeCreation timestamp

AgentResourceUsageSummary​

Aggregated summary schema.

FieldTypeDescription
agent_idstrAgent identifier
resource_typeenumResource type
total_quantityDecimalSum of quantity
total_credit_costDecimalSum of credit cost
unitenumUnit of measurement
period_startdatetimeSummary period start
period_enddatetimeSummary period end
record_countintNumber of usage records

Spending Caps (Budgets)​

Separate from credit metering and x402 wallets, agents can have a USD-denominated spending cap that gates real-time operations — including A2A messages (POST /cloud/a2a/{agent_id}/message and POST /cloud/a2a/route). If an agent's budget is exceeded, the operation is blocked with 402 Payment Required before the operation executes, not after.

This is the mechanism to understand if you're building agents that call /cloud/a2a/* and get an unexpected 402 — a budget gate is almost certainly why, not a credit-balance issue.

Base path: /api/v1/billing

POST /budgets​

Create a spending cap for an agent.

{
"agent_id": "agent-uuid",
"limit_usd": 50.00,
"period": "month",
"max_task_cost_usd": 2.00,
"auto_pause": true
}
FieldTypeRequiredDescription
agent_idstringyesAgent this budget applies to
limit_usdfloatyesTotal spend allowed per period (> 0, ≤ 1,000,000)
periodstringyesday, week, or month
max_task_cost_usdfloatnoReject any single operation costing more than this
auto_pauseboolno (default false)Automatically pause the agent when the period limit is hit

Response (201 Created): a BudgetItem — same fields plus id, current_spend_usd (starts at 0), created_at, updated_at.

GET /budgets​

List budgets, optionally filtered by agent_id query param.

How the gate works​

Every budgeted operation checks two things, in order:

  1. Per-task cap: if max_task_cost_usd is set and this operation's estimated cost exceeds it, reject immediately regardless of remaining period budget.
  2. Period cap: if current_spend_usd + estimated_cost > limit_usd, reject. If auto_pause is enabled, the agent is also paused (its registration is suspended) so subsequent calls fail fast instead of repeatedly hitting the same budget check.

An agent with no budget row at all has no spending cap — budgets are opt-in, not a default restriction.

Agent Wallets (x402)​

In addition to credit-based billing, agents can hold USDC wallets for x402 micropayments. Wallets provide per-agent spending isolation with configurable limits. Refs #5008

Wallet Spending Guards​

Each wallet enforces three layers of protection:

GuardDefaultDescription
Single payment cap$10.00Maximum amount per individual transaction
Period spending limit$100.00/monthMaximum total spend per billing period
Balance check—Transaction rejected if wallet balance insufficient

Wallet Endpoints​

MethodPathDescription
POST/api/v1/cloud/x402/walletsCreate per-agent wallet
GET/api/v1/cloud/x402/wallets/{agent_id}Get wallet balance and limits
POST/api/v1/cloud/x402/wallets/{agent_id}/fundAdd funds to wallet
POST/api/v1/cloud/x402/wallets/{agent_id}/withdrawWithdraw from wallet
PUT/api/v1/cloud/x402/wallets/{agent_id}/limitsUpdate spending limits
GET/api/v1/cloud/x402/wallets/{agent_id}/transactionsTransaction history

Integration with Credit Billing​

There are three independent billing/spend systems, each covering a different concern:

  • Credits (AgentCloudBillingService) meter platform resource consumption (compute, vectors, storage, etc.) and deduct from the customer's credit balance.
  • Budgets (/billing/budgets, above) are a real-time USD spending cap that gates operations like A2A messages before they execute — independent of credit balance.
  • Wallets hold USDC for tool marketplace payments via x402.

An agent can consume platform credits for infrastructure, be gated by a USD budget cap on A2A traffic, AND spend USDC for external tool calls — all at once, as separate concerns. Use get_customer_cloud_spend for credit costs, GET /billing/budgets for spending-cap status, and the wallet transaction history for x402 payment costs.

Full wallet API documentation: Agent402 API — Agent Wallets


Key Source Files​

FilePurpose
src/backend/app/services/agent_cloud_billing_service.pyCore billing service with pricing and metering
src/backend/app/models/agent_resource_usage.pySQLAlchemy model for agent_resource_usage table
src/backend/app/schemas/agent_resource_usage.pyPydantic schemas (ResourceType, ResourceUnit, Create/Response/Summary)
src/backend/app/services/agent_wallet_service.pyPer-agent USDC wallet service with spending guards
src/backend/app/services/x402_revenue_share_service.pyMarketplace 90/5/5 revenue split service