Skip to main content
from openrtc import AgentPool
from my_agents import BookingAgent, SupportAgent, SalesAgent

pool = AgentPool()                 # one livekit-agents worker
pool.add("booking", BookingAgent)  # plain livekit.agents.Agent subclasses
pool.add("support", SupportAgent)
pool.add("sales", SalesAgent)
pool.run()                         # each call is routed to one of them

OpenRTC is the ops layer for self-hosted LiveKit Agents: routing, hot reload, a live openrtc top, tenant caps and drain deploys, around the livekit-agents worker you already run.

Why

  • The problem. A livekit-agents worker has one entrypoint. With more than one agent you either write the dispatch yourself or run a worker per agent, and the tooling to operate it (which call is slow, which client is using the box, how to ship without cutting calls) is yours to build too.
  • What you get. One pool that routes each call to the right agent, swaps live calls to your edited code, shows every call in openrtc top, caps each tenant, and drains on deploy.
  • What doesn't change. Your agents stay standard Agent subclasses. No base class, and @function_tool, RunContext, on_enter and the *_node hooks are untouched. You delete the per-worker entrypoint and AgentSession wiring.

Quick start

pip install "openrtc[livekit,cli]"

Python 3.11 to 3.13, livekit-agents >=1.5,<1.9. Set LIVEKIT_URL, LIVEKIT_API_KEY and LIVEKIT_API_SECRET as for any LiveKit worker. Put one agent per file in a directory:

# agents/booking.py
from livekit.agents import Agent
from openrtc import agent_config


@agent_config(name="booking", greeting="Welcome to reservations.")
class BookingAgent(Agent):
    def __init__(self) -> None:
        super().__init__(instructions="You help callers book a table.")
openrtc dev ./agents \
  --default-stt openai/gpt-4o-mini-transcribe \
  --default-llm openai/gpt-4.1-mini \
  --default-tts openai/gpt-4o-mini-tts

openrtc top          # in a second terminal: every live call

A room named booking-call-1 now reaches BookingAgent. Edit the file during a call and the next turn runs your change. Prefer Python to a directory? pool.add(...) as above, then python main.py dev. Full quick start.

Using a coding agent (Claude Code, Cursor, Codex)? npx skills add mahimailabs/openrtc-runtime gives it two skills: moving a livekit-agents project onto OpenRTC, and running it in production.

What you get, and where it stops

What it does Limits
Routing Each call goes to one agent by job metadata, room metadata, or room-name prefix. An unknown agent name raises; routing never falls back silently.
Hot reload openrtc dev moves live calls to your edited agent on their next turn. A bad save keeps the old code. Coroutine mode only.
openrtc top A live table of every call: agent, tenant, duration, CPU and memory; slow when a call blocks the others. Same host. slow needs coroutine mode.
Tenants Per-tenant providers and keys, per-tenant and per-agent caps, a circuit breaker for a failing tenant. Not a sandbox. The breaker needs coroutine mode.
Deploys deployment_version, pool.begin_drain() and audit events around livekit's drain. Calls finish on the old version; none is moved.
Two isolation modes coroutine (default): every call in one process. process: livekit's process per call. Coroutine mode leans on livekit internals, hence the tight version pin.

Measured, not claimed

Against livekit-agents 1.8.3 on the same two cores, 8 calls: OpenRTC's default mode used about 22 MB per call against about 65 MB, at about the same CPU (uvloop). CPU, not memory, is what limits calls per machine, so OpenRTC does not make one box serve more calls. Benchmark, with the harness to rerun it in benchmarks/headtohead.

When not to use it: you have one agent and don't need the ops tooling (plain livekit-agents is simpler), or you need hard per-call isolation and hot reload together (isolation="process" isolates each call but cannot hot reload).

Docs

Why OpenRTC · How it works · CLI · Benchmark · Changelog · for AI coding tools: llms.txt

Contributing

OpenRTC is early, and a small change moves it. Three commands to a green run (make ci itself takes about a minute):

git clone https://github.com/mahimailabs/openrtc-runtime && cd openrtc-runtime
uv sync --group dev
make ci          # ruff, format, mypy --strict, pytest with the 99% coverage gate

Where to start: issues labelled good first issue are scoped, with the files to read and what done looks like. help wanted are bigger. Found a bug or have an idea? Open an issue.

How we work: read CONTRIBUTING.md. Performance claims need a measurement. AI-assisted PRs are welcome: the repo ships a CLAUDE.md and agent skills (skills/ for adopters), and a PR is judged on the same make ci and review either way.

Contributors

License

MIT. Built by Mahimai Raja at Mahimai AI, in public, on LiveKit Agents.

Metadata

Release files for openrtc 0.21.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 openrtc 0.21.0
File Size Uploaded Provenance Actions
openrtc-0.21.0.tar.gz 2.0 MB Without provenance Details for openrtc-0.21.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for openrtc 0.21.0
File Interpreter ABI Platform Actions
openrtc-0.21.0-py3-none-any.whl Python 3 none any Details for openrtc-0.21.0-py3-none-any.whl

Total release size: 2.1 MB

Release files / openrtc-0.21.0.tar.gz

Download URL openrtc-0.21.0.tar.gz
Size 2.0 MB
Tags Source
SHA-256 checksum
How to use checksums
8168a85e50c590b1a9b75f641eb4e2abedc18239c0ef5f8ff39c77ab7215dff7
BLAKE2b-256 checksum
How to use checksums
bf3325a0a4a3b3c4350030e8e23dffcfbeb331ef62fdc565b22720c105b7593f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / openrtc-0.21.0-py3-none-any.whl

Download URL openrtc-0.21.0-py3-none-any.whl
Size 141.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2e0f201c4c538969e923d0f6683c12adbcb4f2134af3d4dd05f9445bc9ac8398
BLAKE2b-256 checksum
How to use checksums
ad4b205ed5e94827e2953817d31d6eab6c3a8d0c7d398818c1ec0eedf397b2ea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Security for openrtc 0.21.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

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.

Release history Release notifications | RSS feed

This release

0.21.0 This release

2 release files No provenance

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