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

# TypeScript / JavaScript

> The drop-in trace collector for Node.js agents.

`mirrorkit` on npm is the TypeScript sibling of the Python package. Point it at your Anthropic / OpenAI / LangChain.js calls and your agent's traces stream to Mirrors with negligible overhead — non-blocking, background-batched, and it never throws into your app.

## Install

```bash theme={null}
npm install mirrorkit
```

Requires **Node ≥ 18** (uses the built-in `fetch`). Zero runtime dependencies — the LLM SDKs are optional peers, instrumented only if present.

## Usage

```typescript theme={null}
import * as mirrorkit from 'mirrorkit';
import Anthropic from '@anthropic-ai/sdk';

mirrorkit.init({ apiKey: 'mk_live_...', project: 'my-agent' });

// Recommended: wrap each client once. Guaranteed capture, no global patching.
const anthropic = mirrorkit.instrument(new Anthropic());

const res = await anthropic.messages.create({
  model: 'claude-opus-4-8',
  max_tokens: 256,
  messages: [{ role: 'user', content: "What's the weather in Paris?" }],
});
```

`init()` also best-effort auto-instruments importable SDKs, so in many setups the `instrument()` call is optional. We recommend `instrument()` anyway: it is immune to the ESM/CJS dual-instance and version-drift issues that make global patching unreliable in JS.

### Options

```typescript theme={null}
mirrorkit.init({
  apiKey: 'mk_live_...',
  project: 'my-agent',
  endpoint: 'https://api.runmirrors.com', // optional; else MIRRORKIT_ENDPOINT / MIRROR_ENDPOINT / prod
  flushIntervalMs: 2000,                  // ms between background flushes
  maxBatch: 50,                           // max traces per POST
  maxQueue: 10_000,                       // in-memory cap; oldest dropped past this
  instrument: true,                       // best-effort auto-patch at init()
  debug: false,                           // internal debug logs (or MIRRORKIT_DEBUG=1)
});
```

## LangChain.js

LangChain.js has no global handler hook, so attach the handler explicitly — either per call or by wrapping the runnable:

```typescript theme={null}
// per call:
await chain.invoke(input, { callbacks: [mirrorkit.handler()] });

// or wrap once:
const traced = mirrorkit.instrument(chain);
await traced.invoke(input);
```

<Warning>
  LangChain.js support is best-effort — validate against your pinned `@langchain/core` version. Anthropic and OpenAI are the fully-solid path.
</Warning>

## Manual logging

For anything not auto-instrumented, enqueue a trace yourself (OpenAI-style messages):

```typescript theme={null}
mirrorkit.logTrace(
  [
    { role: 'system', content: 'You are a helpful assistant.' },
    { role: 'user', content: "What's the weather in Paris?" },
    {
      role: 'assistant',
      content: null,
      tool_calls: [{ id: 'call_1', function: { name: 'get_weather', arguments: '{"city":"Paris"}' } }],
    },
    { role: 'tool', tool_call_id: 'call_1', content: '18C, sunny' },
    { role: 'assistant', content: "It's 18C and sunny in Paris." },
  ],
  { model: 'gpt-4o' },
);
```

## Custom instrumentation

Providers are pluggable — register your own to trace a framework that isn't covered out of the box:

```typescript theme={null}
mirrorkit.register(
  mirrorkit.defineInstrumentation({
    name: 'my-framework',
    canWrap: (t): boolean => typeof (t as any).run === 'function',
    wrap: (target, ctx) => {
      const orig = (target as any).run.bind(target);
      (target as any).run = async (input: any) => {
        const out = await orig(input);
        ctx.emit({ id: crypto.randomUUID(), messages: /* convert out → messages */ [] });
        return out;
      };
      return target;
    },
  }),
);
```

`register()` works before or after `init()`.

## Graceful shutdown

The collector drains on Node's `beforeExit`. For deterministic delivery in serverless or short-lived processes, flush explicitly:

```typescript theme={null}
await mirrorkit.flush();    // block until the queue drains
await mirrorkit.shutdown(); // stop the timer and flush
```

## API

| Function                      | Description                                        |
| ----------------------------- | -------------------------------------------------- |
| `init(options)`               | Start the collector (idempotent).                  |
| `instrument(client)`          | Wrap an SDK client / runnable; returns it traced.  |
| `register(instrumentation)`   | Add or override an instrumentation.                |
| `defineInstrumentation(inst)` | Typed identity helper for custom instrumentations. |
| `logTrace(messages, opts?)`   | Manually enqueue one trace.                        |
| `handler()`                   | LangChain.js callback handler.                     |
| `flush(timeoutMs?)`           | Block until the queue drains.                      |
| `shutdown()`                  | Stop the collector (flushes first).                |

## Known limitations

* **Streaming** (`stream: true`) calls are passed through untraced — non-streaming calls are fully captured.
* **Auto-instrumentation** can miss if your app loads a different copy of an SDK than `init()` resolves (ESM/CJS duplication). `instrument()` is unaffected.
* **LangChain.js** is best-effort (see above).
