Skip to main content

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:

  1. on_enter loads the caller's current beliefs and appends them to the instructions inside a <recall_memory> block, before the greeting.
  2. The caller says "actually call me Sam, and I moved to Denver". The model calls remember twice. Recall supersedes the old name and timezone, and the agent rewrites its instructions so the next sentence already uses Sam.
  3. 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)

Source distribution for recall-livekit 0.2.0
File Size Uploaded
recall_livekit-0.2.0.tar.gz 23.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for recall-livekit 0.2.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

0.3.1

2 release files

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.0

2 release 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