Verified by the sovseal team

LangChain Agent Memory Integration

Build context-aware AI applications using LangChain for flow and the local-first, zero-knowledge sovseal memory layer.

Integrate LangChain with sovseal to provide your agents with persistent, local-first memory. By exposing the memory node as a set of standard tools, LangChain agents can autonomously decide when to store new facts and recall prior context.

Using the local stdio MCP server transport, your Python or Node.js LangChain application can call the vector store at 0 network RTT, keeping latency under 10ms.

Python Setup

Install the required dependencies:

pip install langchain langchain-openai mcp-client-cli python-dotenv

Exposing sovseal as LangChain Tools

You can connect LangChain to the sovseal-mcp-server using standard MCP tool wrappers. Below is a complete, runnable Python example:

import os
import asyncio
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain.agents import create_openai_functions_agent, AgentExecutor
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from mcp_client import StdioMCPClient  # Standard MCP client implementation

load_dotenv()

async def main():
    # Initialize the local stdio MCP server for sovseal
    async with StdioMCPClient(
        command="npx",
        args=["-y", "@sovseal/mcp-server"]
    ) as mcp_client:
        
        # Load the store_memory and recall_memory tools from the server
        tools = await mcp_client.get_langchain_tools()
        
        # Set up ChatOpenAI model
        llm = ChatOpenAI(model="gpt-4o", temperature=0)
        
        # Create prompt template incorporating memory context
        prompt = ChatPromptTemplate.from_messages([
            ("system", "You are a personalized assistant. Use the recall_memory tool first to gather user preferences."),
            MessagesPlaceholder(variable_name="chat_history"),
            ("human", "{input}"),
            MessagesPlaceholder(variable_name="agent_scratchpad"),
        ])
        
        # Construct the agent
        agent = create_openai_functions_agent(llm, tools, prompt)
        agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
        
        # Run a session
        await agent_executor.ainvoke({
            "input": "My favorite programming language is TypeScript. Remember that.",
            "chat_history": []
        })
        
        # Retrieve preference in a separate query
        response = await agent_executor.ainvoke({
            "input": "What programming language do I prefer?",
            "chat_history": []
        })
        print("Agent Response:", response["output"])

if __name__ == "__main__":
    asyncio.run(main())

TypeScript Setup

In Node.js or Bun environments, you can integrate with the @sovseal/sdk directly:

npm install langchain @sovseal/sdk @langchain/openai

Implementing a Custom Memory Class

Implement a custom memory class that calls the AgentStateClient to snapshot state:

import { BaseChatMemory, type InputValues, type OutputValues } from "langchain/memory";
import { AgentStateClient } from "@sovseal/sdk";

export class SovsealMemory extends BaseChatMemory {
  private client: AgentStateClient;
  private agentId: string;
  private encryptionKey: CryptoKey;

  constructor(fields: { endpoint: string; apiKey: string; agentId: string; encryptionKey: CryptoKey }) {
    super();
    this.client = new AgentStateClient({ endpoint: fields.endpoint, apiKey: fields.apiKey });
    this.agentId = fields.agentId;
    this.encryptionKey = fields.encryptionKey;
  }

  get memoryKeys() {
    return ["history"];
  }

  async loadMemoryVariables(_values: InputValues): Promise<Record<string, any>> {
    try {
      const { receipt } = await this.client.restore({ agentId: this.agentId });
      // Decrypt and return context
      return { history: receipt.active_context || "" };
    } catch {
      return { history: "" };
    }
  }

  async saveContext(inputValues: InputValues, outputValues: OutputValues): Promise<void> {
    const text = `User: ${inputValues.input}\nAssistant: ${outputValues.output}`;
    await this.client.snapshot({
      key: this.encryptionKey,
      payload: {
        agent_id: this.agentId,
        sequence_number: Date.now(),
        parent_snapshot: null,
        policy_hash: "0".repeat(64),
        active_context: { content: text },
        timestamp: new Date().toISOString(),
      }
    });
  }
}

On this page