By Sagar Shankaran, Founder of CallSphere
Explore pricing strategies for AI agents including per-invocation metering, tiered subscriptions, and freemium conversion funnels. Learn how to build billing infrastructure that tracks usage accurately and optimizes revenue.
Key takeaways
AI agents have variable costs that make traditional flat-rate pricing risky. A simple question might cost $0.002 in LLM tokens, while a complex multi-step research task could cost $0.50 or more. Agents that use expensive tools — web search, code execution, database queries — add further cost variability. Your pricing model must account for this variance while remaining simple enough for customers to understand.
The three dominant models each suit different agent types: subscription for predictable-use agents, usage-based for variable workloads, and freemium for maximizing adoption.
Usage-based pricing requires accurate metering. Every agent invocation must be tracked with enough detail to compute costs:
Hear it before you finish reading
Talk to a live CallSphere AI voice agent for IT support in your browser — 60 seconds, no signup.
flowchart TD
USAGE{"Monthly call<br/>volume?"}
STARTER["Starter<br/>under 500 calls per month"]
GROWTH["Growth<br/>500 to 5,000 per month"]
SCALE["Scale<br/>5,000 plus per month"]
ENT["Enterprise<br/>dedicated infra and SLA"]
USAGE -->|Light| STARTER
USAGE -->|Mid| GROWTH
USAGE -->|High| SCALE
USAGE -->|Custom| ENT
STARTER --> NEXT(["Pick monthly plan"])
GROWTH --> NEXT
SCALE --> NEXT
ENT --> NEXT
style USAGE fill:#4f46e5,stroke:#4338ca,color:#fff
style NEXT fill:#059669,stroke:#047857,color:#fff
from dataclasses import dataclass, field
from datetime import datetime, timezone
from enum import Enum
import uuid
class BillableEvent(Enum):
INVOCATION = "invocation"
INPUT_TOKENS = "input_tokens"
OUTPUT_TOKENS = "output_tokens"
TOOL_CALL = "tool_call"
COMPUTE_SECONDS = "compute_seconds"
@dataclass
class UsageRecord:
id: str = field(
default_factory=lambda: str(uuid.uuid4())
)
tenant_id: str = ""
agent_id: str = ""
event_type: BillableEvent = BillableEvent.INVOCATION
quantity: float = 1.0
unit_cost: float = 0.0
metadata: dict = field(default_factory=dict)
timestamp: datetime = field(
default_factory=lambda: datetime.now(timezone.utc)
)
@property
def total_cost(self) -> float:
return self.quantity * self.unit_cost
class UsageMeteringService:
def __init__(self, event_store, pricing_table):
self.event_store = event_store
self.pricing_table = pricing_table
async def record_agent_run(
self, tenant_id: str, agent_id: str,
input_tokens: int, output_tokens: int,
tool_calls: list[str], duration_seconds: float,
):
pricing = await self.pricing_table.get_pricing(
tenant_id, agent_id
)
records = []
# Invocation event
records.append(UsageRecord(
tenant_id=tenant_id,
agent_id=agent_id,
event_type=BillableEvent.INVOCATION,
quantity=1,
unit_cost=pricing.per_invocation,
))
# Token costs
records.append(UsageRecord(
tenant_id=tenant_id,
agent_id=agent_id,
event_type=BillableEvent.INPUT_TOKENS,
quantity=input_tokens,
unit_cost=pricing.per_input_token,
))
records.append(UsageRecord(
tenant_id=tenant_id,
agent_id=agent_id,
event_type=BillableEvent.OUTPUT_TOKENS,
quantity=output_tokens,
unit_cost=pricing.per_output_token,
))
# Tool call costs
for tool_name in tool_calls:
tool_price = pricing.tool_prices.get(
tool_name, pricing.default_tool_price
)
records.append(UsageRecord(
tenant_id=tenant_id,
agent_id=agent_id,
event_type=BillableEvent.TOOL_CALL,
quantity=1,
unit_cost=tool_price,
metadata={"tool_name": tool_name},
))
await self.event_store.batch_insert(records)
Subscription pricing groups features and usage limits into tiers. The tier system must enforce limits in real time and handle upgrades and downgrades:
@dataclass
class SubscriptionTier:
name: str
monthly_price: float
included_invocations: int
included_tokens: int
overage_per_invocation: float
overage_per_token: float
allowed_agents: list[str] # empty = all
max_concurrent_runs: int = 5
features: list[str] = field(default_factory=list)
TIERS = {
"free": SubscriptionTier(
name="Free",
monthly_price=0,
included_invocations=100,
included_tokens=50_000,
overage_per_invocation=0,
overage_per_token=0,
allowed_agents=["basic-assistant"],
max_concurrent_runs=1,
features=["basic_chat"],
),
"pro": SubscriptionTier(
name="Pro",
monthly_price=49.0,
included_invocations=5000,
included_tokens=2_000_000,
overage_per_invocation=0.02,
overage_per_token=0.00003,
allowed_agents=[],
max_concurrent_runs=10,
features=[
"basic_chat", "advanced_tools", "analytics",
],
),
"enterprise": SubscriptionTier(
name="Enterprise",
monthly_price=499.0,
included_invocations=100_000,
included_tokens=50_000_000,
overage_per_invocation=0.01,
overage_per_token=0.00002,
allowed_agents=[],
max_concurrent_runs=50,
features=[
"basic_chat", "advanced_tools", "analytics",
"custom_agents", "sla", "dedicated_support",
],
),
}
Before executing any agent run, check whether the tenant's subscription permits it:
class EntitlementService:
def __init__(self, subscription_store, usage_store):
self.subscriptions = subscription_store
self.usage = usage_store
async def check_entitlement(
self, tenant_id: str, agent_id: str
) -> dict:
sub = await self.subscriptions.get_active(tenant_id)
tier = TIERS[sub.tier_name]
# Check agent access
if tier.allowed_agents and agent_id not in tier.allowed_agents:
return {
"allowed": False,
"reason": "Agent not included in your plan",
"upgrade_to": "pro",
}
# Check usage limits (free tier blocks at limit)
current = await self.usage.get_period_total(
tenant_id, "invocations"
)
if sub.tier_name == "free" and current >= tier.included_invocations:
return {
"allowed": False,
"reason": "Free tier limit reached",
"upgrade_to": "pro",
}
# Check concurrency
active_runs = await self.usage.get_active_runs(
tenant_id
)
if active_runs >= tier.max_concurrent_runs:
return {
"allowed": False,
"reason": "Concurrent run limit reached",
"retry_after_seconds": 30,
}
return {
"allowed": True,
"overage": current > tier.included_invocations,
}
The freemium model works only if you track conversion signals. Instrument the product to understand which features drive upgrades:
class ConversionTracker:
def __init__(self, analytics_store):
self.analytics = analytics_store
async def track_limit_hit(
self, tenant_id: str, limit_type: str
):
await self.analytics.record({
"event": "limit_hit",
"tenant_id": tenant_id,
"limit_type": limit_type,
"timestamp": datetime.now(timezone.utc).isoformat(),
})
async def track_feature_gate(
self, tenant_id: str, feature: str
):
await self.analytics.record({
"event": "feature_gate_shown",
"tenant_id": tenant_id,
"feature": feature,
"timestamp": datetime.now(timezone.utc).isoformat(),
})
async def get_conversion_signals(
self, tenant_id: str
) -> dict:
events = await self.analytics.query(
tenant_id=tenant_id, event_types=[
"limit_hit", "feature_gate_shown",
]
)
return {
"total_limit_hits": sum(
1 for e in events if e["event"] == "limit_hit"
),
"features_attempted": list(set(
e["feature"]
for e in events
if e["event"] == "feature_gate_shown"
)),
"days_active": len(set(
e["timestamp"][:10] for e in events
)),
}
Abstract your pricing from model costs. Define your own unit of value — "agent runs" or "credits" — and price in those units. When model costs change, adjust the internal mapping between credits and actual cost without changing customer-facing prices. This insulates customers from provider volatility.
Still reading? Stop comparing — try CallSphere live.
See the IT support AI agent handle a real call — complete, industry-specific, and live in your browser. No signup.
The best metric aligns with customer value. For customer support agents, price per resolved ticket. For research agents, price per report generated. For general-purpose agents, per-invocation with token overage works well. Avoid pricing on metrics customers cannot predict or control, like raw token counts.
Log every agent run with full input, output, tool calls, and cost breakdown. Provide customers a detailed usage dashboard showing exactly what each invocation cost and why. When disputes arise, the audit trail proves the charges. Consider offering cost caps or budget alerts so customers never face surprise bills.
#AgentMonetization #PricingStrategy #UsageBasedBilling #SaaSPricing #AgenticAI #LearnAI #AIEngineering

Written by
Sagar Shankaran· Founder, CallSphere
LinkedInSagar Shankaran is the founder of CallSphere, where he builds production AI voice and chat agents deployed across healthcare, hospitality, real estate, and home services. He writes about agentic AI, LLM engineering, and shipping voice agents that handle real calls in production.
See how AI voice agents work for your industry. Live demo available -- no signup required.
The 2026 desktop AI agent landscape — ServiceNow Project Arc, Anthropic Claude offerings, OpenAI agents, and Google Mariner. A buyer's map.
An agentic-AI perspective on Anthropic Skills system, covering orchestration patterns, tool use, and how agent tooling fits production agent stacks.
Enterprise CIO Guide perspective on Comet's general-availability launch put an agentic browser in front of millions of consumers, and it works better than the demos suggested.
Enterprise CIO Guide perspective on Harvey AI's enterprise rollout numbers show legal agents have moved past the pilot stage at AmLaw 100 firms.
Enterprise CIO Guide perspective on Hippocratic AI's deployment numbers show healthcare voice agents are moving from pilot to production across major US health systems.
An agentic-AI perspective on Claude Agent SDK loops, covering orchestration patterns, tool use, and how agent orchestration fits production agent stacks.
© 2026 CallSphere Inc. All rights reserved.
Made within San Francisco