recall-livekit
Long-term memory for LiveKit Agents voice agents, backed by Recall by Polign.
The agent loads everything it knows about the caller before the first reply,
and the model saves new facts through a remember tool. Facts are typed:
each one is a predicate from a closed registry with a value, so "call me Sam"
replaces the old name instead of piling up a second one, and the history of
the change is kept. No second model runs on the read path, and no embedding
service is needed.
pip install recall-livekit "livekit-agents[openai,deepgram,cartesia,silero]"
That is the whole install. pip also brings the
polign_db package with the polign
CLI and polign-server binaries for Linux, macOS and Windows, so there is no
separate database to download, and a worker image needs nothing beyond
pip install.
Usage
from livekit.agents import AgentServer, AgentSession, JobContext, JobProcess, cli
from livekit.plugins import cartesia, deepgram, openai, silero
from recall_livekit import VOICE_REGISTRY, RecallAgent, RecallMemory
server = AgentServer()
def setup(proc: JobProcess) -> None:
# one Recall subprocess per worker process
proc.userdata["recall"] = RecallMemory.open(
local_dir="./recall-data", # the database lives here
predicates=VOICE_REGISTRY, # or your own registry file
)
server.setup_fnc = setup
@server.rtc_session()
async def entrypoint(ctx: JobContext) -> None:
participant = await ctx.wait_for_participant()
memory = ctx.proc.userdata["recall"].for_subject(participant.identity)
session = AgentSession(
stt=deepgram.STT(), llm=openai.LLM(model="gpt-4.1-mini"),
tts=cartesia.TTS(), vad=silero.VAD.load(),
)
await session.start(
agent=RecallAgent(
memory=memory,
instructions="You are the support line for Acme. Use what you remember about the caller.",
),
room=ctx.room,
)
if __name__ == "__main__":
cli.run_app(server)
What happens on a call:
on_enterloads the caller's current beliefs and appends them to the instructions inside a<recall_memory>block, before the greeting.- The caller says "actually call me Sam, and I moved to Denver". The model
calls
remembertwice. Recall supersedes the old name and timezone, and the agent rewrites its instructions so the next sentence already uses Sam. - A week later the same identity calls back and step 1 finds the facts.
Nothing is searched per turn. A caller's typed facts are a short list, so the
whole set fits in the prompt. When a caller has more beliefs than limit
(default 20), each user turn also runs a search and adds matching facts to
that turn only.
Where the memory is stored
local_dir="./recall-data" keeps the database on the worker's machine. The
first worker process to open the directory starts a polign-server for it in
the background, listening on localhost only, and every other process shares
that server. It keeps running between worker restarts; its process id is in
recall-data/runtime.json and its log in recall-data/server.log. This is
the quickest way to try the package and is fine for a single machine. It works
on Linux and macOS.
Workers on several machines need one shared server. Run polign-server
somewhere they can all reach (Get started
shows how, including storing into S3, GCS or Azure), then connect to it
instead:
RecallMemory.open(
url="http://memory.internal:23000", # or POLIGN_URL in the environment
api_key=os.environ["POLIGN_API_KEY"],
predicates=VOICE_REGISTRY,
)
Your own Agent subclass
from recall_livekit import attach
agent = FrontDesk() # any Agent with string instructions
await attach(agent, memory, who="the guest")
await session.start(agent, room=ctx.room)
attach adds the memory block and the remember tool. It does not do the
per-turn search for overflowing callers; use RecallAgent for that.
Options
| Where | Option | Default | What it does |
|---|---|---|---|
RecallMemory.open |
local_dir |
none | Keep the database in this directory and run its server; exclusive with url and api_key |
RecallMemory.open |
url, api_key, collection, predicates |
worker environment | Connection for the subprocess (POLIGN_URL, POLIGN_API_KEY, POLIGN_COLLECTION, POLIGN_PREDICATES) |
RecallMemory.open |
command |
polign mcp -memory-only -write |
The subprocess argv, to run a polign binary other than the one pip installed |
for_subject |
limit |
20 | Beliefs loaded into the prompt; above it, per-turn search kicks in |
for_subject |
read_timeout, write_timeout |
0.5 s, 5 s | Reads fail open (last known beliefs); writes tell the model the fact was not saved |
RecallAgent |
context_template |
<recall_memory>\n{context}\n</recall_memory> |
Wrapper around the block; must contain {context} |
RecallAgent |
who |
"the caller" |
How the block refers to the person |
RecallAgent |
remember_tool, forget_tool |
on, off | Which tools the model gets |
RecallAgent |
search_when_overflowed |
on | Per-turn search when the caller has more beliefs than limit |
Custom predicates
Predicates are a JSON file. The remember tool's schema is built from it, so
the model only ever sees the names you allow.
{
"name": { "cardinality": "single", "value_type": "string", "description": "The name the caller asks to be called" },
"open_issue": { "cardinality": "multi", "value_type": "string", "description": "A problem the caller reported that is not resolved yet" }
}
single means a newer value replaces the old one; multi means each value
is an additional fact. value_type is string, number, or boolean. The
file replaces Recall's built-in registry entirely. VOICE_REGISTRY is a
starter set for callers: name, preferred language, callback number, email,
timezone, account tier, recording consent, response style, open issues,
owned products, and technologies used.
Subjects and retention
Use a stable, auth-derived identifier as the subject, such as the participant
identity your token server issued. Never the room name. Recall keeps the
record of every change while the current view updates; enable forget_tool
if callers should be able to withdraw a fact by asking, and see the Recall
docs for retention and export.
Development
cd python/recall-livekit
python -m pip install -e . pytest pytest-asyncio
pytest tests/unit_tests -q # fake Recall subprocess, scripted model
pytest tests/integration_tests -v # real polign-server and polign CLI
The integration tests locate the binaries like the SDK's tests do
(POLIGN_SERVER, POLIGN_SOURCE, POLIGN_SERVER_VERSION, or the latest
release download) and skip when none is found. To test against the binaries
pip installed, set POLIGN_SERVER="$(python -c 'import polign_db; print(polign_db.find_bin("polign-server"))')".
Metadata
Release files for recall-livekit 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| recall_livekit-0.2.0.tar.gz | 23.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| recall_livekit-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 43.0 kB
Release files / recall_livekit-0.2.0.tar.gz
| Download URL | recall_livekit-0.2.0.tar.gz |
|---|---|
| Size | 23.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6a86204e079d17c4bbf710b95f7b56d5a73f92133b7a28ca1a92137ae7a32ffd
|
|
BLAKE2b-256 checksum How to use checksums |
65da3a2e1598f839a09cf109b219c2d41a153969ccd3a77618c3d18ed1af76c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.
Transparency logRelease files / recall_livekit-0.2.0-py3-none-any.whl
| Download URL | recall_livekit-0.2.0-py3-none-any.whl |
|---|---|
| Size | 19.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3f92d29b5bcf0729c1c01073f7946122d84b0ab3a3870dfd24239085f2213130
|
|
BLAKE2b-256 checksum How to use checksums |
795bcac71788fb52de3c4b9357255df09f2b4426d57abc5a894317c5cbe84846
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.
Transparency log