OpenAI Assistants
Use Brain as the long-term memory layer for the OpenAI Assistants API — expose encode / recall as function tools and dispatch them to the SDK.
The pattern
Assistants threads hold the current session's messages — good for "what did the user just say?" but they don't survive thread rotation and don't support recall across history. Brain fills that gap.
When the user shares a fact, the agent calls brain_encode. When it needs
context, it calls brain_recall. Threads stay ephemeral; cross-session
continuity comes from Brain.
Tool definitions
Define two function tools on the assistant. The names are your own — pick clear, intent-revealing ones:
tools = [
{
"type": "function",
"function": {
"name": "brain_encode",
"description": (
"Save a lasting fact, preference, or event to the user's "
"long-term memory. Use whenever the user shares something worth "
"remembering across sessions."
),
"parameters": {
"type": "object",
"properties": {"text": {"type": "string"}},
"required": ["text"],
},
},
},
{
"type": "function",
"function": {
"name": "brain_recall",
"description": (
"Answer a question from the user's long-term memory. Returns the "
"memories that answer the cue, or nothing when unknown."
),
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string"},
"max_results": {"type": "integer", "default": 5, "minimum": 1, "maximum": 100},
},
"required": ["query"],
},
},
},
]Wire them into the assistant:
import openai
from brain_db_sdk import BrainHttpClient
oai = openai.OpenAI()
brain = BrainHttpClient(os.environ["BRAIN_API_KEY"])
assistant = oai.beta.assistants.create(
model="gpt-4o",
instructions=(
"You have long-term memory through the brain_* tools. Save important "
"facts with brain_encode. Recall prior memory with brain_recall before "
"answering questions about the user."
),
tools=tools,
)When a run requires action, dispatch the calls to the SDK:
import json
def handle_tool_call(call):
args = json.loads(call.function.arguments)
if call.function.name == "brain_encode":
r = brain.encode(args["text"])
return f"stored {r.memory_id}"
if call.function.name == "brain_recall":
a = brain.recall(args["query"], max_results=args.get("max_results", 5))
if a.answer_kind == "none":
return "don't know"
return "\n".join(m.text for m in a.memories)
raise ValueError(f"unknown tool: {call.function.name}")The TypeScript pattern is identical with openai.beta.assistants and
BrainHttpClient from @brain-db/sdk.
Tool-driven vs pre-fetched
Two ways to get memory into a run:
- Tool-driven — let the agent call
brain_recallwhen it decides it needs context (above). Highest fidelity; every tool call adds tokens. - Pre-fetched — at the start of each run, call
brain.recall(...)yourself and inject the memory texts into the run'sadditional_instructions. Cheaper per run, but the agent can't iteratively refine what it recalls.
Most deployments do both: pre-fetch a default block and expose brain_recall
for follow-up.
Cleanup at thread end
When a thread is deleted, optionally recall its accumulated memories, summarize
them with your LLM, and encode the summary as one durable memory — see the
Session summary recipe.
Was this page helpful?