Skip to main content
Build LangChain applications that remember context across sessions. Synap handles memory ingestion, retrieval, and per-user scoping; LangChain handles your chain or agent.
Requires Python 3.11+.

Overview

This guide shows how to add Synap to a LangChain application to build agents that:
  • Maintain conversation history across sessions and processes
  • Retrieve user- and organization-scoped context as part of a RAG pipeline
  • Decide for themselves when to search or store memories
The Synap LangChain integration ships four drop-in components. Each one slots into a native LangChain interface so you do not have to wrap or re-implement anything.

Setup

Install the package alongside LangChain and your model provider:
The pip package is maximem-synap-langchain, but the import drops the maximem- prefix and uses underscores: from synap_langchain import ....
Configure your API key. Generate one from the Synap Dashboard.
.env
Then initialize the SDK once at application startup:
See SDK Initialization for the full lifecycle and configuration options.

Basic integration

The smallest useful integration is a chain with automatic memory via SynapCallbackHandler. Every turn is ingested without changing your chain logic:
The handler observes the chain via LangChain’s callback system, captures the user/assistant pair, and ingests it into Synap asynchronously. Ingestion failures are logged at ERROR level and never propagate to your chain. Your application keeps running even if Synap is unreachable. This is the smallest viable setup. To make the model aware of memory at inference time, combine the callback with SynapChatMessageHistory and/or SynapRetriever below.

Core concepts

Persistent chat history

SynapChatMessageHistory implements LangChain’s BaseChatMessageHistory interface. Wrap any chain with RunnableWithMessageHistory to give it conversation memory that survives restarts:
Each session_id maps one-to-one to a Synap conversation_id. Messages are persisted on every turn and replayed on the next invocation.

Automatic ingestion

SynapCallbackHandler covers a different need: it does not feed history into the model, it records every turn for long-term memory. Use it whenever you want a chain’s output to enrich the user’s profile and become searchable later.
You can attach the handler to a single invocation (as above) or globally with chain.with_config(callbacks=[handler]).

Semantic retrieval

SynapRetriever implements BaseRetriever. Use it inside ConversationalRetrievalChain, create_retrieval_chain, or any RAG pipeline that expects a retriever:
The two retrieval modes trade latency against comprehensiveness: fast is lower-latency and suited to the hot path; accurate adds LLM-driven query decomposition and reranking for relationship-aware queries at a higher latency cost. See Context Fetch for the full retrieval contract.

Agent-callable memory

For agent-style chains where the model decides when memory is relevant, expose SynapSearchTool and SynapStoreTool:
The tools surface as synap_search and synap_store in the model’s tool-calling schema, with descriptions that nudge the model toward calling them when context is needed.

Complete example: support assistant with memory

The following class assembles all four components into a single agent. It remembers conversation history, retrieves user-specific context, and lets the model store new facts explicitly.
Three things to notice in this pattern:
  1. SynapChatMessageHistory keeps the chain itself stateful turn-to-turn.
  2. SynapRetriever injects per-user long-term context as a system message, independent of the chat history.
  3. SynapCallbackHandler persists each turn back to Synap so future invocations can retrieve it.
You can drop any one of these and still have a working agent. Adding all three gives you a memory loop that improves over time.

Advanced patterns

Multi-tenant scoping

Every component accepts the same scoping triple: user_id, optional customer_id, and optional conversation_id:
customer_id is required for B2B Synap instances and ignored on single-tenant instances. See Memory Scopes for the full hierarchy.

Combining automatic and explicit memory

The four components compose freely. A common production setup:
  • SynapChatMessageHistory for the running conversation buffer
  • SynapCallbackHandler for long-term ingestion (runs in parallel with history)
  • SynapRetriever injected as a system message before each turn
  • SynapSearchTool exposed to the model for explicit lookups when retrieval misses
The callback handler and the retriever do not conflict: the handler writes, the retriever reads. The chat-history component is orthogonal to both: it stores raw messages for replay, while the handler ingests structured memories.

Tuning retrieval mode per call

SynapRetriever accepts a default mode at construction time, but the underlying sdk.conversation.context.fetch() call accepts a mode override too. For a single high-recall query inside an otherwise low-latency agent, swap the retriever’s mode temporarily:

Failure semantics

The Synap integration follows the Synap-wide contract:
  • Retrieval failures degrade gracefully: SynapRetriever returns [] and logs an error
  • Callback failures degrade gracefully: SynapCallbackHandler logs an ERROR and your chain continues
  • Explicit tool calls surface failures: SynapSearchTool / SynapStoreTool raise SynapIntegrationError so the model can react
This is by design: the read path should never break a user-facing turn, while the write path must surface errors so callers know when persistence failed.

Going further


Next steps

LangGraph

Checkpointer and cross-thread store for LangGraph state graphs.

Context Fetch

The retrieval API that powers SynapRetriever: fast vs accurate, scopes, and response shapes.

Ingestion

Direct ingestion API for custom pipelines that need finer control than the callback handler.

Memory Scopes

How user_id, customer_id, and conversation_id interact across retrievals.