MemorySync
Getting Started

OpenAI Agents SDK Memory

The first drop-in Session implementation from any memory vendor: durable server-side conversation history for Runner.run(..., session=...) that survives restarts and follows multi-agent handoffs — plus per-run memory instructions, five agent memory tools, and async helpers.

What the integration provides

LayerWhat it does
MemorySyncSessionA drop-in implementation of the SDK’s Session protocol: the runner reads history before each run and appends the new turn after it — stored durably server-side, byte-for-byte, shared across handoffs. User/assistant text also lands in long-term memory automatically.
memory_instructionsDynamic instructions that inject recalled memory context per run — the SDK’s documented hook for dynamic system prompts.
Agent toolscreate_memory_tools() — five structured tools (add, search, list, update, delete) the model can call, which never raise.
Helpersget_memory_context, search_memories, save_turn — async, for hand-wired setups.
Mem0SupermemoryZepMemorySync
Session protocol implementation✗ docs recipe only✗ nothing shipped✗ example file only✓ the first drop-in session=...
Automatic history across handoffs✗ manual saves in outer code✗ manual add_message per turn✓ free with a correct Session
Long-term memory extraction✓ (tools — the LLM decides)✓ (~10s graph delay)✓ automatic, deterministic
Retry-safe transcript writes✓ total AND partial batch failures converge
Pattern2 toolsmanager class + instructions pastesession + instructions + 5 tools + helpers

Install

pip install openai-agents-memorysync openai-agents

Set MEMORYSYNC_API_KEY in the environment, or pass api_key explicitly. The package never imports the Agents SDK at runtime (the Session contract is a structural protocol), so it never constrains which SDK version you run — openai-agents is a peer you install alongside it. Python 3.10+. This is a Python surface — for TypeScript agents use the Vercel AI SDK or Mastra integrations.

The drop-in session

from agents import Agent, Runner
from openai_agents_memorysync import MemorySyncSession
agent = Agent(
name="Assistant",
instructions="You are a helpful assistant.",
)
session = MemorySyncSession(
"thread-42", # the conversation
user_id="customer-7", # the end user it belongs to — required
)
# First conversation
await Runner.run(agent, "I'm vegetarian and I fly aisle.", session=session)
# Any later run — same session id, any process, any deploy
result = await Runner.run(
agent, "Book my trip: flight plus a dinner spot.", session=session
)
# The model saw the full prior history — no manual .to_input_list() plumbing.

Items are stored and returned byte-for-byte — assistant messages, function calls, tool outputs, reasoning items — because the runner feeds them straight back to the model. Each session lives in its own server-side namespace, so clear_session() can only ever reach that one conversation, and function-call JSON never pollutes the user’s long-term memories.

Multi-agent handoffs

from agents import Agent, Runner
from openai_agents_memorysync import MemorySyncSession
specialist = Agent(
name="Specialist",
instructions="You handle travel bookings end to end.",
)
triage = Agent(
name="Triage",
instructions="Route travel questions to the specialist.",
handoffs=[specialist],
)
session = MemorySyncSession("thread-42", user_id="customer-7")
# The handoff happens INSIDE one run — triage and specialist share
# this session, and the handoff itself is part of the transcript.
result = await Runner.run(triage, "Book my usual trip.", session=session)
# A later run — by any agent — gets the full cross-agent history.
await Runner.run(specialist, "Add a dinner reservation.", session=session)

The Agents SDK shares one session across every agent in a run — so with a correct Session implementation, cross-handoff memory needs no extra code. No competitor offers this: their patterns save manually after each turn in outer code.

Long-term memory in instructions

from agents import Agent, Runner
from openai_agents_memorysync import memory_instructions
agent = Agent(
name="Assistant",
instructions=memory_instructions(
"You are a helpful assistant.",
user_id="customer-7",
),
)
# Every run now starts with what MemorySync knows about this user:
# You are a helpful assistant.
#
# Relevant memories about this user from previous conversations:
# - human: I'm vegetarian and I fly aisle.
# Multi-user servers resolve identity per request instead:
agent = Agent(
name="Assistant",
instructions=memory_instructions(
"You are a helpful assistant.",
user_id=lambda ctx: ctx.context.user_id, # your context object
),
)

Recall failing means the run proceeds with the base instructions — reported through onError, never thrown. Modes: "profile" (default — an overview of the user), "query" (recall for text your prompt resolver returns), "full" (both). Pair it with a MemorySyncSession and the exchange persists automatically; the two surfaces share idempotency seeds, so nothing double-stores.

Agent memory tools

from agents import Agent, Runner
from openai_agents_memorysync import create_memory_tools
agent = Agent(
name="Assistant",
instructions="Use the memory tools to remember durable facts.",
tools=create_memory_tools(user_id="customer-7"),
)
await Runner.run(agent, "Remember that I prefer aisle seats.")
# Untrusted agents: search + list only.
create_memory_tools(user_id="customer-7", read_only=True)
ToolWhat it doesFailure behaviour
add_memorySave one durable fact; duplicate saves answer “already stored”.Readable error string — never raises.
search_memorySemantic search with relevance scores.Readable error string.
list_memoriesNewest-first listing.Readable error string.
update_memoryChange tags/importance. Memory text is immutable.Readable error string.
delete_memoryPermanent delete by id, scoped to the configured user.Readable error string.

Same five operations, same response strings as the LangChain, AI SDK, CrewAI and Mastra tool sets — an agent moved between frameworks keeps behaving the same way. All tools are async, so they never block the runner’s event loop.

Standalone helpers

For hand-wired setups: the same recall pipeline and the same idempotent persistence as the session, callable directly. Mixing styles is safe — every surface writes the same idempotency seeds.

from openai_agents_memorysync import (
get_memory_context,
save_turn,
search_memories,
)
# 1. Prompt-ready context block ("" for a new user)
context = await get_memory_context(
"what should I cook?", user_id="customer-7"
)
# 2. Scored raw results
hits = await search_memories("dietary preferences", user_id="customer-7")
# [{"id": "m_123", "text": "human: I'm vegetarian", "score": 0.62}, ...]
# 3. Explicit persistence — RAISES on failure (an explicit call is
# owed the truth), unlike the session's degrading long-term plane.
await save_turn(
user_id="customer-7",
user="I'm vegetarian",
assistant="Noted!",
session_id="thread-42",
)

Public API

ExportKindNotes
MemorySyncSessionSession classsession_id + required user_id; long_term, allow_clear, on_error optional. Implements get_items, add_items, pop_item, clear_session.
memory_instructionsInstructions factoryuser_id (string or per-run resolver); mode, k, template, prompt, on_error optional.
create_memory_toolsTool factoryFive @function_tools; read_only=True returns search + list only.
get_memory_contextAsync helperPrompt-ready context block, "" for a new user.
search_memoriesAsync helperScored {id, text, score} results.
save_turnAsync helperExplicit idempotent persist — raises on failure.
MemorySyncAPIErrorExceptionCarries the HTTP status and server detail.

Supported versions

PackageRegistryRequiresRuntime
openai-agents-memorysync 1.0.0PyPIopenai-agents installed alongside (any current 0.x — no version pin by design)Python 3.10+

The test suite drives a REAL Runner — including an item-for-item parity oracle against OpenAI’s own SQLiteSession — and CI re-runs it against the latest openai-agents release on every push, so a protocol change upstream fails our pipeline before it can fail your agent.

Where to go next

Was this page helpful?