Relevant source files
The following files were used as context for generating this wiki page:
- integrations/opencode-plugin/opencode-mem0.ts
- integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts
- mem0-ts/src/community/src/integrations/langchain/mem0.ts
- integrations/hermes-plugin-mem0/init.py
- mem0-ts/src/oss/src/memory/index.ts
- integrations/vercel-ai-sdk/src/mem0-facade.ts
- mem0/memory/main.py
- integrations/vercel-ai-sdk/src/mem0-utils.ts
- mem0/proxy/main.py
- integrations/vercel-ai-sdk/src/mem0-provider.ts
- integrations/deepseek-plugin/src/index.ts
- integrations/hermes-plugin-mem0/_backend.py
- mem0/llms/init.py
- integrations/vercel-ai-sdk/src/provider-response-provider.ts
- integrations/mem0-strands/python/src/mem0_strands/client.py
- integrations/openclaw/providers.ts
- integrations/openclaw/index.ts
- integrations/vercel-ai-sdk/src/mem0-provider-selector.ts
- integrations/agent-plugin-core/typescript/src/lifecycle.ts
- mem0-ts/src/oss/src/vector_stores/langchain.ts
- mem0/vector_stores/langchain.py
- mem0-ts/src/oss/src/llms/lmstudio.ts
- mem0-ts/src/oss/src/llms/langchain.ts
- mem0/configs/llms/init.py
- mem0/proxy/init.py
- integrations/vercel-ai-sdk/src/stream-utils.ts
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, integrations/vercel-ai-sdk/src/mem0-facade.ts:7-42
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, integrations/vercel-ai-sdk/src/mem0-utils.ts:309-390
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
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.
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
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
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.
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
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.
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
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
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.
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
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, integrations/vercel-ai-sdk/src/mem0-generic-language-model.ts:74-77
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.
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
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.
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
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() |
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
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, integrations/vercel-ai-sdk/src/mem0-provider-selector.ts:21-25
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).
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
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
The doGenerate and doStream methods delegate call options directly to the instantiated languageModel instance, returning typed LanguageModelV3GenerateResult and LanguageModelV3StreamResult responses respectively.
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
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].
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
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.
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
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
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.
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
| 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. |
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
Similarly, retrieveMemories flattens the input prompt or string, searches internal memories via searchInternalMemories, and constructs a formatted system instruction string if results exist.
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
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
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.
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
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. |
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
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
HTTP Headers and Version Attribution
When dispatching requests to the Mem0 backend, updateMemories attaches explicit attribution and authorization headers to every outgoing fetch call.
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
| 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. |
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, integrations/vercel-ai-sdk/src/mem0-utils.ts:341-352
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
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.
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
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.
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
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
Related
On This Page
OverviewProvider Architecture and Client FactoryProvider Configuration OptionsProvider Instance InitializationThe Mem0 Class FacadeGeneric Language Model Wrapper LifecycleWrapper Initialization and V3 Specification ConformanceIntercepting Generation and Streaming CallsResult Augmentation and Stream HandlingProvider Selection and Response GenerationDynamic Provider Selection and InstantiationText Generator Dispatch and ExecutionPrompt Flattening and Memory RetrievalMultimodal Content Conversion and FlatteningMemory Search and System Prompt InjectionMemory Persistence and Post-Generation HooksAdding Memories and Request Payload AssemblyHTTP Headers and Version AttributionStreaming Chunk Transformation and FilteringStream Interceptor PipelineChunk Filtering LogicRelated