> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pylva.com/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript SDK

> Install and operate the Pylva TypeScript SDK for Node.js agent runtimes.

The TypeScript SDK ships as `@pylva/sdk`. It auto-instruments supported provider clients and emits server-priced telemetry to Pylva.

```bash theme={null}
pnpm add @pylva/sdk
```

## Initialize

```ts theme={null}
import { init } from "@pylva/sdk";

init({
  apiKey: process.env.PYLVA_API_KEY!,
});
```

You can pass `endpoint` for self-hosted deployments. Omit it for Pylva Cloud.

## Auto-instrumentation

Importing the SDK patches supported provider clients in the host process. Current coverage:

* OpenAI.
* Anthropic.
* Vercel AI.

Captured fields include provider, model, tokens in, tokens out, latency, status, `customer_id`, and `step_name` when a tracking context is active.

## Tracking context

```ts theme={null}
import { track } from "@pylva/sdk";

await track(
  "acme-corp",
  { step: "draft_reply" },
  async () => {
    return openai.chat.completions.create({
      model: "gpt-4o-mini",
      messages,
    });
  },
);
```

`track` uses async context so metadata follows nested awaits without manual argument threading.

## LangGraph and LangChain callbacks

Use the callback entrypoint when LangGraph.js or LangChain.js owns the model
calls. This path is observer-only and does not import the root SDK entrypoint,
so it does not auto-patch providers.

```bash theme={null}
pnpm add @pylva/sdk @langchain/core @langchain/langgraph
```

```ts theme={null}
import { PylvaCallbackHandler } from "@pylva/sdk/langgraph";

const handler = new PylvaCallbackHandler({
  apiKey: process.env.PYLVA_API_KEY!,
});

await graph.invoke(input, {
  callbacks: [handler],
  metadata: { pylva_customer_id: "cust_acme" },
});
```

`@pylva/sdk/langchain` re-exports the same handler. Pylva records run ids,
parent run ids, graph node attribution, provider, model, token usage, latency,
status, and customer id. It does not send prompts, completions, tool inputs, or
tool outputs.

Customer id resolution order is:

* Constructor `customerId`.
* `metadata.pylva_customer_id`.
* `metadata.customer_id`.
* Active `track()` context.
* `anonymous`.

Enable tool-call usage only when the tool execution itself is billable:

```ts theme={null}
const handler = new PylvaCallbackHandler({
  apiKey: process.env.PYLVA_API_KEY!,
  trackToolCalls: true,
});
```

Tool events report `metric="calls"` and `metric_value=1`.

## Non-LLM usage

```ts theme={null}
import { reportUsage } from "@pylva/sdk";

reportUsage({
  customer_id: "acme-corp",
  step: "speak_answer",
  metric: "characters",
  value: 4200,
});
```

Report raw usage, not dollars. Pylva applies pricing on the server.

## Budget hard stops

```ts theme={null}
import { init, PylvaBudgetExceeded } from "@pylva/sdk";

init({ apiKey: process.env.PYLVA_API_KEY! });

try {
  await openai.chat.completions.create({ model, messages });
} catch (err) {
  if (err instanceof PylvaBudgetExceeded) {
    return cachedOrSmallerResponse();
  }
  throw err;
}
```

SDK errors fail open unless an active, cached rule intentionally blocks the call.

## Webhook verification

```ts theme={null}
import { verifyWebhook } from "@pylva/sdk";

const ok = verifyWebhook(
  rawBody,
  signatureHeader,
  process.env.PYLVA_WEBHOOK_SECRET!,
  timestampHeader,
);
```

The helper accepts raw hex signatures and `sha256=` prefixed signatures.
