SVSANNVIT
SDKs

SDK TypeScript

Installez et utilisez le SDK TypeScript du registre — l'implémentation de référence, avec capture manuelle et auto-instrumentation Anthropic/OpenAI en une ligne.

Le SDK TypeScript (sdk/typescript, nom de package @ledger/sdk) est l'implémentation de référence — parité complète, y compris l'auto-instrumentation pour les clients Anthropic et OpenAI.

Installation

Pas encore publié sur npm. Pour l'instant, intégrez sdk/typescript directement dans votre projet — copiez le répertoire, ou référencez-le comme dépendance locale/git :

npm install <path-to-repo>/sdk/typescript

Démarrage rapide — capture manuelle

import { init } from "@ledger/sdk";

const ledger = init({
  endpoint: process.env.LEDGER_ENDPOINT ?? "http://127.0.0.1:4010",
  ingestKey: process.env.LEDGER_INGEST_KEY ?? "",
  agentId: "urn:agent:research-assistant",
  onError: (e) => console.error("[ledger]", e),
});

const t0 = new Date();
// ... effectuer le travail ...
const t1 = new Date();

ledger.record({
  action_type: "llm_call",
  provider: "anthropic",
  model: "claude-fable-5",
  started_at: t0,
  ended_at: t1,
  status: "success",
  usage: { tokens_in: 420, tokens_out: 180 },
  payloads: [
    { kind: "prompt", content: "Summarize the policy for the client memo." },
    { kind: "response", content: "The policy provides that…" },
  ],
  trigger: { type: "human", subject: "person@example.com" },
});

await ledger.flush();
await ledger.shutdown();

shutdown() effectue un flush final au mieux (best-effort) avec un délai impératif (2s par défaut) — appelez-le avant que votre processus ne se termine afin que les événements en tampon ne soient pas perdus.

Démarrage rapide — auto-instrumentation

Pour Anthropic ou OpenAI, ignorez complètement les appels manuels à record() — enveloppez le client une seule fois et chaque appel suivant est capturé automatiquement, y compris le streaming :

import { init } from "@ledger/sdk";
import Anthropic from "@anthropic-ai/sdk";

const ledger = init({
  endpoint: process.env.LEDGER_ENDPOINT ?? "http://127.0.0.1:4010",
  ingestKey: process.env.LEDGER_INGEST_KEY ?? "",
  agentId: "urn:agent:research-assistant",
});
ledger.setTrigger({ type: "human", subject: "person@example.com" });

const anthropic = ledger.instrumentAnthropic(new Anthropic());

// code applicatif non modifié à partir d'ici — aucune référence au registre nécessaire
const res = await anthropic.messages.create({
  model: "claude-fable-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Draft the client memo." }],
});

instrumentOpenAI(client) fonctionne de la même manière pour le client OpenAI. Les deux sont des wrappers à typage structurel (duck-typed) — aucune dépendance aux SDK des fournisseurs à l'intérieur de @ledger/sdk lui-même.

Lignée décisionnelle

const { spanId } = ledger.record({ action_type: "search", /* ... */ });

ledger.within(spanId, async () => {
  // tout ce qui est enregistré ici a par défaut spanId comme parent_ref
  const anthropic = ledger.instrumentAnthropic(client);
  await anthropic.messages.create(/* ... */);
});

Passez parentRef explicitement sur un appel à record() pour remplacer le parent ambiant.

Envoi de blobs

const { blob_id } = await ledger.uploadBlob(fileBuffer, "application/pdf");

ledger.record({
  action_type: "data_read",
  payloads: [{ kind: "artifact", blob_ref: blob_id }],
  // ...
});

OpenTelemetry

Si vous exploitez déjà un pipeline OTel, branchez le registre comme exportateur ou processeur de spans plutôt que d'instrumenter manuellement :

import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";

provider.addSpanProcessor(ledger.otelSpanProcessor());
// ou : new BatchSpanProcessor(ledger.otelExporter())

Chaque span gen_ai.* devient un événement du registre ; les autres spans passent sans modification.