Turn written replies into concise, normalized text that TTS engines can read naturally.
Memory
Elevenlabs Twilio Memory Bridge
Inject persistent caller memory and current context into ElevenLabs agents handling Twilio calls.
What it does
Give ElevenLabs voice agents on Twilio caller-specific context through a FastAPI webhook invoked once per inbound call. It loads hashed caller history, long-term facts, and daily notes from local JSON, combines them with a personality template, then returns system-prompt and first-message overrides. Twilio and ElevenLabs continue to handle audio directly.
When to use it
- Personalized greetings for repeat callers
- Persistent caller facts across inbound calls
- Daily or caller-scoped context injection
- File-backed voice-agent memory without audio proxying
The skill document
elevenlabs-twilio-memory-bridge
Personalization webhook service for ElevenLabs + Twilio voice agents with persistent caller memory.
What It Does
When a call arrives on your Twilio number, ElevenLabs' native integration triggers this webhook. The bridge looks up the caller's history, loads long-term memory facts and daily context notes, combines them with a customizable soul/personality template, and returns everything as a system prompt override so your agent greets each caller with full context.
Architecture
- No audio proxying — ElevenLabs and Twilio handle media directly
- Webhook only — called once per inbound call to inject context
- File-based persistence — JSON files in
./data/, zero external dependencies - OpenClaw compatible — works with any OpenAI-compatible LLM endpoint
Endpoints
| Endpoint | Method | Purpose |
|---|---|---|
/webhook/personalize | POST | ElevenLabs calls this on inbound call |
/webhook/post-call | POST | Optional post-call cleanup |
/api/memory/{phone_hash} | POST | Add long-term fact about a caller |
/api/notes | POST | Add global or caller-scoped context note |
/health | GET | Health check |
Setup
- Clone repo,
pip install -r requirements.txt - Copy
.env.exampleto.env, fill in secrets - Configure ElevenLabs agent with Custom LLM pointing to your OpenClaw instance
- Enable system prompt + first message overrides in agent Security settings
- Add webhook URL
https://your-domain/webhook/personalizein ElevenLabs settings - Import Twilio number in ElevenLabs dashboard
- Run:
uvicorn app:app --host 0.0.0.0 --port 8000
Required Environment Variables
ELEVENLABS_API_KEY— scoped ElevenLabs keyELEVENLABS_AGENT_ID— your agent IDOPENCLAW_API_BASE_URL— your OpenClaw instance URLPUBLIC_BASE_URL— publicly reachable URL of this serviceADMIN_API_KEY— secret for admin endpoint authPHONE_HASH_SALT— salt for phone number hashing. Generate withopenssl rand -base64 32. Changing this invalidates all existing caller data.WEBHOOK_SECRET— shared secret for HMAC webhook verification. Must be set in production.
Optional Environment Variables
| Variable | Default | Purpose |
|---|---|---|
DATA_ENCRYPTION_KEY | (unset) | Fernet key for encrypting memories and notes at rest. Generate with python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())". When unset, data is stored as plain JSON. |
SOUL_TEMPLATE_PATH | ./soul_template.md | Path to personality template file |
DATA_DIR | ./data | Directory for JSON persistence |
ALLOWED_ORIGINS | (unset) | Comma-separated CORS origins |
HOST | 0.0.0.0 | Bind address for uvicorn |
PORT | 8000 | Listen port |
LOG_LEVEL | INFO | Python logging level |
Security
- Deterministic phone hashing — Phone numbers are hashed with HMAC-SHA256 using
PHONE_HASH_SALTas the key before storage. Changing the salt invalidates existing caller data. - Encryption at rest — Memories and notes are encrypted with Fernet when
DATA_ENCRYPTION_KEYis set. Data is stored as plain JSON when the key is not configured. - Mandatory webhook verification —
WEBHOOK_SECRETis required in production. Webhooks are rejected when the secret is not set (fail-closed). - Rate limiting — Admin endpoints (
/api/memory,/api/notes) are limited to 30 requests per minute. Webhook endpoints are limited to 60 per minute. - File locking — JSON reads and writes use POSIX advisory locks (
fcntl) to prevent race conditions under concurrent access. - Restrictive permissions — Data directory (
DATA_DIR) is created with0o700permissions. JSON files are written with0o600. - Secrets from env vars only — No hardcoded credentials in source.
- Safe for public GitHub repos — All sensitive config is loaded from environment variables.
Migration from v1.1.x to v1.2.x
v1.2.0 introduces breaking security changes:
-
PHONE_HASH_SALT is now required — Previously, phone numbers were hashed with unsalted SHA-256. Now HMAC-SHA256 with a salt is required. Existing caller data will be unreachable after upgrading because the hash keys change. You must accept data loss and start fresh (v1.2.0 uses a different hashing algorithm).
-
WEBHOOK_SECRET is now required — Previously optional for development. Now mandatory in all environments. Webhooks without a valid secret are rejected.
-
DATA_ENCRYPTION_KEY is optional but recommended — When set, all new memories and notes are encrypted at rest. Existing unencrypted data remains readable.
Migration checklist
- Generate a salt:
openssl rand -base64 32 - Generate a webhook secret:
openssl rand -hex 32 - Generate an encryption key (optional):
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" - Add all to
.env - Review CORS settings —
ALLOWED_ORIGINSnow defaults to disabled - Update ElevenLabs webhook settings with the new
WEBHOOK_SECRET - Note: v1.2.0 requires fresh data — existing caller sessions will be recreated on first call
Questions people ask
- Does it proxy Twilio call audio?
- No. It is a webhook-only service called once per inbound call; ElevenLabs and Twilio handle media directly.
- How are caller memories stored and protected?
- Memories and notes use JSON files in `./data` by default, with POSIX file locking and restrictive permissions. Phone numbers are keyed with salted HMAC-SHA256, and setting `DATA_ENCRYPTION_KEY` enables Fernet encryption at rest; otherwise data remains plain JSON.
- What must I configure before running it?
- Set the required ElevenLabs, OpenClaw, public URL, admin key, phone-hash salt, and webhook-secret environment variables. Enable system-prompt and first-message overrides in ElevenLabs, register `/webhook/personalize`, import the Twilio number, and run the FastAPI app with uvicorn.
Related skills
Run inbound and confirmed outbound phone workflows with local logs, calendar tools, CRM, contacts, and MCP.
Generate narration, cloned voices, sound effects, and music from text prompts.
Operate Slack messages, channels, users, and conversations through managed OAuth and API calls.
Send messages to configured AI agents and maintain separate multi-turn sessions from the command line.
Manage Instantly campaigns, leads, sending accounts, inbox email, and analytics through API v2.