---
title: "Vercel AI SDK Integration"
description: "The Vercel AI SDK integration provides a specialized provider interface that bridges Mem0 long-term memory management directly into AI applications built with the Vercel AI SDK and the Version 3 la..."
last_updated: "2026-10-11T17:37:10.229915+00:00"
canonical_url: "https://www.doc0.dev/docs/faa36707-7c28-4f69-a18f-700ff61c704e/technical/ecosystem-integrations/vercel-ai-sdk-integration"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [integrations/opencode-plugin/opencode-mem0.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/opencode-plugin/opencode-mem0.ts)
- [integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts)
- [mem0-ts/src/community/src/integrations/langchain/mem0.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/mem0-ts/src/community/src/integrations/langchain/mem0.ts)
- [integrations/hermes-plugin-mem0/__init__.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/hermes-plugin-mem0/__init__.py)
- [mem0-ts/src/oss/src/memory/index.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/mem0-ts/src/oss/src/memory/index.ts)
- [integrations/vercel-ai-sdk/src/mem0-facade.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-facade.ts)
- [mem0/memory/main.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/mem0/memory/main.py)
- [integrations/vercel-ai-sdk/src/mem0-utils.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-utils.ts)
- [mem0/proxy/main.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/mem0/proxy/main.py)
- [integrations/vercel-ai-sdk/src/mem0-provider.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-provider.ts)
- [integrations/deepseek-plugin/src/index.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/deepseek-plugin/src/index.ts)
- [integrations/hermes-plugin-mem0/_backend.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/hermes-plugin-mem0/_backend.py)
- [mem0/llms/__init__.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/mem0/llms/__init__.py)
- [integrations/vercel-ai-sdk/src/provider-response-provider.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/provider-response-provider.ts)
- [integrations/mem0-strands/python/src/mem0_strands/client.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/mem0-strands/python/src/mem0_strands/client.py)
- [integrations/openclaw/providers.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/providers.ts)
- [integrations/openclaw/index.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/openclaw/index.ts)
- [integrations/vercel-ai-sdk/src/mem0-provider-selector.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-provider-selector.ts)
- [integrations/agent-plugin-core/typescript/src/lifecycle.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/agent-plugin-core/typescript/src/lifecycle.ts)
- [mem0-ts/src/oss/src/vector_stores/langchain.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/mem0-ts/src/oss/src/vector_stores/langchain.ts)
- [mem0/vector_stores/langchain.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/mem0/vector_stores/langchain.py)
- [mem0-ts/src/oss/src/llms/lmstudio.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/mem0-ts/src/oss/src/llms/lmstudio.ts)
- [mem0-ts/src/oss/src/llms/langchain.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/mem0-ts/src/oss/src/llms/langchain.ts)
- [mem0/configs/llms/__init__.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/mem0/configs/llms/__init__.py)
- [mem0/proxy/__init__.py](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/mem0/proxy/__init__.py)
- [integrations/vercel-ai-sdk/src/stream-utils.ts](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/stream-utils.ts)
</details>

## Overview

The Vercel AI SDK integration provides a specialized provider interface that bridges Mem0 long-term memory management directly into AI applications built with the Vercel AI SDK and the Version 3 language model specification. It exposes a configurable provider factory via `[[createMem0]]` that handles base URL resolution, headers, custom fetch wrappers, and API key management across multiple underlying LLM vendors.

Sources: [integrations/vercel-ai-sdk/src/mem0-provider.ts:1-140](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-provider.ts#L1-L140), [integrations/vercel-ai-sdk/src/mem0-facade.ts:7-42](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-facade.ts#L7-L42)

The architecture encapsulates generation and streaming calls within a generic language model wrapper (`Mem0GenericLanguageModel`) that automatically flattens prompts, queries relevant historical memories, and injects retrieved context as system messages prior to invocation. It dynamically routes requests through selected backend providers while capturing assistant completions to persist conversational turns back into Mem0.

Sources: [integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts:20-170](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts#L20-L170), [integrations/vercel-ai-sdk/src/mem0-utils.ts:309-390](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-utils.ts#L309-L390)

## Provider Architecture and Client Factory

### Provider Configuration Options

The public API surface revolves around the `[[createMem0]]` factory function and the `Mem0` class facade, which initialize provider instances conforming to the Vercel AI SDK `ProviderV3` specification.

The `Mem0ProviderSettings` interface defines the configuration properties accepted by `createMem0()` and the `Mem0` class constructor.

| Property | Type | Default Value | Description |
| :--- | :--- | :--- | :--- |
| `baseURL` | `string` | `"https://api.openai.com"` | Base URL for API requests, normalized via `withoutTrailingSlash`. |
| `fetch` | `typeof fetch` | `undefined` | Custom fetch implementation for request interception or testing. |
| `generateId` | `() => string` | `undefined` | Internal identifier generator function. |
| `headers` | `Record<string, string \| undefined>` | `undefined` | Custom headers included in outgoing requests. |
| `name` | `string` | `undefined` | Provider or model identifier name. |
| `mem0ApiKey` | `string` | `undefined` | API key specific to Mem0 services. |
| `apiKey` | `string` | `undefined` | General API key for the underlying model vendor. |
| `provider` | `string` | `"openai"` | Underlying LLM provider identifier. |
| `modelType` | `"completion" \| "chat"` | `undefined` | Target model type constraint. |
| `mem0Config` | `Mem0Config` | `undefined` | Configuration object for memory extraction and retrieval. |
| `config` | `LLMProviderSettings` | `undefined` | Provider-specific configuration options passed to language models. |

Sources: [integrations/vercel-ai-sdk/src/mem0-provider.ts:20-46](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-provider.ts#L20-L46)

### Provider Instance Initialization

The `createMem0` function instantiates a callable `Mem0Provider` function augmented with helper methods for constructing language models. When invoked directly, the provider checks `new.target` to guard against construction via the `new` keyword and defaults to creating a generic language model via `createGenericModel`.

```typescript
export function createMem0(
  options: Mem0ProviderSettings = {
    provider: "openai",
  }
): Mem0Provider {
  const baseURL =
    withoutTrailingSlash(options.baseURL) ?? "https://api.openai.com";
  const getHeaders = () => ({
    ...options.headers,
  });

  const createGenericModel = (
    modelId: Mem0ChatModelId,
    settings: Mem0ChatSettings = {}
  ) =>
    new Mem0GenericLanguageModel(
      modelId,
      settings,
      {
        baseURL,
        fetch: options.fetch,
        headers: getHeaders(),
        provider: options.provider || "openai",
        name: options.name,
        mem0ApiKey: options.mem0ApiKey,
        apiKey: options.apiKey,
        mem0Config: options.mem0Config,
      },
      options.config
    );

  const createCompletionModel = (
    modelId: Mem0ChatModelId,
    settings: Mem0ChatSettings = {}
  ) =>
    new Mem0GenericLanguageModel(
      modelId,
      settings,
      {
        baseURL,
        fetch: options.fetch,
        headers: getHeaders(),
        provider: options.provider || "openai",
        name: options.name,
        mem0ApiKey: options.mem0ApiKey,
        apiKey: options.apiKey,
        mem0Config: options.mem0Config,
        modelType: "completion",
      },
      options.config
    );

  const createChatModel = (
    modelId: Mem0ChatModelId,
    settings: Mem0ChatSettings = {}
  ) =>
    new Mem0GenericLanguageModel(
      modelId,
      settings,
      {
        baseURL,
        fetch: options.fetch,
        headers: getHeaders(),
        provider: options.provider || "openai",
        name: options.name,
        mem0ApiKey: options.mem0ApiKey,
        apiKey: options.apiKey,
        mem0Config: options.mem0Config,
        modelType: "chat",
      },
      options.config
    );

  const provider = function (
    modelId: Mem0ChatModelId,
    settings: Mem0ChatSettings = {}
  ) {
    if (new.target) {
      throw new Error(
        "The Mem0 model function cannot be called with the new keyword."
```
Sources: [integrations/vercel-ai-sdk/src/mem0-provider.ts:48-140](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-provider.ts#L48-L140)

> [!WARNING]
> Calling the returned `Mem0Provider` instance with the `new` keyword throws an explicit runtime error: `"The Mem0 model function cannot be called with the new keyword."`

Sources: [integrations/vercel-ai-sdk/src/mem0-provider.ts:125-129](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-provider.ts#L125-L129)

### The Mem0 Class Facade

In parallel with `createMem0`, the `Mem0` class provides an alternative object-oriented facade wrapping base URL normalization, header aggregation, and model factory methods for chat and completion interfaces.

```typescript
export class Mem0 {
  readonly baseURL: string
  readonly headers?: any

  constructor(options: Mem0ProviderSettings = {
    provider: 'openai',
  }) {
    this.baseURL =
      withoutTrailingSlash(options.baseURL) ?? 'https://api.openai.com'

    this.headers = options.headers
  }

  private get baseConfig() {
    return {
      baseURL: this.baseURL,
      headers: this.headers,
    }
  }

  chat(modelId: Mem0ChatModelId, settings: Mem0ChatSettings = {}) {
    return new Mem0GenericLanguageModel(modelId, settings, {
      provider: 'openai',
      modelType: 'chat',
      ...this.baseConfig,
    })
  }

  completion(modelId: Mem0ChatModelId, settings: Mem0ChatSettings = {}) {
    return new Mem0GenericLanguageModel(modelId, settings, {
      provider: 'openai',
      modelType: 'completion',
      ...this.baseConfig,
    })
  }
}
```
Sources: [integrations/vercel-ai-sdk/src/mem0-facade.ts:7-42](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-facade.ts#L7-L42)

## Generic Language Model Wrapper Lifecycle

### Wrapper Initialization and V3 Specification Conformance

The `Mem0GenericLanguageModel` class implements the Vercel AI SDK `LanguageModelV3` specification, exposing version `v3` and supporting wildcard URLs (`*`) matched by `/.*/`. The constructor accepts a chat model identifier, chat settings, a configuration object, and optional provider settings, defaulting the underlying provider string to `"openai"` if unspecified.

```typescript
export class Mem0GenericLanguageModel implements LanguageModelV3 {
  readonly specificationVersion = "v3";
  readonly supportedUrls: Record<string, RegExp[]> = {
    '*': [/.*/]
  };

  constructor(
    public readonly modelId: Mem0ChatModelId,
    public readonly settings: Mem0ChatSettings,
    public readonly config: Mem0ChatConfig,
    public readonly provider_config?: Mem0ProviderSettings
  ) {
    this.provider = config.provider ?? "openai";
  }

  provider: string;
```
Sources: [integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts:20-35](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts#L20-L35)

> [!NOTE]
> The generic language model wrapper assigns `specificationVersion = "v3"` and exposes a wildcard `supportedUrls` mapping so that requests targeting any endpoint can be intercepted and enhanced with memory context.

Sources: [integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts:21-24](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts#L21-L24)

### Intercepting Generation and Streaming Calls

When `doGenerate` or `doStream` is invoked with `LanguageModelV3CallOptions`, the wrapper constructs provider and memory configurations, initializes a `Mem0ClassSelector`, and processes conversational prompts through `processMemories`. This internal lifecycle method attempts to persist new memories before retrieving relevant historical context, formatting retrieved items into a specialized system prompt prepended to the prompt array.

```typescript
private async processMemories(messagesPrompts: LanguageModelV3Message[], mem0Config: Mem0ConfigSettings) {
  try {
    // Add new memories — await to ensure writes complete before returning
    try {
      await addMemories(messagesPrompts, mem0Config);
    } catch (e) {
      console.error("Error while adding memories");
    }

    // Get memories (always returns an array since graph support is removed)
    const memories: any[] = await getMemories(messagesPrompts, mem0Config) ?? [];

    const mySystemPrompt = "These are the memories I have stored. Give more weightage to the question by users and try to answer that first. You have to modify your answer based on the memories I have provided. If the memories are irrelevant you can ignore them. Also don't reply to this section of the prompt, or the memories, they are only for your reference. The System prompt starts after text System Message: \n\n";

    let memoriesText = "";
    try {
      memoriesText = memories
        ?.map((memory: any) => `Memory: ${memory?.memory}\n\n`)
        .join("\n\n");
    } catch (e) {
      console.error("Error while parsing memories");
    }

    const memoriesPrompt = `System Message: ${mySystemPrompt} ${memoriesText} `;

    // Clone the prompt array to avoid mutating the caller's reference on retries
    const updatedPrompts = [...messagesPrompts];

    if (memories?.length > 0) {
      const systemPrompt: LanguageModelV3Message = {
        role: "system",
        content: memoriesPrompt
      };
      updatedPrompts.unshift(systemPrompt);
    }

    return { memories, messagesPrompts: updatedPrompts };
  } catch (e) {
    console.error("Error while processing memories");
    return { memories: [], messagesPrompts: [...messagesPrompts] };
  }
}
```
Sources: [integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts:37-78](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts#L37-L78)

> [!CAUTION]
> If memory processing encounters an exception during either persistence or retrieval, the error is caught, logged to `console.error`, and execution safely falls back to returning the original unmodified prompt array without historical context.

Sources: [integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts:38-44](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts#L38-L44), [integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts:74-77](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts#L74-L77)

### Result Augmentation and Stream Handling

In `doGenerate`, once the underlying provider model generates a response, the wrapper checks if any memories were retrieved. If memories are present, it constructs a `LanguageModelV3Source` object with a generated random identifier (`mem0-` followed by randomized alphanumeric characters) and attaches provider metadata containing the raw memories and concatenated memory text before returning the augmented result.

```typescript
  if (!memories || memories?.length === 0) {
    return ans;
  }

  const mem0Source: LanguageModelV3Source = {
    type: "source",
    sourceType: "url",
    id: "mem0-" + generateRandomId(),
    url: "https://app.mem0.ai?utm_source=oss&utm_medium=vercel-ai-sdk-src",
    title: "Mem0 Memories",
    providerMetadata: {
      mem0: {
        memories: memories,
        memoriesText: memories
          ?.map((memory: any) => memory?.memory)
          .join("\n\n"),
      },
    },
  };

  return {
    ...ans,
    content: [...(ans.content ?? []), mem0Source],
  };
}
```
Sources: [integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts:108-132](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts#L108-L132)

Conversely, `doStream` delegates to the underlying provider model's `doStream` method using the updated memory-injected prompts, returning the raw stream response or throwing an error if streaming fails or remains unimplemented.

```typescript
async doStream(options: LanguageModelV3CallOptions): Promise<LanguageModelV3StreamResult> {
  try {
    const provider = this.config.provider;
    const mem0_api_key = this.config.mem0ApiKey;

    const settings: Mem0ProviderSettings = {
      provider: provider,
      mem0ApiKey: mem0_api_key,
      apiKey: this.config.apiKey,
      modelType: this.config.modelType,
    }

    const mem0Config: Mem0ConfigSettings = {
      mem0ApiKey: mem0_api_key,
      ...this.config.mem0Config,
      ...this.settings,
    }

    const selector = new Mem0ClassSelector(this.modelId, settings, this.provider_config);

    const { messagesPrompts: updatedPrompts } = await this.processMemories(options.prompt, mem0Config);

    const baseModel = selector.createProvider();

    const streamResponse = await baseModel.doStream({
      ...options,
      prompt: updatedPrompts,
    });

    // Return the full stream response, preserving all V3 fields (warnings, etc.)
    return streamResponse;
  } catch (error) {
    console.error("Error in doStream:", error);
    throw new Error("Streaming failed or method not implemented.");
  }
}
```
Sources: [integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts:134-169](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts#L134-L169)

## Provider Selection and Response Generation

### Dynamic Provider Selection and Instantiation

The `Mem0ClassSelector` class validates and instantiates the underlying AI provider. It accepts a `modelId`, `Mem0ProviderSettings`, and optional `ProviderSettings`, defaulting `provider_wrapper` to `"openai"` if `config.provider` is omitted. 

| Provider Identifier | Supported Status | Initialization Factory Function |
| :--- | :--- | :--- |
| `"openai"` | Supported | `createOpenAI()` |
| `"anthropic"` | Supported | `createAnthropic()` |
| `"cohere"` | Supported | `createCohere()` |
| `"groq"` | Supported | `createGroq()` |
| `"google"` / `"gemini"` | Supported | `createGoogleGenerativeAI()` |

```typescript
class Mem0ClassSelector {
    modelId: string;
    provider_wrapper: string;
    config: Mem0ProviderSettings;
    provider_config?: ProviderSettings;
    static supportedProviders = ["openai", "anthropic", "cohere", "groq", "google", "gemini"];

    constructor(modelId: string, config: Mem0ProviderSettings, provider_config?: ProviderSettings) {
        this.modelId = modelId;
        this.provider_wrapper = config.provider || "openai";
        this.provider_config = provider_config;
        if(config) this.config = config;
        else this.config = {
            provider: this.provider_wrapper,
        };

        // Check if provider_wrapper is supported
        if (!Mem0ClassSelector.supportedProviders.includes(this.provider_wrapper)) {
            throw new Error(`Model not supported: ${this.provider_wrapper}`);
        }
    }

    createProvider(): LanguageModelV3 {
        return new Mem0AITextGenerator(this.modelId, this.config , this.provider_config || {});
    }
}
```
Sources: [integrations/vercel-ai-sdk/src/mem0-provider-selector.ts:5-30](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-provider-selector.ts#L5-L30)

> [!WARNING]
> If `provider_wrapper` does not match any entry in `Mem0ClassSelector.supportedProviders`, the constructor throws an error stating `Model not supported: ${this.provider_wrapper}`.

Sources: [integrations/vercel-ai-sdk/src/mem0-provider-selector.ts:10-10](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-provider-selector.ts#L10-L10), [integrations/vercel-ai-sdk/src/mem0-provider-selector.ts:21-25](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-provider-selector.ts#L21-L25)

### Text Generator Dispatch and Execution

The `Mem0AITextGenerator` class implements the `LanguageModelV3` specification, exposing `specificationVersion = "v3"`, a `modelId`, a fixed provider string `"mem0"`, and `supportedUrls` matching any URL pattern (`'*': [/.*/]`). Its constructor uses a switch statement over `config.provider` to instantiate the appropriate underlying SDK client. For OpenAI, it supports specific model types (`completion`, `chat`, or default `languageModel`).

```typescript
class Mem0AITextGenerator implements LanguageModelV3 {
    readonly specificationVersion = "v3";
    readonly modelId: string;
    readonly provider = "mem0";
    readonly supportedUrls: Record<string, RegExp[]> = {
        '*': [/.*/]
    };
    private languageModel: any; // Use any type to avoid version conflicts

    constructor(modelId: string, config: Mem0ProviderSettings, provider_config: ProviderSettings) {
        this.modelId = modelId;

        switch (config.provider) {
            case "openai":
                if(config?.modelType === "completion"){
                    this.languageModel = createOpenAI({
                        apiKey: config?.apiKey,
                        ...provider_config as OpenAIProviderSettings,
                    }).completion(modelId);
                } else if(config?.modelType === "chat"){
                    this.languageModel = createOpenAI({
                        apiKey: config?.apiKey,
                        ...provider_config as OpenAIProviderSettings,
                    }).chat(modelId);
                } else {
                    this.languageModel = createOpenAI({
                        apiKey: config?.apiKey,
                        ...provider_config as OpenAIProviderSettings,
                    }).languageModel(modelId);
                }
                break;
            case "cohere":
                this.languageModel = createCohere({
                    apiKey: config?.apiKey,
                    ...provider_config as CohereProviderSettings,
                })(modelId);
                break;
            case "anthropic":
                this.languageModel = createAnthropic({
                    apiKey: config?.apiKey,
                    ...provider_config as AnthropicProviderSettings,
                }).languageModel(modelId);
                break;
            case "groq":
                this.languageModel = createGroq({
                    apiKey: config?.apiKey,
                    ...provider_config as GroqProviderSettings,
                })(modelId);
                break;
            case "google":
            case "gemini":
                this.languageModel = createGoogleGenerativeAI({
                    apiKey: config?.apiKey,
                    ...provider_config as GoogleGenerativeAIProviderSettings,
                })(modelId);
                break;
            default:
                throw new Error("Invalid provider");
        }
    }
```
Sources: [integrations/vercel-ai-sdk/src/provider-response-provider.ts:10-69](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/provider-response-provider.ts#L10-L69)

> [!CAUTION]
> If an unrecognized provider string is passed to `Mem0AITextGenerator`, the switch statement triggers its default branch and throws an `Error("Invalid provider")`.

Sources: [integrations/vercel-ai-sdk/src/provider-response-provider.ts:66-68](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/provider-response-provider.ts#L66-L68)

The `doGenerate` and `doStream` methods delegate call options directly to the instantiated `languageModel` instance, returning typed `LanguageModelV3GenerateResult` and `LanguageModelV3StreamResult` responses respectively.

```typescript
    async doGenerate(options: LanguageModelV3CallOptions): Promise<LanguageModelV3GenerateResult> {
        const result = await this.languageModel.doGenerate(options);
        return result as LanguageModelV3GenerateResult;
    }

    async doStream(options: LanguageModelV3CallOptions): Promise<LanguageModelV3StreamResult> {
        const result = await this.languageModel.doStream(options);
        return result as LanguageModelV3StreamResult;
    }
}
```
Sources: [integrations/vercel-ai-sdk/src/provider-response-provider.ts:71-80](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/provider-response-provider.ts#L71-L80)

## Prompt Flattening and Memory Retrieval

### Multimodal Content Conversion and Flattening

The `flattenPrompt` utility extracts and flattens user message prompts from a `LanguageModelV3Prompt` structure. It maps over prompt parts, verifying if the role is `"user"`, and handles string content, text array objects, or specific file and multimodal media types. File attachments mapped by `mediaType` yield standard text descriptions (`[PDF document]`, `[Markdown document]`, `[Image]`, or `[File attachment]`), while unhandled types resolve to `[multimodal content]`.

```typescript
const flattenPrompt = (prompt: LanguageModelV3Prompt) => {
    try {
        return prompt.map((part) => {
            if (part.role === "user") {
                if (typeof part.content === 'string') {
                    return part.content;
                } else if (Array.isArray(part.content)) {
                    return part.content
                        .filter((obj) => obj.type === 'text')
                        .map((obj) => obj.text)
                        .join(" ");
                } else if (part.content && typeof part.content === 'object' && 'type' in part.content) {
                    const content = part.content as any;
                    if (content.type === 'text' && content.text) {
                        return content.text;
                    } else if (content.type === 'file') {
                        if (content.mediaType === 'application/pdf') {
                            return '[PDF document]';
                        } else if (content.mediaType === 'text/markdown' || content.mediaType === 'application/mdx') {
                            return '[Markdown document]';
                        } else if (content.mediaType && content.mediaType.startsWith('image/')) {
                            return '[Image]';
                        } else {
                            return '[File attachment]';
                        }
                    }
                }
                return "[multimodal content]";
            }
            return "";
        }).join(" ");
    } catch (error) {
        console.error("Error in flattenPrompt:", error);
        return "";
    }
}
```
Sources: [integrations/vercel-ai-sdk/src/mem0-utils.ts:36-71](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-utils.ts#L36-L71)

Complementing prompt flattening, `convertToMem0Format` transforms messages into structures accepted by the backend. It handles string contents, text arrays, and specific attachment types including PDFs (`pdf_url`), Markdown or MDX documents (`mdx_url`), and images (`image_url`), normalizing various schema aliases.

```typescript
const convertToMem0Format = (messages: LanguageModelV3Prompt) => {
    try {
        return messages.flatMap((message: any) => {
            try {
                if (typeof message.content === 'string') {
                    return {
                        role: message.role,
                        content: message.content,
                    };
                }
                else if (Array.isArray(message.content)) {
                    return message.content.map((obj: any) => {
                        try {
                            if (obj.type === "text") {
                                return {
                                    role: message.role,
                                    content: obj.text,
                                };
                            } else if (obj.type === "file") {
                                if (obj.mediaType === "application/pdf") {
                                    return {
                                        role: message.role,
                                        content: {
                                            type: "pdf_url",
                                            pdf_url: {
                                                url: obj.data
                                            }
                                        }
                                    };
                                } else if (obj.mediaType === "text/markdown" || obj.mediaType === "application/mdx") {
                                    return {
                                        role: message.role,
                                        content: {
                                            type: "mdx_url",
                                            mdx_url: {
                                                url: obj.data
                                            }
                                        }
                                    };
                                } else if (obj.mediaType && obj.mediaType.startsWith("image/")) {
                                    return {
                                        role: message.role,
                                        content: {
                                            type: "image_url",
                                            image_url: {
                                                url: obj.data
                                            }
                                        }
                                    };
                                }
                            } else if (obj.type === "image_url" || obj.type === "image") {
                                return {
                                    role: message.role,
                                    content: {
                                        type: "image_url",
                                        image_url: {
                                            url: obj.image_url?.url || obj.image?.url || obj.url
                                        }
                                    }
                                };
                            } else if (obj.type === "mdx_url" || obj.type === "mdx") {
                                return {
                                    role: message.role,
                                    content: {
                                        type: "mdx_url",
                                        mdx_url: {
                                            url: obj.mdx_url?.url || obj.mdx?.url || obj.url
                                        }
                                    }
                                };
                            } else if (obj.type === "pdf_url" || obj.type === "pdf") {
                                return {
                                    role: message.role,
                                    content: {
                                        type: "pdf_url",
                                        pdf_url: {
                                            url: obj.pdf_url?.url || obj.pdf?.url || obj.url
                                        }
                                    }
                                };
```
Sources: [integrations/vercel-ai-sdk/src/mem0-utils.ts:73-154](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-utils.ts#L73-L154)

> [!NOTE]
> `flattenPrompt` catches internal mapping errors and safely returns an empty string `""` rather than crashing the execution pipeline.

Sources: [integrations/vercel-ai-sdk/src/mem0-utils.ts:67-70](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-utils.ts#L67-L70)

### Memory Search and System Prompt Injection

The `processMemories` method in `Mem0GenericLanguageModel` orchestrates persistence and retrieval during generation turns. It invokes `addMemories` to record conversational turns, queries relevant items via `getMemories`, and formats the retrieved records into a structured system prompt prefix.

```typescript
private async processMemories(messagesPrompts: LanguageModelV3Message[], mem0Config: Mem0ConfigSettings) {
  try {
    // Add new memories — await to ensure writes complete before returning
    try {
      await addMemories(messagesPrompts, mem0Config);
    } catch (e) {
      console.error("Error while adding memories");
    }

    // Get memories (always returns an array since graph support is removed)
    const memories: any[] = await getMemories(messagesPrompts, mem0Config) ?? [];

    const mySystemPrompt = "These are the memories I have stored. Give more weightage to the question by users and try to answer that first. You have to modify your answer based on the memories I have provided. If the memories are irrelevant you can ignore them. Also don't reply to this section of the prompt, or the memories, they are only for your reference. The System prompt starts after text System Message: \n\n";

    let memoriesText = "";
    try {
      memoriesText = memories
        ?.map((memory: any) => `Memory: ${memory?.memory}\n\n`)
        .join("\n\n");
    } catch (e) {
      console.error("Error while parsing memories");
    }

    const memoriesPrompt = `System Message: ${mySystemPrompt} ${memoriesText} `;

    // Clone the prompt array to avoid mutating the caller's reference on retries
    const updatedPrompts = [...messagesPrompts];

    if (memories?.length > 0) {
      const systemPrompt: LanguageModelV3Message = {
        role: "system",
        content: memoriesPrompt
      };
      updatedPrompts.unshift(systemPrompt);
    }

    return { memories, messagesPrompts: updatedPrompts };
  } catch (e) {
    console.error("Error while processing memories");
    return { memories: [], messagesPrompts: [...messagesPrompts] };
  }
}
```
Sources: [integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts:37-78](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts#L37-L78)

| Step | Operation | Description |
| :--- | :--- | :--- |
| 1 | `addMemories` | Persists user messages to the backend using `updateMemories`. |
| 2 | `getMemories` | Searches for contextually relevant past memories based on the prompt. |
| 3 | System Prefix | Prepends guidance instructing the model to weigh user questions against memories. |
| 4 | Prompt Injection | Unshifts a system message containing the formatted memories to `updatedPrompts`. |

```typescript
  await addMemories(messagesPrompts, mem0Config);
} catch (e) {
  console.error("Error while adding memories");
}

// Get memories (always returns an array since graph support is removed)
const memories: any[] = await getMemories(messagesPrompts, mem0Config) ?? [];

const mySystemPrompt = "These are the memories I have stored. Give more weightage to the question by users and try to answer that first. You have to modify your answer based on the memories I have provided. If the memories are irrelevant you can ignore them. Also don't reply to this section of the prompt, or the memories, they are only for your reference. The System prompt starts after text System Message: \n\n";

let memoriesText = "";
try {
  memoriesText = memories
    ?.map((memory: any) => `Memory: ${memory?.memory}\n\n`)
    .join("\n\n");
} catch (e) {
  console.error("Error while parsing memories");
}

const memoriesPrompt = `System Message: ${mySystemPrompt} ${memoriesText} `;

// Clone the prompt array to avoid mutating the caller's reference on retries
const updatedPrompts = [...messagesPrompts];

if (memories?.length > 0) {
  const systemPrompt: LanguageModelV3Message = {
    role: "system",
    content: memoriesPrompt
  };
  updatedPrompts.unshift(systemPrompt);
}
```
Sources: [integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts:41-71](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts#L41-L71)

Similarly, `retrieveMemories` flattens the input prompt or string, searches internal memories via `searchInternalMemories`, and constructs a formatted system instruction string if results exist.

```typescript
const retrieveMemories = async (prompt: LanguageModelV3Prompt | string, config?: Mem0ConfigSettings) => {
    try {
        const message = typeof prompt === 'string' ? prompt : flattenPrompt(prompt);
        const systemPrompt = "These are the memories I have stored. Give more weightage to the question by users and try to answer that first. You have to modify your answer based on the memories I have provided. If the memories are irrelevant you can ignore them. Also don't reply to this section of the prompt, or the memories, they are only for your reference. The System prompt starts after text System Message: \n\n";

        const data = await searchInternalMemories(message, config);
        // The API response may be a flat array or an object with a results key
        const memories: any[] = Array.isArray(data) ? data : (data?.results ?? []);

        if (memories.length === 0) {
            return "";
        }

        const memoriesText = memories
            .map((memory: any) => `Memory: ${memory.memory}\n\n`)
            .join("\n\n");

        return `System Message: ${systemPrompt} ${memoriesText}`;
    } catch (error) {
        console.error("Error in retrieveMemories:", error);
        throw error;
    }
}
```
Sources: [integrations/vercel-ai-sdk/src/mem0-utils.ts:367-389](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-utils.ts#L367-L389)

> [!WARNING]
> If memory retrieval returns an empty array or fails, `processMemories` clones the original prompt array without unshifting a system message, preventing empty injection blocks.

Sources: [integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts:63-76](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts#L63-L76)

## Memory Persistence and Post-Generation Hooks

### Adding Memories and Request Payload Assembly

The `addMemories` utility formats input prompts into structured message payloads before sending them to the backend via `updateMemories`. If the input is a plain string, it wraps it in a single user message object; otherwise, it translates the messages using `convertToMem0Format`.

```typescript
const addMemories = async (messages: LanguageModelV3Prompt, config?: Mem0ConfigSettings) => {
    try {
        let finalMessages: Array<Message> = [];
        if (typeof messages === "string") {
            finalMessages = [{ role: "user", content: messages }];
        } else {
            finalMessages = convertToMem0Format(messages);
        }
        const response = await updateMemories(finalMessages, config);
        return response;
    } catch (error) {
        console.error("Error in addMemories:", error);
        throw error;
    }
}
```
Sources: [integrations/vercel-ai-sdk/src/mem0-utils.ts:309-323](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-utils.ts#L309-L323)

The `updateMemories` function loads authentication credentials via `loadApiKey` checking the `MEM0_API_KEY` environment variable or configuration settings. It constructs a POST request body containing the messages along with optional identifiers and parameters.

| Property | Field Type | Description |
| :--- | :--- | :--- |
| `messages` | `Array<Message>` | The array of conversation turns to persist. |
| `user_id` | `string` | Optional user scope identifier. |
| `app_id` | `string` | Optional application scope identifier. |
| `agent_id` | `string` | Optional agent scope identifier. |
| `run_id` | `string` | Optional execution run identifier. |
| `metadata` | `object` | Optional custom metadata key-value pairs. |
| `infer` | `boolean` | Optional flag controlling memory extraction inference. |

```typescript
const updateMemories = async (messages: Array<Message>, config?: Mem0ConfigSettings) => {
    try {
        const apiKey = loadApiKey({
            apiKey: config?.mem0ApiKey,
            environmentVariableName: "MEM0_API_KEY",
            description: "Mem0",
        });

        const body: Record<string, any> = { messages };
        if (config?.user_id) body.user_id = config.user_id;
        if (config?.app_id) body.app_id = config.app_id;
        if (config?.agent_id) body.agent_id = config.agent_id;
        if (config?.run_id) body.run_id = config.run_id;
        if (config?.metadata) body.metadata = config.metadata;
        if (config?.infer != null) body.infer = config.infer;

```
Sources: [integrations/vercel-ai-sdk/src/mem0-utils.ts:325-340](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-utils.ts#L325-L340)

> [!NOTE]
> `updateMemories` targets the `/v3/memories/add/` endpoint on the configured host, defaulting to `https://api.mem0.ai` when no host setting is provided.

Sources: [integrations/vercel-ai-sdk/src/mem0-utils.ts:354-355](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-utils.ts#L354-L355)

### HTTP Headers and Version Attribution

When dispatching requests to the Mem0 backend, `updateMemories` attaches explicit attribution and authorization headers to every outgoing fetch call. 

```typescript
const options = {
    method: 'POST',
    headers: {
        Authorization: `Token ${apiKey}`,
        'Content-Type': 'application/json',
        // Surface attribution. Set-once by contract: this wrapper is the
        // outermost layer on these raw fetch calls.
        'X-Mem0-Source': 'VERCEL_AI_SDK',
        'X-Mem0-Client': `mem0-vercel-ai-provider/${PROVIDER_VERSION}`
    },
    body: JSON.stringify(body),
};
```
Sources: [integrations/vercel-ai-sdk/src/mem0-utils.ts:341-352](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-utils.ts#L341-L352)

| Header Name | Value / Source | Purpose |
| :--- | :--- | :--- |
| `Authorization` | `Token ${apiKey}` | Authenticates the API request using the loaded credentials. |
| `Content-Type` | `application/json` | Specifies the JSON serialization format of the request body. |
| `X-Mem0-Source` | `VERCEL_AI_SDK` | Surfaces provider attribution set-once by contract as the outermost layer. |
| `X-Mem0-Client` | `mem0-vercel-ai-provider/${PROVIDER_VERSION}` | Identifies the client wrapper version, resolving to `dev` unbundled or `__MEM0_PROVIDER_VERSION__` at build time. |

```typescript
declare const __MEM0_PROVIDER_VERSION__: string | undefined;

// Replaced at build time by tsup `define`. The fallback only applies when the
// source is run unbundled, such as in tests.
const PROVIDER_VERSION =
  typeof __MEM0_PROVIDER_VERSION__ !== "undefined" ? __MEM0_PROVIDER_VERSION__ : "dev";

…
const options = {
    method: 'POST',
    headers: {
        Authorization: `Token ${apiKey}`,
        'Content-Type': 'application/json',
        // Surface attribution. Set-once by contract: this wrapper is the
        // outermost layer on these raw fetch calls.
        'X-Mem0-Source': 'VERCEL_AI_SDK',
        'X-Mem0-Client': `mem0-vercel-ai-provider/${PROVIDER_VERSION}`
    },
    body: JSON.stringify(body),
};
```
Sources: [integrations/vercel-ai-sdk/src/mem0-utils.ts:1-7](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-utils.ts#L1-L7), [integrations/vercel-ai-sdk/src/mem0-utils.ts:341-352](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-utils.ts#L341-L352)

> [!WARNING]
> If the fetch response status is not successful (`!response.ok`), `updateMemories` throws an HTTP error containing the response status code.

Sources: [integrations/vercel-ai-sdk/src/mem0-utils.ts:356-358](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/mem0-utils.ts#L356-L358)

## Streaming Chunk Transformation and Filtering

### Stream Interceptor Pipeline

The streaming architecture utilizes `filterStream` to process and intercept response chunks generated during `doStream` invocations. The interceptor wraps an original `ReadableStream` by acquiring its reader and constructing a new stream that reads chunks asynchronously within a continuous loop.

```typescript
async function filterStream(originalStream: ReadableStream) {
    const reader = originalStream.getReader();
    const filteredStream = new ReadableStream({
        async start(controller) {
            while (true) {
                const { done, value } = await reader.read();
                if (done) {
                    controller.close();
                    break;
                }
                try {
                    const chunk = JSON.parse(value); 
                    if (chunk.type !== "step-finish") {
                        controller.enqueue(value);
                    }
                } catch (error) {
                    if (!(value.type==='step-finish')) {
                        controller.enqueue(value);
                    }
                }
            }
        }
    });

    return filteredStream;
}
```
Sources: [integrations/vercel-ai-sdk/src/stream-utils.ts:1-26](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/stream-utils.ts:1-26)

### Chunk Filtering Logic

As chunks are read from the underlying stream, the transformation pipeline attempts to parse each value as JSON. If parsing succeeds, chunks whose `.type` property matches `"step-finish"` are filtered out and omitted from the output controller.

```typescript
try {
    const chunk = JSON.parse(value); 
    if (chunk.type !== "step-finish") {
        controller.enqueue(value);
    }
} catch (error) {
```
Sources: [integrations/vercel-ai-sdk/src/stream-utils.ts:11-16](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/stream-utils.ts:11-16)

> [!NOTE]
> If JSON parsing throws an error, the interceptor falls back to checking the raw value object directly, enqueuing the chunk only if its type field is not equal to `'step-finish'`.

Sources: [integrations/vercel-ai-sdk/src/stream-utils.ts:16-20](https://github.com/blade47/mem0/blob/b7ad69afda6b6ed030347c66d48a13e4de9dec08/integrations/vercel-ai-sdk/src/stream-utils.ts:16-20)

## Related

- [Typescript Core](https://www.doc0.dev/docs/faa36707-7c28-4f69-a18f-700ff61c704e/technical/typescript-core/typescript-core)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/faa36707-7c28-4f69-a18f-700ff61c704e/llms.txt) for all pages in this wiki.
