Manual setup — Node
Install token-police, call tp.init() with instrumentModules, mind ESM import order, and run.
Add TokenPolice to a Node / TypeScript app in three steps. You'll need your API key and the collector URL first.
1. Install
npm install token-policeNode 20 or newer; works in both ESM and CommonJS. Provider libraries are auto-instrumented — no extra install for the common ones. Framework extras are on the integrations page.
2. Initialize
Call tp.init() once at startup, before you construct your LLM client — and pass the
client class in instrumentModules:
import * as tp from "token-police";
import OpenAI from "openai"; // default export or namespace — both work
tp.init({
apiKey: process.env.TOKENPOLICE_API_KEY, // tp_sk_...
baseUrl: "https://collect.tokenpolice.ai", // the collector — always set this
firewall: "dry_run", // watch first; flip to "enforce" later
instrumentModules: { openAI: OpenAI },
});
// Only now construct the client:
const client = new OpenAI();Every call client makes is now checked before it runs and logged after.
Always pass instrumentModules. It's required on native ESM, on openai 7.x, and on
pnpm/workspace installs — and harmless everywhere else. The full key list and which import
form each one takes are in Node & ESM.
3. Attach identity (recommended)
To budget per user or per session, wrap your entrypoint with tp.workflow. It tags every
call inside with one identity:
const runAgent = tp.workflow(
{ name: "support_agent" },
async (opts: { userId: string; paidPlan: string; sessionId: string; query: string }) => {
return client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: opts.query }],
});
},
);
await runAgent({ userId: "u_123", paidPlan: "pro", sessionId: "chat_42", query });tp.workflow reads userId, paidPlan, and sessionId from the first argument when it's
an object (snake_case keys work too). These identities are what budgets and rules match
on. More in Identity.
4. Run it
Run your app and make an LLM call. Then open app.tokenpolice.ai — the call shows up with its token counts and cost. Only token metadata is sent; your prompts and completions never leave your process (what's in that record).
Then finish the job
The three steps above get you metering. A production integration also names its steps, wraps its tool calls, flushes before a serverless function freezes, and handles a blocked call — and then proves all of it works. The integration checklist walks through the rest in order.
Next steps
Node & ESM
instrumentModules, import order, per-key import form.
init() parameters
Every option, defaults, and env vars.
Dry-run vs enforce
Turn on blocking when you're ready.
Integration checklist
The rest of the steps, and how to verify.
ESM / instrumentation order
If calls aren't showing up.
See it in a running app →
A full support-desk chat wired exactly like this, in Node and Python.

