Skip to main content

LiveKit Agents Plugin for SpatialReal Avatar

This plugin provides integration with SpatialReal's avatar service for lip-synced avatar rendering in LiveKit voice agents.

Installation

pip install livekit-plugins-spatialreal

Versioning

Starting with 1.7.1, the plugin's major and minor version track the livekit-agents release it was validated against (e.g. plugin 1.8.x targets livekit-agents 1.8.x). The patch number is the plugin's own and may advance independently.

The current release, 1.8.11, is validated against livekit-agents 1.8.11.

Or install from source:

pip install -e .

Configuration

Set the following environment variables:

# Required
SPATIALREAL_API_KEY=your-api-key
SPATIALREAL_APP_ID=your-app-id
SPATIALREAL_AVATAR_ID=your-avatar-id

# Optional
# Named SpatialReal deployment; the SDK resolves its endpoints. Defaults to the public one.
SPATIALREAL_ENVIRONMENT=
# Explicit endpoints, for a deployment SpatialReal gives you addresses for. They win over
# SPATIALREAL_ENVIRONMENT.
SPATIALREAL_CONSOLE_ENDPOINT=
SPATIALREAL_INGRESS_ENDPOINT=
# Max seconds of per-response audio retained for false-interruption resume (default 180, min 10)
SPATIALREAL_RESUME_BUFFER_MAX_SECONDS=
# TTL (seconds) of the LiveKit room-join token the egress worker uses; must outlive
# the whole session so mid-session reconnects don't hit an expired token (default 86400)
SPATIALREAL_LIVEKIT_TOKEN_TTL_SECONDS=

# LiveKit credentials
LIVEKIT_URL=
LIVEKIT_API_KEY=
LIVEKIT_API_SECRET=

Usage

from livekit.agents import Agent, AgentSession, JobContext, cli, WorkerOptions
from livekit.plugins import spatialreal


class VoiceAssistant(Agent):
    def __init__(self):
        super().__init__(instructions="You are a helpful voice assistant.")


async def entrypoint(ctx: JobContext):
    await ctx.connect()

    # Configure your pipeline components (VAD, STT, LLM, TTS)
    session = AgentSession(
        vad=vad,
        stt=stt,
        llm=llm,
        tts=tts,
    )

    # Initialize and start the avatar session
    avatar = spatialreal.AvatarSession()
    await avatar.start(session, room=ctx.room)

    # Start the agent session
    await session.start(
        agent=VoiceAssistant(),
        room=ctx.room,
    )


if __name__ == "__main__":
    cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint))

For production agents, catch SpatialRealException so you can decide whether to fail the job or continue without avatar output:

try:
    await avatar.start(session, room=ctx.room)
except spatialreal.SpatialRealException as err:
    logger.error("Avatar startup failed: %s", err)
    raise

API Reference

AvatarSession

Main class for integrating SpatialReal avatars with LiveKit agents.

Constructor Parameters

Parameter Type Description
api_key str SpatialReal API key (or set SPATIALREAL_API_KEY)
app_id str SpatialReal application ID (or set SPATIALREAL_APP_ID)
avatar_id str Avatar ID to use (or set SPATIALREAL_AVATAR_ID)
environment str Named SpatialReal deployment whose endpoints the SDK resolves (or set SPATIALREAL_ENVIRONMENT); defaults to the public deployment
console_endpoint_url str Explicit console endpoint, for a private deployment (or set SPATIALREAL_CONSOLE_ENDPOINT)
ingress_endpoint_url str Explicit ingress endpoint, for a private deployment (or set SPATIALREAL_INGRESS_ENDPOINT)
avatar_participant_identity str LiveKit identity for avatar participant
avatar_participant_name str LiveKit display name for avatar participant
idle_timeout_seconds int LiveKit egress idle timeout in seconds (0 uses server defaults)
sample_rate int | None Optional avatar audio sample rate override
livekit_token_ttl_seconds int TTL of the LiveKit room-join token used by the egress worker; must outlive the whole session (or SPATIALREAL_LIVEKIT_TOKEN_TTL_SECONDS; default 86400)

Methods

  • start(agent_session, room, *, livekit_url, livekit_api_key, livekit_api_secret): Start the avatar session and hook into the agent's audio output. Raises SpatialRealException with actionable context if startup fails.
  • aclose(): Clean up avatar session resources.

When starting, the plugin automatically sets lk.publish_on_behalf to the agent participant identity for avatar worker association in LiveKit frontends.

Events

  • playback_started — emitted with an AvatarPlaybackStartedEvent when audible avatar playback is first observed for a request.
@avatar.on("playback_started")
def _on_playback_started(ev: spatialreal.AvatarPlaybackStartedEvent):
    logger.info("avatar playing request %s (via %s)", ev.request_id, ev.source)

AvatarPlaybackStartedEvent

Field Type Description
request_id str SpatialReal request the playback belongs to
source str Signal that observed the start (e.g. livekit_avatar_audio_track)
observed_at float Unix timestamp of the observation

SpatialRealException

Exception raised for SpatialReal-related errors.

How It Works

  1. The plugin intercepts TTS audio output from the agent session
  2. Audio frames are forwarded to SpatialReal's avatar service
  3. SpatialReal generates lip-synced video and audio
  4. The avatar joins the LiveKit room and publishes the synchronized streams

Interruptions and false-interruption recovery

LiveKit Agents owns turn-taking and interruption decisions; the plugin never adds its own VAD or interruption policy. The audio output the plugin installs advertises pause support, so the framework's resume_false_interruption behaviour (on by default) works with the avatar:

  • When the framework detects a possible interruption it calls pause(). The plugin stops the current SpatialReal request and retains the unplayed PCM tail locally.
  • If the framework later rejects the interruption (a laugh, a backchannel, a cough), it calls resume(). The plugin re-sends only the estimated unplayed remainder as a new request.
  • If the interruption is confirmed, clear_buffer() discards the retained audio.

The retained tail is bounded by SPATIALREAL_RESUME_BUFFER_MAX_SECONDS.

License

Apache-2.0

Metadata

Release files for livekit-plugins-spatialreal 1.8.11

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for livekit-plugins-spatialreal 1.8.11
File Size Uploaded Provenance Actions
livekit_plugins_spatialreal-1.8.11.tar.gz 28.8 kB With provenance Details for livekit_plugins_spatialreal-1.8.11.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for livekit-plugins-spatialreal 1.8.11
File Interpreter ABI Platform Actions
livekit_plugins_spatialreal-1.8.11-py3-none-any.whl Python 3 none any Details for livekit_plugins_spatialreal-1.8.11-py3-none-any.whl

Total release size: 58.3 kB

Release files / livekit_plugins_spatialreal-1.8.11.tar.gz

Download URL livekit_plugins_spatialreal-1.8.11.tar.gz
Size 28.8 kB
Tags Source
SHA-256 checksum
How to use checksums
85764e9595e281d0b6c7973da950deeae691239f2e53c380b6948220a251f4c7
BLAKE2b-256 checksum
How to use checksums
8a767243b4cd2006211d478414e966940678de419313dc29c54eefda51dd4525
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 5, 2026.

Transparency log

Release files / livekit_plugins_spatialreal-1.8.11-py3-none-any.whl

Download URL livekit_plugins_spatialreal-1.8.11-py3-none-any.whl
Size 29.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1c1f04f2291d0ea0d4d2b08f87a1d221bf94e43f637b0ca84f9d60f97fc61fe6
BLAKE2b-256 checksum
How to use checksums
c319344b6203463c9f79807637173dc8f02f75b768c34ba02ee6d4b9190d842c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 5, 2026.

Transparency log

Security for livekit-plugins-spatialreal 1.8.11

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.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for livekit_plugins_spatialreal-1.8.11.tar.gz

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 Nov 5, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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