GitHubBook a demoStart routing
Browse docs

TypeScript SDK

The zero-dependency TypeScript instrumentation SDK — install, the exported API, callback scopes, the drop-in fetch, the async ledger pull, and runnable examples.

On this page

The TypeScript SDK is the idiomatic-TS binding of the same contract as Python: zero runtime dependencies, dual ESM+CJS, edge-safe core. It emits x-tt-* headers and reads back typed receipts — it forwards and reads; it never computes.

Install

npm install tokentriage
import * as tt from "tokentriage";
// or named:
import { init, trace, step, headers, receipt, fetch, wrapFetch, lastReceipt, ledger, check } from "tokentriage";

Subpaths: tokentriage (the frozen root), tokentriage/adapters/otel, and tokentriage/management (the generated admin-API client).

Configure

tt.init({
  baseUrl: "https://tt.example.com",     // env: TOKENTRIAGE_BASE_URL
  adminUrl: "http://127.0.0.1:9090",     // env: TOKENTRIAGE_ADMIN_URL
  log: "warn",                            // "debug" | "warn" | "off"
  agent: "my-service",
});

init(options?) is the one entry that throws (TokenTriageConfigError). The env vars match Python’s (TOKENTRIAGE_BASE_URL, TOKENTRIAGE_ADMIN_URL, TOKENTRIAGE_DISABLED, TOKENTRIAGE_LOG, TOKENTRIAGE_ADMIN_TOKEN).

The exported API

  • Context (callback-scoped): trace<T>(options, fn) / trace<T>(fn) and step<T>(...) run their callback inside one AsyncLocalStorage frame. currentStep() returns Step | null. (There is no decorator form and no observe — that’s a Python-only convenience.)
  • Wire: headers(overrides?) returns the x-tt-* record; receipt(source, status?) parses a Response, Headers, or header record into a Receipt; lastReceipt() returns the most recent.
  • Transport: fetch is a drop-in for globalThis.fetch that injects headers(), opens an implicit per-request step, and pairs the receipt; wrapFetch(base?, options?) builds an origin-scoped wrapper.
  • Ledger & doctor (all async): ledger.fetch(receiptOrReqId, { adminUrl?, waitS? }), ledger.fetchTrace(...), ledger.feedback(receiptOrReqId, { ok, note?, adminUrl? }); check({ adminUrl?, probe? }).
  • Also exported: registerExporter, DebugExporter, renderCost, version, TokenTriageConfigError, and the full type set (Mode, StepClass, Cost, Receipt, InitOptions, TraceOptions, StepOptions, …).

Examples

Drop-in fetch behind the OpenAI SDK, honest cost from the ledger:

import * as tt from "tokentriage";
import OpenAI from "openai";

tt.init({ baseUrl: "https://tt.example.com", adminUrl: "http://127.0.0.1:9090" });
const client = new OpenAI({ baseURL: "https://tt.example.com/v1", fetch: tt.fetch });

await tt.trace({ agent: "planner" }, async () => {
  await tt.step({ agent: "coder", stepClass: "tool_loop" }, async () => {
    await client.chat.completions.create({ model: "gpt-4o", messages: [] });
    const rcpt = tt.lastReceipt();
    if (rcpt) {
      const row = await tt.ledger.fetch(rcpt);           // async in TS
      if (row.cost?.state === "priced") console.log(row.cost.usd);  // string
    }
  });
});

Library-agnostic headers() path (any client, no adapter):

import { init, trace, headers, receipt } from "tokentriage";

init({ baseUrl: "https://tt.example.com" });
await trace({ agent: "planner", tags: { env: "prod" } }, async () => {
  const r = await fetch("https://tt.example.com/v1/messages", { headers: headers() });
  const rcpt = receipt(r);
  console.log(rcpt.requestId, rcpt.mode, rcpt.costDisplay);
});

Doctor + feedback + the OTel bridge:

import { check, ledger, lastReceipt } from "tokentriage";
import { bridge } from "tokentriage/adapters/otel";   // importing the subpath is the opt-in

const report = await check({ adminUrl: "http://127.0.0.1:9090" });
const dispose = bridge();                              // x-tt-* now adopt the active OTel span ids
try {
  const ack = await ledger.feedback(lastReceipt()!, { ok: false, note: "bad" });  // rejects on failure
  console.log(ack.accepted, ack.verdict, ack.source);
} finally {
  dispose();
}

Parity with Python

Aspect Python TypeScript
install / import pip install tokentriage / import tokentriage as tt npm install tokentriage / import * as tt from "tokentriage"
scope form context manager and decorator (with, @observe) callback only (trace(opts, fn))
ledger / check synchronous async (Promise)
built-in transport adapters httpx, requests, LangChain, CrewAI, OTel fetch/wrapFetch + OTel
Cost.usd Decimal | None decimal string, after narrowing to priced
naming snake_case (fetch_trace, last_receipt) camelCase (fetchTrace, lastReceipt)
feedback on failure raises rejects

Both bindings are verified against the same byte-equality conformance corpus.