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

# Vercel AI SDK: Stateful Chat Apps with sovseal Memory

> Use @sovseal/sdk's store/recall with Vercel AI SDK tool calling to inject relevant local memory into every request and let the model write new facts back mid-stream.

<style>
  {`
      main, article, .prose {
        margin-left: 2.5cm !important;
        margin-right: 2.5cm !important;
      }
      `}
</style>

sovseal pairs with the Vercel AI SDK to give your chat applications memory that outlives individual HTTP requests. On each request your Next.js route handler calls `AgentStateClient.recall()` to pull memories relevant to the incoming message and injects them into the system prompt. A `storeMemory` tool lets the model write new facts back to the store mid-stream. `store`/`recall` talk to the local ONEBRAIN engine over framed IPC — no network round-trip, no encryption key to manage in your route handler.

## Installation

```bash theme={null}
npm install ai @ai-sdk/openai @sovseal/sdk zod
```

## Next.js App Router API route

Create `app/api/chat/route.ts` with the following implementation. It recalls memories relevant to the incoming message, streams a response with a `storeMemory` tool available, and lets the model call that tool to persist new facts at any point in the stream.

```typescript app/api/chat/route.ts theme={null}
import { NextRequest } from "next/server";
import { streamText, tool } from "ai";
import { openai } from "@ai-sdk/openai";
import { AgentStateClient, EngineUnavailableError } from "@sovseal/sdk";
import { z } from "zod";

// Initialise the AgentStateClient once at module level.
// store/recall need no endpoint/apiKey — they talk to the local native host.
const client = new AgentStateClient();

export async function POST(req: NextRequest) {
  const { messages } = await req.json();
  const lastUserMessage = messages[messages.length - 1]?.content ?? "";

  // 1. Recall memories relevant to this message
  let recalledContext = "";
  try {
    const hits = await client.recall(lastUserMessage, { topK: 5 });
    recalledContext = hits.map((h) => h.text).join("\n");
  } catch (err) {
    if (!(err instanceof EngineUnavailableError)) throw err;
    console.warn(`Memory engine unavailable (${err.reason}) — proceeding without recall.`);
  }

  // 2. Stream the response with a storeMemory tool
  const response = streamText({
    model: openai("gpt-4o"),
    messages,
    system: `You are a helpful assistant. Here is context from previous conversations:
${recalledContext}`,
    tools: {
      storeMemory: tool({
        description:
          "Store a new fact or preference about the user for future conversations.",
        parameters: z.object({
          fact: z
            .string()
            .describe(
              "A declarative fact about the user, e.g. 'User prefers dark mode'"
            ),
        }),
        execute: async ({ fact }) => {
          try {
            const result = await client.store(fact);
            return { success: true, stored: fact, reinforced: result.reinforced };
          } catch (err) {
            if (err instanceof EngineUnavailableError) {
              return { success: false, reason: err.reason };
            }
            throw err;
          }
        },
      }),
    },
  });

  return response.toDataStreamResponse();
}
```

## Environment variables

No environment variables are required for `store`/`recall` — they need no `endpoint` or `apiKey`. If you also use `@sovseal/sdk`'s `snapshot`/`restore` for zero-knowledge state replication in the same route, add:

```bash .env.local theme={null}
SOVSEAL_API_KEY=sov_live_your-api-key
```

## How the data flow works

| Step                      | Action                                                                                         |
| ------------------------- | ---------------------------------------------------------------------------------------------- |
| Request arrives           | `client.recall()` searches the local memory store for context relevant to the incoming message |
| LLM streams               | The model reads `recalledContext` from the system prompt and answers with historical awareness |
| Model calls `storeMemory` | `client.store()` persists the new fact to the local engine before the stream closes            |
| Next request              | `client.recall()` picks up the newly stored fact if it's relevant to the new query             |

<Note>
  `store`/`recall` require the native host launcher at `~/.sovseal/native-host/run.sh`. Run `npx -y @sovseal/mcp-server` once to provision it — see [SDK Reference: Overview](/sdk-reference/overview). Memories never leave your server process in plaintext form over the network either way — `store`/`recall` are local IPC calls, not HTTP requests.
</Note>
