# TanStack AI

Adding SurrealDB Agent Memory to a TanStack AI application.

[`@tanstack/ai`](https://tanstack.com/ai) is a type-safe, provider-agnostic AI SDK for streaming chat, tool calling, and agents. SurrealDB Agent Memory adds long-term memory to a `chat()` call: recall relevant context before a generation, then store the exchange afterwards. There is no dedicated adapter. The [JavaScript SDK](/docs/agent-memory/integrations/sdks/javascript-and-typescript.md) (`@surrealdb/spectron`) runs in any server handler that calls `chat()`.

> [!NOTE]
> `Spectron` was the project name for SurrealDB Agent Memory. These type names
> will be renamed in a future release.

> [!NOTE]
> This is an integration guide. There is no first-party TanStack package; the code below wires the SurrealDB Agent Memory SDK into a `@tanstack/ai` handler, and you can adapt it to your server shape.

## Installation

```bash
npm install @surrealdb/spectron @tanstack/ai @tanstack/ai-openai
```

SurrealDB Agent Memory holds an API key, so construct the client only on the server, never in a component or loader that ships to the browser.

## A memory-aware server handler

Recall context, prepend it to the system prompt, generate, then store the turn:

```typescript
// src/routes/api/chat.ts
import { Spectron } from "@surrealdb/spectron";
import { chat, toServerSentEventsResponse } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai";

const spectron = new Spectron({
    endpoint: process.env.SPECTRON_ENDPOINT!,
    context: "acme-prod",
    apiKey: process.env.SPECTRON_API_KEY!,
});

export async function POST(request: Request) {
    const { userId, message } = await request.json();
    const scope = [`org/acme/user/${userId}`];

    // 1. Recall relevant memory as a ready-to-inject context block.
    const memory = await spectron.context(message, { scope, k: 8 });

    // 2. Generate with the context block in the system prompt.
    const stream = chat({
        adapter: openaiText("gpt-4o"),
        messages: [
            { role: "system", content: `You are a helpful assistant.\n\n## Memory\n${memory}` },
            { role: "user", content: message },
        ],
    });

    // 3. Store the exchange so it is available next time.
    //    (streamToText collects the reply; stream once to the client instead
    //    if you prefer, and store from a tee.)
    return toServerSentEventsResponse(stream);
}
```

To store the turn, collect the reply with `streamToText` before returning it:

```typescript
import { chat, streamToText } from "@tanstack/ai";

const text = await streamToText(chat({
    adapter: openaiText("gpt-4o"),
    messages: [
        { role: "system", content: `You are a helpful assistant.\n\n## Memory\n${memory}` },
        { role: "user", content: message },
    ],
}));

await spectron.rememberMany(
    [
        { role: "user", content: message },
        { role: "assistant", content: text },
    ],
    { scope },
);
```

## Recall as a tool

To let the model decide when to reach for memory, expose recall as a `@tanstack/ai` tool. Build it with `toolDefinition(...).server(...)` and pass it to `chat`:

```typescript
import { chat, toolDefinition } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai";
import { z } from "zod";

const recall = toolDefinition({
    name: "recall",
    description: "Search long-term memory for context relevant to a query.",
    inputSchema: z.object({ query: z.string() }),
    outputSchema: z.object({ context: z.string() }),
}).server(async ({ query }) => {
    const context = await spectron.context(query, { scope, k: 8 });
    return { context };
});

const stream = chat({
    adapter: openaiText("gpt-4o"),
    messages: [{ role: "user", content: message }],
    tools: [recall],
});
```

The agent loop invokes the tool automatically when the model asks for it.

## Scope per user or session

Pass a `scope` on every call to isolate memory. A scope is a slash path or an array of paths, for example `["org/acme/user/alice"]` for one user, or a session-specific path such as `["org/acme/session/abc123"]`. Register paths with `spectron scopes create` before first use.

## Next steps

- [JavaScript SDK](/docs/agent-memory/integrations/sdks/javascript-and-typescript.md): the full client surface
- [REST API](/docs/agent-memory/integrations/surfaces/rest.md): if you would rather call SurrealDB Agent Memory over HTTP directly
