!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}return t}()||function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}(),document.documentElement.setAttribute("data-announcement-bar-initially-dismissed",function(){try{return"true"===localStorage.getItem("docusaurus.announcement.dismiss")}catch(t){}return!1}())

[Skip to main content](#__docusaurus_skipToContent_fallback)

LangChain v0.2 is coming soon! Preview the new docs [here](/v0.2/docs/introduction/).

[

![🦜️🔗 Langchain](/v0.1/img/brand/wordmark.png)![🦜️🔗 Langchain](/v0.1/img/brand/wordmark-dark.png)

](/v0.1/)[Docs](/v0.1/docs/get_started/introduction/)[Use cases](/v0.1/docs/use_cases/)[Integrations](/v0.1/docs/integrations/platforms/)[API Reference](https://api.js.langchain.com)

[More](#)

*   [People](/v0.1/docs/people/)
*   [Community](/v0.1/docs/community/)
*   [Tutorials](/v0.1/docs/additional_resources/tutorials/)
*   [Contributing](/v0.1/docs/contributing/)

[v0.1](#)

*   [v0.2](https://js.langchain.com/v0.2/docs/introduction)
*   [v0.1](/v0.1/docs/get_started/introduction/)

[🦜🔗](#)

*   [LangSmith](https://smith.langchain.com)
*   [LangSmith Docs](https://docs.smith.langchain.com)
*   [LangChain Hub](https://smith.langchain.com/hub)
*   [LangServe](https://github.com/langchain-ai/langserve)
*   [Python Docs](https://python.langchain.com/)

[Chat](https://chatjs.langchain.com)[](https://github.com/langchain-ai/langchainjs)

Search

*   [Get started](/v0.1/docs/get_started/)
    
    *   [Introduction](/v0.1/docs/get_started/introduction/)
    *   [Installation](/v0.1/docs/get_started/installation/)
    *   [Quickstart](/v0.1/docs/get_started/quickstart/)
*   [LangChain Expression Language](/v0.1/docs/expression_language/)
    
    *   [Get started](/v0.1/docs/expression_language/get_started/)
    *   [Why use LCEL?](/v0.1/docs/expression_language/why/)
    *   [Interface](/v0.1/docs/expression_language/interface/)
    *   [Streaming](/v0.1/docs/expression_language/streaming/)
    *   [How to](/v0.1/docs/expression_language/how_to/routing/)
        
        *   [Route between multiple runnables](/v0.1/docs/expression_language/how_to/routing/)
        *   [Cancelling requests](/v0.1/docs/expression_language/how_to/cancellation/)
        *   [Use RunnableMaps](/v0.1/docs/expression_language/how_to/map/)
        *   [Add message history (memory)](/v0.1/docs/expression_language/how_to/message_history/)
        *   [Add message history (memory)](/v0.1/docs/expression_language/how_to/with_history/)
    *   [Cookbook](/v0.1/docs/expression_language/cookbook/)
        
    *   [LangChain Expression Language (LCEL)](/v0.1/docs/expression_language/)
*   [Modules](/v0.1/docs/modules/)
    
    *   [Model I/O](/v0.1/docs/modules/model_io/)
        
    *   [Retrieval](/v0.1/docs/modules/data_connection/)
        
    *   [Chains](/v0.1/docs/modules/chains/)
    *   [Agents](/v0.1/docs/modules/agents/)
        
    *   [More](/v0.1/docs/modules/memory/)
        
*   [Security](/v0.1/docs/security/)
*   [Guides](/v0.1/docs/guides/)
    
*   [Ecosystem](/v0.1/docs/ecosystem/)
    
*   [LangGraph](/v0.1/docs/langgraph/)
*   * * *
    

*   [](/v0.1/)
*   [LangChain Expression Language](/v0.1/docs/expression_language/)
*   How to
*   Add message history (memory)

Add message history (memory)
============================

The `RunnableWithMessageHistory` let's us add message history to certain types of chains.

Specifically, it can be used for any Runnable that takes as input one of

*   a list of `BaseMessage`
*   an object with a key that takes a list of `BaseMessage`
*   an object with a key that takes the latest message(s) as a string or list of `BaseMessage`, and a separate key that takes historical messages

And returns as output one of

*   a string that can be treated as the contents of an `AIMessage`
*   a list of `BaseMessage`
*   an object with a key that contains a list of `BaseMessage`

Let's take a look at some examples to see how it works.

tip

See [this section for general instructions on installing integration packages](/v0.1/docs/get_started/installation/#installing-integration-packages).

*   npm
*   Yarn
*   pnpm

    npm install @langchain/openai

    yarn add @langchain/openai

    pnpm add @langchain/openai

    import { ChatOpenAI } from "@langchain/openai";import {  ChatPromptTemplate,  MessagesPlaceholder,} from "@langchain/core/prompts";import {  RunnableConfig,  RunnableWithMessageHistory,} from "@langchain/core/runnables";import { ChatMessageHistory } from "@langchain/community/stores/message/in_memory";// Instantiate your model and prompt.const model = new ChatOpenAI({});const prompt = ChatPromptTemplate.fromMessages([  ["ai", "You are a helpful assistant"],  new MessagesPlaceholder("history"),  ["human", "{input}"],]);// Create a simple runnable which just chains the prompt to the model.const runnable = prompt.pipe(model);// Define your session history store.// This is where you will store your chat history.const messageHistory = new ChatMessageHistory();// Create your `RunnableWithMessageHistory` object, passing in the// runnable created above.const withHistory = new RunnableWithMessageHistory({  runnable,  // Optionally, you can use a function which tracks history by session ID.  getMessageHistory: (_sessionId: string) => messageHistory,  inputMessagesKey: "input",  // This shows the runnable where to insert the history.  // We set to "history" here because of our MessagesPlaceholder above.  historyMessagesKey: "history",});// Create your `configurable` object. This is where you pass in the// `sessionId` which is used to identify chat sessions in your message store.const config: RunnableConfig = { configurable: { sessionId: "1" } };// Pass in your question, in this example we set the input key// to be "input" so we need to pass an object with an "input" key.let output = await withHistory.invoke(  { input: "Hello there, I'm Archibald!" },  config);console.log("output 1:", output);/**output 1: AIMessage {  lc_namespace: [ 'langchain_core', 'messages' ],  content: 'Hello, Archibald! How can I assist you today?',  additional_kwargs: { function_call: undefined, tool_calls: undefined }} */output = await withHistory.invoke({ input: "What's my name?" }, config);console.log("output 2:", output);/**output 2: AIMessage {  lc_namespace: [ 'langchain_core', 'messages' ],  content: 'Your name is Archibald, as you mentioned earlier. Is there anything specific you would like assistance with, Archibald?',  additional_kwargs: { function_call: undefined, tool_calls: undefined }} *//** * You can see the LangSmith traces here: * output 1 @link https://smith.langchain.com/public/686f061e-bef4-4b0d-a4fa-04c107b6db98/r * output 2 @link https://smith.langchain.com/public/c30ba77b-c2f4-440d-a54b-f368ced6467a/r */

#### API Reference:

*   [ChatOpenAI](https://api.js.langchain.com/classes/langchain_openai.ChatOpenAI.html) from `@langchain/openai`
*   [ChatPromptTemplate](https://api.js.langchain.com/classes/langchain_core_prompts.ChatPromptTemplate.html) from `@langchain/core/prompts`
*   [MessagesPlaceholder](https://api.js.langchain.com/classes/langchain_core_prompts.MessagesPlaceholder.html) from `@langchain/core/prompts`
*   [RunnableConfig](https://api.js.langchain.com/interfaces/langchain_core_runnables.RunnableConfig.html) from `@langchain/core/runnables`
*   [RunnableWithMessageHistory](https://api.js.langchain.com/classes/langchain_core_runnables.RunnableWithMessageHistory.html) from `@langchain/core/runnables`
*   [ChatMessageHistory](https://api.js.langchain.com/classes/langchain_core_chat_history.InMemoryChatMessageHistory.html) from `@langchain/community/stores/message/in_memory`

Pass config through the constructor[​](#pass-config-through-the-constructor "Direct link to Pass config through the constructor")
---------------------------------------------------------------------------------------------------------------------------------

You don't always have to pass the `config` object through the `invoke` method. `RunnableWithMessageHistory` supports passing it through the constructor as well.

To do this, the only change you need to make is remove the second arg (or just the `configurable` key from the second arg) from the `invoke` method, and add it in through the `config` key in the constructor.

This is a simple example building on top of what we have above:

    import { ChatOpenAI } from "@langchain/openai";import {  ChatPromptTemplate,  MessagesPlaceholder,} from "@langchain/core/prompts";import {  RunnableConfig,  RunnableWithMessageHistory,} from "@langchain/core/runnables";import { ChatMessageHistory } from "@langchain/community/stores/message/in_memory";// Construct your runnable with a prompt and chat model.const model = new ChatOpenAI({});const prompt = ChatPromptTemplate.fromMessages([  ["ai", "You are a helpful assistant"],  new MessagesPlaceholder("history"),  ["human", "{input}"],]);const runnable = prompt.pipe(model);const messageHistory = new ChatMessageHistory();// Define a RunnableConfig object, with a `configurable` key.const config: RunnableConfig = { configurable: { sessionId: "1" } };const withHistory = new RunnableWithMessageHistory({  runnable,  getMessageHistory: (_sessionId: string) => messageHistory,  inputMessagesKey: "input",  historyMessagesKey: "history",  // Passing config through here instead of through the invoke method  config,});const output = await withHistory.invoke({  input: "Hello there, I'm Archibald!",});console.log("output:", output);/**output: AIMessage {  lc_namespace: [ 'langchain_core', 'messages' ],  content: 'Hello, Archibald! How can I assist you today?',  additional_kwargs: { function_call: undefined, tool_calls: undefined }} *//** * You can see the LangSmith traces here: * output @link https://smith.langchain.com/public/ee264a77-b767-4b5a-8573-efcbebaa5c80/r */

#### API Reference:

*   [ChatOpenAI](https://api.js.langchain.com/classes/langchain_openai.ChatOpenAI.html) from `@langchain/openai`
*   [ChatPromptTemplate](https://api.js.langchain.com/classes/langchain_core_prompts.ChatPromptTemplate.html) from `@langchain/core/prompts`
*   [MessagesPlaceholder](https://api.js.langchain.com/classes/langchain_core_prompts.MessagesPlaceholder.html) from `@langchain/core/prompts`
*   [RunnableConfig](https://api.js.langchain.com/interfaces/langchain_core_runnables.RunnableConfig.html) from `@langchain/core/runnables`
*   [RunnableWithMessageHistory](https://api.js.langchain.com/classes/langchain_core_runnables.RunnableWithMessageHistory.html) from `@langchain/core/runnables`
*   [ChatMessageHistory](https://api.js.langchain.com/classes/langchain_core_chat_history.InMemoryChatMessageHistory.html) from `@langchain/community/stores/message/in_memory`

* * *

#### Help us out by providing feedback on this documentation page:

[

Previous

Add message history (memory)

](/v0.1/docs/expression_language/how_to/message_history/)[

Next

Cookbook

](/v0.1/docs/expression_language/cookbook/)

Community

*   [Discord](https://discord.gg/cU2adEyC7w)
*   [Twitter](https://twitter.com/LangChainAI)

GitHub

*   [Python](https://github.com/langchain-ai/langchain)
*   [JS/TS](https://github.com/langchain-ai/langchainjs)

More

*   [Homepage](https://langchain.com)
*   [Blog](https://blog.langchain.dev)

Copyright © 2024 LangChain, Inc.