Usage metering for
the agent economy
Drop-in metering for APIs that serve AI agents.
Track every request, attribute it to an agent,
and issue cryptographic usage receipts.
// axum middleware — wrap any route let meter = AgentMeter::new(MeterConfig { service_id: "my-api".into(), ..Default::default() }); let app = Router::new() .route("/api/generate", post(handler) .layer(AgentMeterLayer::new(meter) .with_receipt_secret("svc-secret")));
let client = AgentClient::new(ClientConfig { agent_id: "agent-y".into(), signing_secret: Some("shared-secret".into()), service_url: "https://api.agentmeter.io".into(), ..Default::default() }); // Signed request → receipt in response headers let resp = client.call("POST", "/api/generate", body).await?; // Diff local log against service records let report = client.reconcile().await?; // matched: 47 · agent_only: 2 · service_only: 0
How it works
Two parties. One correlation key. Cryptographic proofs on both sides.
Agent signs the request
Before sending, Agent Y computes HMAC(secret, body) and sends it as X-Agent-Signature. This signature is the unforgeable correlation key between both parties' records.
Service meters and issues a receipt
The axum middleware verifies the signature, builds a UsageRecord, stores it, and injects X-Usage-Receipt: HMAC(svc_secret, sig) into the response. The receipt proves Service X recorded the request.
Both parties reconcile
Agent Y downloads Service X's usage records and diffs them against its local log. Unmatched records surface as agent_only (not metered) or service_only (unexpected charges).
HMAC-SHA256 signing
Every request body is signed. Service X can't fabricate Agent Y's signatures. Compatible byte-for-byte with the TypeScript SDK.
Merkle attestation
Batches ship with a Merkle root signed over all records. Any tampering in transit invalidates the root — detectable by either party.
Reconciliation
Periodic diff by requestSignature. Matched, unmatched, and discrepant records surfaced with counts. Same model as financial statements.
Transports
Records go wherever you need them. Composable and swappable.
Retry-After.Install
# Core + axum middleware agent-meter = "0.1" agent-meter-axum = "0.1" # Optional: persistent SQLite storage agent-meter = { version = "0.1", features = ["sqlite"] }
# Agent-side: signing + reconciliation agent-meter-client = "0.1"
npm install @oztenbot/agent-meter
Get in touch
Questions, bugs, ideas, or just building something with agents.
Hosted billing backend
Send records to api.agentmeter.io instead of running your own SQLite. Queryable usage history, invoicing, and rate limiting included.
HttpTransport::new(HttpTransportOptions { url: "https://api.agentmeter.io/v1/usage/batch".into(), headers: [("Authorization", "Bearer sk-...")].into(), ..Default::default() })