Usage-based billing for AI agent developers. 3-line integration.
Project description
AgentBill
Usage-based billing for AI agents. 3-line integration.
Stop charging flat monthly fees for agents whose costs swing between $2 and $40 per run.
Stop losing money when a rogue agent loops for 45 minutes at your expense.
The problem
You built an AI agent. It does something valuable. You charge $99/month flat.
- A 3-second run costs you $0.80. You made $98.20.
- A 45-minute recursive loop costs you $140. You lost $41.
And you don't find out until your OpenAI invoice arrives.
The fix: 3 lines
from agentbill import meter
@meter(event="research_run", customer_id_from="customer_id", preflight=True)
async def run_agent(customer_id: str, topic: str) -> str:
result = await call_your_llm(topic)
return result
That's it. AgentBill now:
- Checks the customer's credit balance before the LLM call (
preflight=True) - Records the credit usage after the function succeeds
- Blocks the call with
BudgetExhaustedErrorthe moment the customer runs out — no surprise overages
Install
pip install agentbill
npm install agentbill
Quick start (5 minutes)
1. Get an API key
AGENTBILL_API_KEY=your_key_here
2. Decorate your agent
from agentbill import meter, BudgetExhaustedError
# Charge 1 credit per run
@meter(event="research_run", customer_id_from="customer_id")
async def run_agent(customer_id: str, topic: str) -> str:
...
# Pre-flight: block BEFORE the LLM call if the customer is out of credits
@meter(event="research_run", customer_id_from="customer_id", preflight=True)
async def run_agent_safe(customer_id: str, topic: str) -> str:
...
# Outcome-based: charge credits only if the task succeeded
@meter(
event="ticket_resolved",
customer_id_from="customer_id",
units=lambda result: 5 if result["resolved"] else 0,
)
async def resolve_ticket(customer_id: str, ticket_id: str) -> dict:
...
3. Handle credit exhaustion
try:
result = await run_agent(customer_id="cust_123", topic="quarterly report")
except BudgetExhaustedError as e:
# Show paywall, send upgrade email, pause the agent — your call
show_paywall(e.customer_id)
4. Watch your dashboard
Open https://your-instance/dashboard to see every customer's credit usage in real time:
- Credit usage bar (turns red at 80%)
- Remaining credits
- BLOCKED badge when limit is hit
Node.js
import { meter, BudgetExhaustedError } from 'agentbill'
const runAgent = meter(
async ({ customerId, topic }: { customerId: string; topic: string }) => {
const result = await callLLM(topic)
return result
},
{
event: 'research_run',
customerIdFrom: 'customerId',
preflight: true,
}
)
try {
await runAgent({ customerId: 'cust_123', topic: 'quarterly report' })
} catch (e) {
if (e instanceof BudgetExhaustedError) {
showPaywall(e.customerId)
}
}
Pricing for outcomes, not tokens
Most billing tools count events. They have no concept of "did the task actually succeed?"
AgentBill does. The credit count is a function of the result — you decide what success means:
# Support agent — charge credits only when the ticket is resolved
@meter(
event="ticket_resolved",
customer_id_from="customer_id",
units=lambda result: 5 if result["resolved"] else 0,
)
async def resolve_ticket(customer_id: str, ticket_id: str) -> dict:
resolution = await run_support_agent(ticket_id)
return resolution # {"resolved": True, "summary": "..."}
# Coding agent — charge credits only when tests pass
@meter(
event="code_generated",
customer_id_from="customer_id",
units=lambda result: 10 if result["tests_passed"] else 0,
)
async def generate_code(customer_id: str, spec: str) -> dict:
code = await run_coding_agent(spec)
passed = run_tests(code)
return {"code": code, "tests_passed": passed}
# Research agent — charge by volume processed
@meter(
event="research_completed",
customer_id_from="customer_id",
units=lambda result: result["pages_processed"],
)
async def research(customer_id: str, topic: str) -> dict:
return await run_research_agent(topic)
# returns {"summary": "...", "pages_processed": 14}
If credits resolve to 0 — no event is recorded. The customer is not charged. Your margins stay intact.
Why AgentBill? (vs. Metronome / Orb / Stripe)
Metronome and Orb are excellent for SaaS products. They're built around usage records, pricing tiers, and invoicing. If you're building a database or an API with predictable units — use them.
AgentBill is different in two ways:
1. Pre-flight enforcement
Metronome and Orb record usage after the fact. They have no way to stop an expensive operation before it starts.
AgentBill checks the customer's credit balance before the LLM call runs. If they're out — the function never executes. No API call is made. No money is spent.
Metronome/Orb: run → bill → (oops, over budget)
AgentBill: check → [blocked if over budget] → run → bill
This matters when a single agent run costs $0.80 on a good day and $43 on a bad one.
2. Lives inside your function
Metronome requires you to emit events from your infrastructure. AgentBill is a decorator — it wraps your function directly and handles everything: pre-flight check, credit deduction, idempotency, error handling.
No event pipelines. No webhooks to configure. One line.
Current scope — what AgentBill solves today
AgentBill is designed for atomic, short-running agent tasks — functions that complete in a single execution and return a deterministic result.
Works well for:
- Research runs, report generation, document processing
- Support ticket resolution (single attempt)
- Code generation with test validation
- Any agent function that runs once and returns a clear result
Not yet supported:
- Multi-signal outcomes — tasks where success is determined by multiple events over time (e.g., a ticket that gets reopened 3 days later)
- Long-running workflows — agents that run for hours or days across multiple steps
- Outcome invalidation — billing reversal when a previously "successful" result is later undone
These are real problems. They require a different architecture — event sourcing, state machines, reversal logic. If you're building at that level of complexity, AgentBill's current version isn't the right tool yet.
For atomic tasks — it's 3 lines.
How it works
Your agent code
│
▼
@meter decorator
│
├─ [preflight=true] GET /budget → is_blocked? → raise BudgetExhaustedError
│
├─ Run your function (LLM call happens here)
│
├─ [function succeeded] POST /events → record credits used
│
└─ Return result
Credits are recorded after success only. If your agent throws, the customer is not charged.
API reference
@meter(event, options)
| Option | Type | Default | Description |
|---|---|---|---|
event |
str |
required | Event label, shown in dashboard |
customer_id |
str |
— | Fixed customer identifier |
customer_id_from |
str |
— | Name of a function parameter to read customer_id from |
units |
int | callable |
1 |
Credits per call, or a function (result) -> int returning 0 to skip billing |
preflight |
bool |
False |
Check credit balance before running. Blocks immediately if exhausted. |
metadata |
dict |
— | Static key-value pairs attached to every event |
Exceptions
| Exception | When |
|---|---|
BudgetExhaustedError |
Customer has 0 remaining credits (HTTP 402) |
AgentBillError |
Network error or unexpected server response |
Self-hosting
git clone https://github.com/marketinglior-pixel/agentbill
cd agentbill
cp .env.example .env # add your DATABASE_URL and AGENTBILL_API_KEY
npm install
npm run dev
Requires: Node 20+, PostgreSQL 14+
Roadmap
- Core metering (
POST /events) - Credit balance enforcement (HTTP 402)
- Pre-flight guardrails (
preflight=True) - Outcome-based billing (
units=lambda) - Live dashboard
- Stripe Connect — bill your customers directly
- Webhooks — alerts at 80% and 100% credit usage
- Multi-signal outcome support
- Team accounts
Why not Stripe directly?
Stripe's metered billing requires: a product, a price, a customer, a subscription, a subscription item, and then a usage record per event. That's 6 API calls and 47 pages of documentation to charge someone $2.
Stripe also has no concept of "did the task succeed?" or "stop before it starts."
AgentBill handles all of that behind a single decorator.
Built for developers who ship agents and want to get paid fairly for what they actually deliver.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentbill_sdk-0.1.1.tar.gz.
File metadata
- Download URL: agentbill_sdk-0.1.1.tar.gz
- Upload date:
- Size: 7.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
94745dc4e20561430c77270fced25f4c1aba34a463f0f93b5e70f5473763a0c9
|
|
| MD5 |
78e7b795b65c2887b2212415592b4cc7
|
|
| BLAKE2b-256 |
93fe434fff2d83e758967ab2bd9340c2e763db3d2316e8e0b737eb508892599b
|
File details
Details for the file agentbill_sdk-0.1.1-py3-none-any.whl.
File metadata
- Download URL: agentbill_sdk-0.1.1-py3-none-any.whl
- Upload date:
- Size: 7.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36a9a9fbe74b9f8b57086161f2b8c82dab464bca3ce96cf9644cb7495b29587a
|
|
| MD5 |
af8c22c8dbf078e3b128cee1808707ce
|
|
| BLAKE2b-256 |
c555d80260b86f642a6dcaa61d4f15c5101f71f0e4537ccf4fc015d9330e3c3e
|