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.20.1

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.20.1
File Size Uploaded
openrtc-0.20.1.tar.gz 1.8 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for openrtc 0.20.1
File Interpreter ABI Platform
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

Release history Release notifications | RSS feed

This release

0.20.1 This release

2 release files

0.20.0

2 release files

0.19.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.1.0

2 release files

0.0.16

2 release files

0.0.15

2 release files

0.0.14

2 release files

0.0.13

2 release files

0.0.12

2 release files

0.0.11

2 release files

0.0.10

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.1

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