generateText, streamText, and generateObject all keep working — the middleware just makes them memory-aware.
Runtime: Node.js 18+ only. The JS SDK wraps the Python SDK as a subprocess, so it needs Python 3.11+ on the host and does NOT run on Edge / Cloudflare Workers / Bun / Deno / Lambda-Node-only. On Next.js, pin the route to runtime = “nodejs”.
Overview
This guide shows how to add Synap to a Vercel AI SDK application to build apps that:- Inject relevant memory before every
generateText/streamText/generateObjectcall - Record completed turns back to Synap automatically
- Work with any provider — OpenAI, Anthropic, Google, etc. — without per-provider plumbing
| Export | Purpose |
|---|---|
createSynap | Async factory that initializes the Synap provider |
SynapProvider | Provider class with wrap and listen methods |
Setup
Install the package:Import the integration from its package name directly:
import { createSynap } from "@maximem/synap-vercel-adk". createSynap initializes the underlying Synap SDK for you, so you don’t import the core @maximem/synap-js-sdk package separately..env
createSynap initializes the underlying Synap SDK internally — you don’t need to manage the SDK lifecycle separately. See SDK Initialization for the full lifecycle if you’d rather construct the SDK directly.
Basic integration
The smallest useful integration wraps a model withsynap.wrap and uses it like any other Vercel AI SDK model:
Core concepts
synap.wrap
synap.wrap(model, options) returns a standard Vercel AI SDK LanguageModel. Drop it anywhere you’d use the underlying model — generateText, streamText, generateObject, agentic loops, structured output, etc.
wrap — the model only ever sees the messages, never userId/customerId. This means prompt injection cannot spoof scope.
The middleware loop
On every call to the wrapped model:- Before — fetches the user’s Synap context and injects it as a system message.
- Generates — proxies the request to the wrapped model unchanged.
- After — ingests the completed user + assistant turn into Synap asynchronously.
Provider-agnostic
Wrap any Vercel AI SDK-compatible model:Streaming
streamText and streamObject work without any code changes — the middleware injects context before the stream starts and ingests the turn when the stream ends:
Complete example: chat route with per-request scoping
The pattern below is a typical Next.js (Node runtime) chat route. Each request gets its own scope baked into a freshly-wrapped model, so multiple concurrent users cannot leak into each other’s memory:- The provider is module-scoped, the model is request-scoped.
createSynapruns once;synap.wrapruns per request with the rightuserId. - Streaming is unchanged. No special integration needed —
streamTextand the middleware co-exist transparently. - The
runtime = "nodejs"pin matters. Edge Runtime would break the Python-subprocess dependency.
Advanced patterns
Per-request scoping
For multi-tenant services, build the wrapped model per request and never cache it across users:Anticipation stream
synap.listen() opens a gRPC stream that pre-fetches context speculatively before the user’s next request arrives. This reduces perceived latency in long-lived server processes where you can predict who will message next:
Multi-tenant scoping
synap.wrap accepts the standard scoping triple — userId (required), optional customerId, optional conversationId. customerId is required on B2B Synap instances and ignored on single-tenant ones. See Memory Scopes.
Failure semantics
The middleware follows the Synap-wide contract:- Context fetch degrades gracefully — empty context is injected and the error logged if Synap is unreachable.
- Turn ingestion surfaces failures — write failures raise
SynapIntegrationErrorso callers know if persistence failed.
Going further
- Patterns overview — reusable memory patterns across frameworks.
- Cookbook overview — end-to-end worked examples.
Next steps
Mastra
SynapMemory and tools for Mastra.Claude Agent SDK
Hooks and MCP server for the Claude Agent SDK.
Context Fetch
The retrieval API behind
synap.wrap — modes, scopes, and response shapes.Memory Scopes
How
userId, customerId, and conversationId interact across reads.