The SDK
@argus/sdk wraps fetch once, at your app's edge. From then on, every provider call is metered automatically — what it cost, how long it took, and the rate-limit headers that never show up on any billing dashboard.
Not on npm yet. The SDK is still being packaged for public release. To integrate today, use the ingest protocol directly — it's one signed POST, zero dependencies, and is exactly what the SDK does under the hood. The snippet below shows the shape the SDK will ship with.
Setup
import { ArgusReporter } from "@argus/sdk";
const argus = new ArgusReporter({
endpoint: "https://api.argus.town/ingest",
sourceId: process.env.ARGUS_SOURCE_ID,
secret: process.env.ARGUS_SOURCE_SECRET,
});
globalThis.fetch = argus.instrument(fetch);That's the whole integration. The reporter batches events and flushes every five seconds, signing each batch the way the ingest API expects.
On Cloudflare Workers
Workers can't run timers between requests, so flush explicitly at the end of each invocation — it's one line, and it never delays your response:
export default {
async fetch(req, env, ctx) {
const res = await handle(req);
ctx.waitUntil(argus.settleAndFlush());
return res;
},
};In queue consumers and cron handlers (no ctx to hand off to), call await argus.settleAndFlush() before returning.
What it captures — and what it never touches
For each call: provider (from the hostname), endpoint, status, latency, in-band costs (like OpenRouter's usage.cost, including from streamed responses), token and credit counts, and rate-limit headers. The captured fields are a fixed allowlist — request bodies, prompts, and auth headers are never read, and the SDK never modifies or delays your requests. If Argus is unreachable, your app doesn't notice.
The SDK has zero runtime dependencies — everything is WebCrypto and plain fetch. If your app uses Effect, there's an adapter at @argus/sdk/effect.