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 Type | Credits per Unit | Unit | Description |
|---|---|---|---|
compute | 2 | seconds | Agent CPU execution time |
memory_ops | 5 | operations | ZeroMemory read/write operations |
vector_search | 8 | queries | Vector similarity search queries |
storage | 0.001 | bytes | Object/file storage consumption |
a2a | 3 | messages | Agent-to-agent communication messages |
postgresql | 20 | queries | Dedicated PostgreSQL queries |
Cost Examples
| Operation | Quantity | Calculation | Credit Cost |
|---|---|---|---|
| 60 seconds of compute | 60 | 60 * 2 | 120.000 |
| 10 memory operations | 10 | 10 * 5 | 50.000 |
| 5 vector searches | 5 | 5 * 8 | 40.000 |
| 1 MB storage (1,048,576 bytes) | 1048576 | 1048576 * 0.001 | 1048.576 |
| 25 agent-to-agent messages | 25 | 25 * 3 | 75.000 |
| 3 PostgreSQL queries | 3 | 3 * 20 | 60.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.
| Column | Type | Description |
|---|---|---|
| id | UUID | Primary key |
| agent_id | VARCHAR(255) | Agent identifier (indexed) |
| customer_id | UUID | Foreign key to users.id (indexed) |
| resource_type | VARCHAR(32) | One of the six resource types |
| quantity | NUMERIC | Amount of resource consumed |
| unit | VARCHAR(32) | Unit of measurement (seconds, operations, etc.) |
| credit_cost | NUMERIC | Calculated credit cost for this usage |
| period_start | DATETIME | Start of the metering period |
| period_end | DATETIME | End of the metering period |
| metadata | JSON | Optional additional context |
| created_at | DATETIME | Record 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,postgresqlquantity(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 identifiercustomer_id(str) -- Customer UUID as stringresource_type(str) -- One of the six valid resource typesquantity(float) -- Amount consumed (must be positive)period_start(datetime) -- Start of metering periodperiod_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:
ValueErrorif resource_type is unknownValueErrorif period_end is not after period_startValueErrorif 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 stringcredits(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 identifierperiod_start(datetime) -- Start of query periodperiod_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 stringperiod_start(datetime) -- Start of query periodperiod_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.
| Field | Type | Required | Constraints |
|---|---|---|---|
| agent_id | str | yes | 1-255 chars |
| customer_id | UUID | yes | |
| resource_type | enum | yes | One of the 6 resource types |
| quantity | Decimal | yes | Must be > 0 |
| unit | enum | yes | Matching unit for type |
| credit_cost | Decimal | yes | Must be >= 0 |
| period_start | datetime | yes | |
| period_end | datetime | yes | Must be after period_start |
| metadata | dict | no | Default: empty dict |
AgentResourceUsageResponse
Response schema returned by API endpoints.
Includes all fields from AgentResourceUsageCreate plus:
| Field | Type | Description |
|---|---|---|
| id | UUID | Record primary key |
| created_at | datetime | Creation timestamp |
AgentResourceUsageSummary
Aggregated summary schema.
| Field | Type | Description |
|---|---|---|
| agent_id | str | Agent identifier |
| resource_type | enum | Resource type |
| total_quantity | Decimal | Sum of quantity |
| total_credit_cost | Decimal | Sum of credit cost |
| unit | enum | Unit of measurement |
| period_start | datetime | Summary period start |
| period_end | datetime | Summary period end |
| record_count | int | Number of usage records |
Key Source Files
| File | Purpose |
|---|---|
src/backend/app/services/agent_cloud_billing_service.py | Core billing service with pricing and metering |
src/backend/app/models/agent_resource_usage.py | SQLAlchemy model for agent_resource_usage table |
src/backend/app/schemas/agent_resource_usage.py | Pydantic schemas (ResourceType, ResourceUnit, Create/Response/Summary) |