Framework adapters
One portable brain, dropped into React, the Vercel AI SDK, or LangChain — recall, ground, and remember with provenance, no plumbing.
The framework adapters ("Brain Everywhere") let you plug a ThinkingRoot
brain into the AI stack you already use. Instead of wiring fetch calls and
reshaping responses by hand, you get first-class hooks, middleware, and
retrievers that speak one portable Memory Moment contract — every recalled
memory carries its provenance (which claim, which source, which bytes), and
every answer is grounded or it abstains.
Availability. These four packages are in preview. They are built and
unit-tested but are not yet on the public npm registry — the install lines
below are how you'll consume them once published. The underlying brain they
adapt (recall / ground / remember) is live today via
@thinkingroot/sdk and the REST API.
The four packages
| Package | For | What you get |
|---|---|---|
@thinkingroot/memory | every adapter | The Brain contract + MemoryMoment / Witness / GroundedAnswer types. Zero runtime dependencies. |
@thinkingroot/react | React / Next.js | useRecall · useAsk · useRemember · useBrain hooks. |
@thinkingroot/ai-sdk | Vercel AI SDK | withMemory() middleware — auto-grounds any model call. |
@thinkingroot/langchain | LangChain.js | ThinkingRootRetriever (cited Documents) + ThinkingRootMemory. |
They are thin adapters over the SDK — no engine logic is re-implemented.
You always start from a Brain, which you get from a project key:
import { thinkingroot } from "@thinkingroot/sdk";
import { brainFromScope } from "@thinkingroot/memory";
const tr = thinkingroot({
gatewayUrl: "https://api.thinkingroot.com",
projectKey: "tr_sk_…",
});
// A per-end-user brain — recall/remember land in that user's private namespace.
const brain = brainFromScope(tr.scope(userId));Use a per-user brain (brainFromScope(tr.scope(userId))) when you want
isolated, writable memory per end-user. A workspace brain
(brainFromWorkspace(tr.brain("main"))) is shared and read-mostly — it can
ask and manage branches, but per-user recall/remember throw a
BrainCapabilityError (honest by design, never a silent no-op).
The Memory Moment contract
Every adapter speaks the same shape, so a memory means the same thing in React, in a middleware, or in a LangChain chain:
interface MemoryMoment {
id: string; // the claim id
statement: string; // the fact, in plain text
kind?: string; // claim type
source?: string; // where it came from
confidence?: number;
}
interface GroundedAnswer {
text: string;
witnesses: Witness[]; // citations: claimId, source, byte range, hash
grounded: boolean; // false when the brain abstained
confidence: number;
claimsUsed: number;
}grounded is true only when the answer is backed by recalled claims. When the
brain has no evidence it abstains (grounded: false) rather than confabulating.
React
import { useRecall, useAsk } from "@thinkingroot/react";
function Suggestions({ brain, query }) {
const { moments, loading } = useRecall(brain, { query, topK: 6 });
if (loading) return <Spinner />;
return (
<ul>
{moments.map((m) => (
<li key={m.id}>{m.statement}</li>
))}
</ul>
);
}
function Answer({ brain }) {
const { ask, answer, witnesses } = useAsk(brain);
return (
<>
<button onClick={() => ask("what does this user prefer?")}>Ask</button>
{answer && <p>{answer.text}</p>}
{witnesses.map((w) => (
<cite key={w.claimId}>{w.source}</cite>
))}
</>
);
}The race-safety (last-query-wins) and error handling live in framework-agnostic
stores, so the hooks stay tiny. useRemember(brain) writes a fact back to the
user's brain; useBrain(...) builds a memoized brain from a scope.
Vercel AI SDK
withMemory() is a LanguageModelV2 middleware: it recalls on the user's last
turn and prepends a grounded system message before the model runs — so it
works regardless of how you structure your messages.
import { wrapLanguageModel } from "ai";
import { openai } from "@ai-sdk/openai";
import { withMemory } from "@thinkingroot/ai-sdk";
const model = wrapLanguageModel({
model: openai("gpt-4o"),
middleware: withMemory(brain, { topK: 6, remember: true }),
});
// Every generateText/streamText call is now grounded in the user's memory.Recall failure is fail-loud by default (pass onError to soften it). With
remember: true it stores the user's turn only — never the model's answer,
so the brain never learns from its own ungrounded output.
LangChain.js
import { ThinkingRootRetriever, ThinkingRootMemory } from "@thinkingroot/langchain";
// A cited retriever for a RAG chain — hits are Documents with provenance.
const retriever = new ThinkingRootRetriever({ brain, topK: 6 });
const docs = await retriever.invoke("what does this user prefer?");
// docs[0].metadata = { claimId, source, kind, confidence }
// Or as conversation memory: loads grounded context, remembers the user's turn.
const memory = new ThinkingRootMemory({ brain, memoryKey: "memory" });@langchain/core is a peer dependency; the retriever maps each
MemoryMoment to a Document whose metadata carries the citation.
Why this matters
Every framework has won its lane — MCP for tools, A2A for agent-to-agent, the Vercel AI SDK and LangChain for orchestration — and all of them deliberately leave persistent, verifiable memory undefined. These adapters make ThinkingRoot that memory: one brain, the same grounded-and-cited contract, reachable from wherever your agent already runs.
For the raw client these build on, see Clients & SDKs.