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

# TanStack AI

> Automatic tracking for TanStack AI chat middleware with Raindrop.

`@raindrop-ai/tanstack-ai` adds Raindrop to TanStack AI `chat()` via a `ChatMiddleware`. It captures each chat invocation as a Raindrop event plus an OTel trace, and uses TanStack `threadId` to keep multi-turn chats grouped together.

## Install

```bash theme={null}
pnpm add @raindrop-ai/tanstack-ai @tanstack/ai @tanstack/ai-openai
```

## Quick start

```ts theme={null}
import { createRaindropTanstackAI } from "@raindrop-ai/tanstack-ai";
import { chat } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai/adapters";

const raindrop = createRaindropTanstackAI({
  writeKey: process.env.RAINDROP_WRITE_KEY,
  endpoint: "https://api.raindrop.ai/v1",
  events: { enabled: true },
  traces: { enabled: true },
  defaults: {
    userId: "user-123",
    eventName: "support_chat",
  },
});

for await (const chunk of chat({
  adapter: openaiText(),
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: "Hello!" }],
  threadId: "convo-abc",
  middleware: [raindrop.middleware],
  context: {
    userId: "user-123",
    convoId: "convo-abc",
    eventName: "support_chat",
    eventId: "evt_123",
  },
})) {
  void chunk;
}

await raindrop.flush();
```

## Configuration

`createRaindropTanstackAI()` accepts the public options exported by the package:

| Option             | Description                                                                                                      |
| ------------------ | ---------------------------------------------------------------------------------------------------------------- |
| `writeKey`         | Optional Raindrop write key. Omit it to keep telemetry local-only or disabled, depending on your workshop setup. |
| `endpoint`         | Optional Raindrop API endpoint.                                                                                  |
| `projectId`        | Optional project slug. Sets `X-Raindrop-Project-Id` on outbound event and trace requests.                        |
| `localWorkshopUrl` | Optional explicit Workshop / local debugger URL. Pass `false` to opt out of local mirroring.                     |
| `events`           | Event shipping controls (`enabled`, `debug`, `partialFlushMs`).                                                  |
| `traces`           | Trace shipping controls (`enabled`, `debug`, `debugSpans`, `flushIntervalMs`, `maxBatchSize`, `maxQueueSize`).   |
| `defaults`         | Fallback `userId`, `convoId`, `eventName`, `eventId`, and `properties` when a call omits them.                   |
| `captureContent`   | When `false`, omits message bodies, system prompts, tool args, and tool results from captured telemetry.         |

For multi-project organizations, create one client per project and pass each
project's slug as `projectId`. Omit `projectId` to use the organization's
default project.

Per-call overrides go on TanStack AI's `context` object:

```ts theme={null}
chat({
  ...
  context: {
    userId: "user-123",
    convoId: "convo-abc",
    eventName: "support_chat",
    eventId: "evt_123", // or event_id
    properties: { source: "docs" },
  },
});
```

`eventId` / `event_id` override the generated event ID for that request. When `convoId` is omitted, the middleware falls back to TanStack AI's `threadId`.

## What gets captured

* One Raindrop event per `chat()` call
* One trace per `chat()` call
* Message content and system prompts when `captureContent` is left on
* Tool calls and tool results
* Per-call metadata from `context.properties`

## Known limitations

* TanStack AI does not expose a public attachment channel on the `chat()` capture path yet, so attachments are not captured here.
* Capture currently ships through the partial-event route, so the event is emitted first and finalized by patching the partial record.
