OpenRTC: track every agent in one worker
OpenRTC runs N LiveKit voice agents in one worker. VoiceGateway plugs into itsSessionObserver seam, so a
single line gives every session per-call cost tracking, attributed per agent
and per tenant.
Install
One line: hand the pool an observer
Agent subclasses, tools, or session wiring. The
observer attaches VoiceGateway to each live session automatically.
What gets recorded
Per call, rows are tagged:project: the value you passed to the observer.agent_id: which registered agent handled the call (info.agent_name).tenant_id:info.metadata["tenant"]if present in the room or job metadata, elseNone.
Where the numbers go
- Fleet mode (shown above,
collector_urlset): one sharedRemoteCollectorSinkbatches rows and POSTs them to<collector_url>/v1/ingestwithAuthorization: Bearer <api_key>. Every worker pushes to the same collector, so you slice cost byagent_id,project, andtenantacross the whole fleet. - Single node (omit
collector_url): rows write to a local SQLite database (db_path, elseVOICEGW_DB_PATH, else the default). Runvoicegw dashboardto read it.
Multi-tenant attribution
Dispatch jobs with room or job metadata like{"tenant": "acme-corp"}. OpenRTC
parses and merges it, and the observer reads tenant per call, so one agent
serving many tenants produces cleanly separated cost streams with no branching
in your code.
How it works
The observer builds one sink lazily on the first session and shares it for the worker’s life. It holds only configuration, so it is safe to use with OpenRTCprocess isolation (it pickles cleanly and rebuilds its sink in the worker).
attach() flushes the shared sink when each session closes but never closes it,
so one session ending never disrupts the others.