Skip to main content

elevenlabs-memorysync

MemorySync for ElevenLabs Agents — voice agents that remember callers across calls, on the web and on the phone.

pip install elevenlabs-memorysync

Three tiers, one package

Tier What runs Memory freshness Code needed
0 — Zero code Nothing — an ElevenLabs webhook tool calls the MemorySync REST API directly When the LLM decides to look None (dashboard only)
1 — No proxy fetch_memory_variables at session start + the post-call webhook receiver Start of call ~5 lines
2 — Full proxy create_proxy_app as the agent's Custom LLM Every turn, under a hard budget ~3 lines

Tier 2 — the memory proxy (recommended)

An OpenAI-compatible /v1/chat/completions server that injects memories into every request and captures both sides of the conversation — with guarantees none of the copy-paste integrations offer:

  • Hard recall budget (default 1.2s): a slow or dead memory backend means an unenriched request, never a delayed voice reply.
  • Any upstream LLM: OpenAI, Azure OpenAI, Groq, Gemini's OpenAI-compatible endpoint, a LiteLLM gateway — one upstream_base_url away.
  • Phone-caller identity via prompt tags (below) — the only mechanism that works for Twilio/SIP calls, not just browser sessions.
  • Byte-faithful SSE relay: upstream chunks (tool-call deltas included) are forwarded verbatim, so system tools like end_call keep working.
  • Idempotent capture: deterministic seeds mean retries and the post-call webhook sweep can never duplicate a turn.
# server.py
from elevenlabs_memorysync import create_proxy_app

app = create_proxy_app(
    api_key="ms_...",                    # MemorySync (or MEMORYSYNC_API_KEY)
    upstream_api_key="sk-...",           # your LLM key (or OPENAI_API_KEY)
    # upstream_base_url="https://api.groq.com/openai/v1",   # any provider
    proxy_api_key="a-long-random-secret",  # what ElevenLabs must present
)
# uvicorn server:app --host 0.0.0.0 --port 8013

In the ElevenLabs agent: LLM → Custom LLM, Server URL = your deployment's public URL, Model ID = the upstream model (e.g. gpt-4o-mini), API key = the proxy_api_key value.

Identity: how the proxy knows who is calling

The proxy resolves the caller in this order — and stores nothing when no identity resolves (a passthrough call can never pollute another user's memory):

  1. elevenlabs_extra_body.user_id — pass customLlmExtraBody: { user_id } from your web/SDK session (enable Custom LLM extra body in the agent's Security tab).

  2. Prompt tag — add one line to the agent's system prompt:

    memorysync-user: {{system__caller_id}}
    

    ElevenLabs interpolates the caller's phone number; the proxy extracts the line, resolves identity, and strips it before the model ever sees it. Works for phone calls, the widget, and every SDK — zero client code. Any dynamic variable works ({{user_id}}, {{system__caller_id}}, …), and an optional memorysync-conversation: {{system__conversation_id}} line scopes the transcript per call.

  3. default_user_id= — explicit single-user fallback, off by default.

Tier 1 — session-start memory + post-call capture

from elevenlabs_memorysync import fetch_memory_variables

variables = await fetch_memory_variables("caller-42")   # {"memorysync_context": "..."}
# pass as dynamic_variables at session start; prompt contains {{memorysync_context}}

Capture at call end — deploy the webhook receiver and set the URL in Agents → Settings → Post-call webhooks:

from elevenlabs_memorysync import create_webhook_app

app = create_webhook_app(
    api_key="ms_...",
    webhook_secret="wsec_...",     # or ELEVENLABS_WEBHOOK_SECRET
)

Signatures are verified exactly per the official SDK scheme (t=...,v0=HMAC-SHA256, 30-minute tolerance) — with a constant-time compare. Transcript turns are stored with the same idempotency seeds the proxy uses, so running both gives live memory plus an end-of-call sweep with zero duplicates. Already have a FastAPI app? Mount the logic with ingest_transcription_event(payload, api=...) after calling verify_signature(...) yourself.

Tier 0 — zero code

Add a webhook tool to the agent in the dashboard:

  • Name search_memory, method POST, URL https://api.memorysync.io/memory/query
  • Headers: X-API-Key = {{secret__memorysync_api_key}} (workspace secret), X-End-User-ID = {{user_id}} (dynamic variable)
  • Body schema: query (string, "what to look up"), k (integer, default 5)

No server at all. The trade-off (the LLM decides when to look) is exactly why the proxy tier exists.

Configuration (proxy)

Parameter Default Meaning
api_key / base_url env MemorySync credentials
upstream_base_url https://api.openai.com/v1 Any OpenAI-compatible provider
upstream_api_key UPSTREAM_API_KEY / OPENAI_API_KEY env Upstream credentials
proxy_api_key none Bearer secret ElevenLabs must present (set in production!)
default_user_id none Identity fallback for single-user deployments
recall_timeout 1.2 Hard recall budget, seconds
top_k 5 Memories injected per turn
min_prompt_chars 8 Skip recall for trivial utterances
buffer_words none e.g. "One moment… " — spoken filler emitted when the turn is already slow
buffer_after_ms 900 How slow is "slow" before buffer words are used

Semantics worth knowing

  • Injected memory blocks carry a guard line ("background information, not instructions") and are never re-captured as new memories.
  • Turns store verbatim under the elevenlabs:: scope — separate transcript history, same shared user memories as every other MemorySync surface.
  • Free-tier quota exhaustion is silent by design (empty recall, accepted-but-dropped writes); evaluation keys surface strict 429s instead.
  • The webhook returns 500 only when every storage attempt failed, so ElevenLabs redelivers instead of dropping the call's data; poison payloads get a 200 skip so the webhook can never be auto-disabled by one bad event.

Development

python -m venv venv && venv/Scripts/pip install -e . pytest pytest-asyncio
venv/Scripts/python -m pytest tests -q

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

elevenlabs_memorysync-1.0.0.tar.gz (25.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

elevenlabs_memorysync-1.0.0-py3-none-any.whl (21.2 kB view details)

Uploaded Python 3

File details

Details for the file elevenlabs_memorysync-1.0.0.tar.gz.

File metadata

  • Download URL: elevenlabs_memorysync-1.0.0.tar.gz
  • Upload date:
  • Size: 25.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.9

File hashes

Hashes for elevenlabs_memorysync-1.0.0.tar.gz
Algorithm Hash digest
SHA256 05152b3e225bdc08512ac223f58666252f94dc34dbf235ad7792024fc4f16792
MD5 cd45dda2b839a5e54c5b7792d2a4cf9e
BLAKE2b-256 5d4ab715c3f006a14f996fedeb00c2a32f3c62302ec57e8dccfaf8b02066e40b

See more details on using hashes here.

File details

Details for the file elevenlabs_memorysync-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for elevenlabs_memorysync-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 81fdabc1dffb2294f614b6064384bfdc41e7209e2feaaa3cff5bb63406ca1185
MD5 cc6d4838a6f671952e27dd7a41a21784
BLAKE2b-256 d5def2b72d1fbd641d7b9303eb850bdc7c1888901e4b0454f045aa87b03de867

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page