npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@oztenbot/agent-meter

v0.3.0

Published

Usage metering for the agent economy

Readme

agent-meter

Usage metering for the agent economy.

Drop-in metering for APIs that serve AI agents. Track every request, attribute it to an agent, and emit structured usage records — in three lines of code.

import { AgentMeter } from "agent-meter";
const meter = new AgentMeter({ serviceId: "my-api" });
app.use(meter.express());

Why

APIs are getting a new class of customer: autonomous agents. Agents call your API thousands of times, on behalf of humans you've never met, with usage patterns nothing like a browser session.

Subscriptions don't work when the buyer is a machine that can meter its own consumption. Usage-based pricing does — but only if you can measure it.

agent-meter gives you the measurement layer. Zero dependencies, framework-agnostic, and designed for the standards that are emerging around agent-to-service commerce.

Install

npm install agent-meter

Zero runtime dependencies for the core SDK. Only uses Node.js built-in crypto.

For persistent storage, optionally install:

npm install better-sqlite3

Quick Start

import express from "express";
import { AgentMeter, MemoryTransport } from "agent-meter";

const app = express();
const transport = new MemoryTransport();
const meter = new AgentMeter({ serviceId: "my-api", transport });

app.use(meter.express());

app.get("/api/widgets", (req, res) => {
  res.json({ widgets: ["a", "b", "c"] });
});

app.listen(3000);

Agents identify themselves with the X-Agent-Id header. Every request from an identified agent produces a UsageRecord.

curl -H "X-Agent-Id: bot-123" http://localhost:3000/api/widgets

Usage Records

Every metered request produces a structured record:

{
  "id": "a1b2c3d4e5f6...",
  "timestamp": "2026-02-15T00:00:00.000Z",
  "serviceId": "my-api",
  "agent": {
    "agentId": "bot-123",
    "name": "WidgetBot"
  },
  "operation": "GET /api/widgets",
  "units": 1,
  "unitType": "request",
  "pricingModel": "per-call",
  "method": "GET",
  "path": "/api/widgets",
  "statusCode": 200,
  "durationMs": 12
}

Configuration

const meter = new AgentMeter({
  // Required: identifies your service
  serviceId: "my-api",

  // Where records go (default: MemoryTransport)
  transport: new HttpTransport({ url: "https://billing.example.com/ingest" }),

  // Default pricing model for all routes
  defaultPricing: "per-call",

  // Custom agent identification (default: X-Agent-Id header)
  identifyAgent: (req) => ({
    agentId: req.headers["authorization"],
    tier: req.headers["x-agent-tier"],
  }),

  // HMAC-SHA256 signature verification
  signingSecret: process.env.SIGNING_SECRET,

  // Transform or filter records before they're sent
  beforeEmit: (record) => {
    if (record.path === "/health") return undefined; // drop
    return { ...record, metadata: { region: "us-east-1" } };
  },

  // Whether to meter 4xx/5xx responses (default: false)
  meterErrors: false,
});

Per-Route Options

app.post("/api/generate", meter.express({
  operation: "generate-text",
  units: (req) => req.body.tokens,
  unitType: "token",
  pricing: "per-unit",
}));

app.get("/health", meter.express({ skip: true }));

Transports

MemoryTransport

Stores records in-memory. Useful for testing and development.

import { MemoryTransport } from "agent-meter";

const transport = new MemoryTransport();
// After requests...
console.log(transport.records);

// Query interface (same as SQLiteTransport)
const records = transport.query({ agentId: "bot-123" });
const count = transport.count({ operation: "GET /widgets" });
const stats = transport.summary();

transport.flush(); // clear all records

SQLiteTransport

Persistent local storage with zero infrastructure. Records survive restarts and are queryable.

import { SQLiteTransport } from "agent-meter/sqlite";

const transport = new SQLiteTransport({
  filename: "./usage.db",   // or :memory: for testing
  tableName: "usage_records", // optional, default shown
});

// Records are persisted immediately on send
// Query them later:
const records = transport.query({ agentId: "bot-123", limit: 100 });
const total = transport.count({ from: "2026-02-15T00:00:00.000Z" });
const stats = transport.summary({ serviceId: "my-api" });
// stats.totalRecords, stats.totalUnits, stats.uniqueAgents
// stats.byOperation, stats.byAgent

transport.close(); // when shutting down

Requires better-sqlite3 as a peer dependency. Uses WAL mode for concurrent reads.

HttpTransport

Batches and POSTs records to a backend. Retries failed requests with exponential backoff.

import { HttpTransport } from "agent-meter";

const transport = new HttpTransport({
  url: "https://billing.example.com/ingest",
  headers: { Authorization: "Bearer sk-..." },
  batchSize: 10,          // flush every N records
  flushIntervalMs: 5000,  // or every 5 seconds
  maxRetries: 3,          // retry failed requests (default: 3)
  onError: (err, batch) => {
    console.error(`Failed to send ${batch.length} records:`, err.message);
  },
});

Request Signing

Agents can sign requests with HMAC-SHA256 so your service can verify authenticity:

// Agent side
import { signPayload } from "agent-meter";
const signature = signPayload(JSON.stringify(body), sharedSecret);
// Send as X-Agent-Signature header

// Service side
const meter = new AgentMeter({
  serviceId: "my-api",
  signingSecret: sharedSecret,
});
// Unsigned or invalid requests are silently dropped

Architecture

Agent (X-Agent-Id header)
  │
  ▼
┌─────────────────────────┐
│  Your Express API       │
│  ┌───────────────────┐  │
│  │  agent-meter       │  │
│  │  middleware         │  │
│  └────────┬──────────┘  │
│           │ UsageRecord  │
└───────────┼──────────────┘
            ▼
┌─────────────────────────┐
│  Transport                       │
│  (Memory, SQLite, HTTP, custom)  │
└─────────────────────────┘

The SDK is framework-agnostic at its core. AgentMeter.record() works with any request/response pair. The .express() method is a thin adapter (~10 lines). Adapters for Fastify, Hono, and others are coming.

Design Principles

  • Zero runtime dependencies. Only node:crypto. Install pulls nothing.
  • Measure first, bill later. This SDK captures usage. Billing is a separate concern.
  • Agent-native. Built for machine clients, not browser sessions. Agent identity is a first-class concept.
  • Non-blocking. Metering never delays your API response.
  • Extensible. Custom transports, identification, pricing models, and hooks.

Roadmap

  • [x] SQLite transport (persistent local storage)
  • [x] Query interface (query, count, summary)
  • [x] HTTP retry with exponential backoff
  • [ ] Fastify adapter
  • [ ] Hono adapter
  • [ ] Rate-limit awareness (meter + enforce)
  • [ ] Agent-side SDK (sign requests, attach identity)
  • [ ] Dashboard UI
  • [ ] Hosted billing backend

License

MIT