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
Agentsubclasses. No base class, and@function_tool,RunContext,on_enterand the*_nodehooks are untouched. You delete the per-workerentrypointandAgentSessionwiring.
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.
License
MIT. Built by Mahimai Raja at Mahimai AI, in public, on LiveKit Agents.
Metadata
Release files for openrtc 0.20.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| openrtc-0.20.1.tar.gz | 1.8 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| openrtc-0.20.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.9 MB
Release files / openrtc-0.20.1.tar.gz
| Download URL | openrtc-0.20.1.tar.gz |
|---|---|
| Size | 1.8 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d1fabdb0fd7e3d692ff26d742d7a430bc740745852a12e98d157db58f7739db1
|
|
BLAKE2b-256 checksum How to use checksums |
52d65c473a97d1091c62fe1d213c5fe31235ad69f3c77829f7e446eb12fd5266
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / openrtc-0.20.1-py3-none-any.whl
| Download URL | openrtc-0.20.1-py3-none-any.whl |
|---|---|
| Size | 139.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a5559999238fad58eb04c7fabb61283a82a4af1ef1c6d6f455a5634c745b5039
|
|
BLAKE2b-256 checksum How to use checksums |
d2bb44b6da08e9210544136f5ff5740df716481f43c5be0e6d7095916fb73fdf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|