Repository navigation
Releases
OpenRing 0.1.6: call limits, voicemail detection, recordings, squads, knowledge bases, SIP, Plivo and Vonage
Added
-
The phone line in a call's cost (
costBreakdown.line, included intotal): Twilio's list prices for US and Canadian
numbers, rounded up to the minute. Other carriers and countries are named inunpriceduntil you add a rate in
~/.openring/prices.json("line"). -
The Calls page exports to CSV, with formula cells made safe for spreadsheets, and a call's page copies its transcript
(thanks to Vaibhav R Valakunde, vaibhavrvalakunde2006-gif). -
Provider logos on the Providers page.
-
OmniRoute takes an API key on the Providers page (
OMNIROUTE_API_KEY), for when its API key protection is on;
it is checked against OmniRoute's model list before it's saved. -
OAuth sign-in (
/oauth/*) for xAI, Anthropic and OpenAI with the server owner's own OAuth client
(<PROVIDER>_CLIENT_ID). OpenRing never signs in as another vendor's app. OpenRouter keeps its own sign-in. -
Calls in and out through Plivo and Vonage, and out through Telnyx (beta): signed webhooks, campaigns, and
transferCallon Plivo and Vonage. Connect them on the Providers page. The import brings Telnyx and Vonage numbers. -
openring --version(thanks to Vaibhav R Valakunde, vaibhavrvalakunde2006-gif) andopenring --host, which wins over
HOSTand warns in its help that anything but localhost exposes the dashboard (thanks to Arin Aeruva, arin30). -
Vapi's
createdAtGt,createdAtLt,createdAtGeandcreatedAtLeonGET /call,/assistant,/tooland
/phone-number, filtered in SQL, in any ISO 8601 offset, with a 400 for a date that isn't one (thanks to
k_s_neeraj, Neeraj111010). Importing from another OpenRing with more than 100 items now gets every page. -
Disconnect on the Providers page asks for a second click, labeled Confirm disconnect, before it removes a key
(thanks to Arin Aeruva, arin30). -
Prices for Rime's Coda and Smallest.ai's Lightning voices, and
"*"in~/.openring/prices.jsonnow covers every
model of a provider, including the ones with a price of their own (thanks to Mohit Anand, coughlmao). -
Squads (beta), in Vapi's format: several assistants on one call, each with its own prompt, tools, model and voice.
/squad, thehandofftool andassistantDestinations,squadIdon numbers, calls andassistant-request,
contextEngineeringPlan,firstMessageModeandtools:append; the call'shandoffslists each change. The import
brings squads. -
Knowledge bases (beta), in Vapi's format:
POST /file, thequerytool,/knowledge-baseand
model.knowledgeBaseId. The search runs on your server with SQLite's full-text index, matching words, or asks your
own withcustom-knowledge-base. PDFs are read with pypdf, a new dependency, in a process of their own with a time
limit. -
SIP trunks (beta), in Vapi's format:
byo-sip-trunkcredentials in/credentialandbyo-phone-numbernumbers, in and
out, with login, registration and transfers, over UDP with G.711. Only your trunks' gateways get an answer.
customer.sipUriworks, and Twilio and Telnyx SIP calls find their number. -
Words the transcriber should get right, in Vapi's
transcriber.keyterm,keytermsPromptandkeywords, or
Words to recognize in the assistant editor. Each goes to the field its transcriber and model take, since Deepgram
refuses a connection given the wrong one. -
Call recording, in Vapi's
artifactPlan.recordingEnabled: a stereo WAV per call on your server, played on the
call's page, withartifact.recordingUrlon the call and in theend-of-call-report.
GET /call/{id}/recordingneeds the API key or a dashboard session, andDELETEremoves the file. It's off by
default, unlike on Vapi: many places require telling people they are being recorded. Recordings are deleted after
365 days; change it under Settings > Recordings or withPATCH /settings/recordings(0 keeps them for good). -
Call limits, in Vapi's fields: a call ends by itself after
maxDurationSecondsor aftersilenceTimeoutSeconds
without activity (the clock waits while someone talks, the model thinks or a tool runs), with Vapi'sendedReason
(exceeded-max-duration,silence-timed-out),
sayingendCallMessagefirst. When the caller goes quiet after the assistant spoke,
messagePlan.idleMessagesare said ("Are you still there?"), afteridleTimeoutSeconds, up to
idleMessageMaxSpokenCounttimes. The assistant editor has the length, the silence and the idle message.
These limits apply to assistants you already have: givemaxDurationSecondsa higher value if their calls can run
past 10 minutes.endCallMessageis also said when anendCalltool has no message of its own, as on Vapi. -
Voicemail detection on outgoing calls (beta), in Vapi's fields: with
voicemailDetectionor avoicemailMessage,
Twilio's answering machine detection checks who picked up and waits for the beep. A voicemail gets the message, in
the assistant's voice (or a recording, from the URL of a .wav or .mp3), and the call ends withendedReason: "voicemail", which campaigns count incallsCounterEndedVoicemail; without a message it just hangs up. It stays
off unless asked for. The assistant editor has the switch and the message. -
The
apiRequesttool, in Vapi's format: the model fills in thebodyand OpenRing sends it to your URL, such as
an n8n, Make or Zapier webhook, with no server of your own. The URL,headersandparametersstay yours and
can use{{variables}}; the model can only send the fieldsbodydeclares. Only a 2xx answer counts; nothing is
retried or redirected, a caller's interruption doesn't
cancel a request already sent, and cloud metadata addresses are refused. Vapi'scredentialIdisn't available. -
Tools:
request-response-delayedmessages are said when a tool runs late, and arequest-failedmessage with
"role": "system"now goes to the model instead of being read out to the caller.
Changed
- Calls now have Vapi's default limits: 10 minutes at most, and 30 seconds of silence from the caller. Before,
a call with nobody on the line kept running (and billing the providers) until the phone company dropped it.
Fixed
-
Only OpenAI is sent the
developermessage role now. Pipecat adds such messages during a call (a tool's late answer, a
caller's empty turn), and a provider that refuses the role ended the call. Mistral, DeepSeek and Perplexity go through
Pipecat's own services for them, which follow their rules for messages. -
A caller speaking during a transfer no longer cancels it, and a transfer that fails now gets an answer: the model tells
the caller, or the tool'srequest-failedmessage does, instead of leaving them in silence. -
When a provider stopped working during a call (a rejected key, no credit left, an outage) and no fallback could
take over, the caller heard silence until they hung up, and the call was recorded ascustomer-ended-call,
a success. The call now ends right away withpipeline-error: the voice (11labs ...) stopped working: ...,
naming the layer, the provider and its error. -
A Vonage webhook token that carries a payload hash now vouches for that body only. Before, a captured token also
passed with no body at all, so it could stand in for any GET to/vonage/eventor/vonage/voicefor five minutes.
An outgoing Vonage call that was answered but never connected its websocket now ends with
vonage-failed-to-connect-callinstead of stayingqueued. -
OAuth's
redirect_urihas to be on the same origin asPUBLIC_URL(or on localhost). It was a prefix match, so
https://your-host.evil.examplepassed.
OpenRing 0.1.5: no requests to cloud metadata, no leaked URLs, campaign fixes
A security and fixes release. Update if your server takes assistants, tools or imports from anyone else.
npx openring # installs 0.1.5
pip install -U "openring[kokoro,whisper]" # or with pipSecurity
- No requests to cloud metadata addresses. Tool servers,
server.url,custom-llmbase URLs and the import source come from assistants, numbers and API calls. On a cloud server, a URL such ashttp://169.254.169.254/could have read the machine's cloud credentials through OpenRing. Link-local and cloud metadata addresses are now refused, on every request and redirect. Private networks stay allowed, so a tool server on your office network still works. - URLs no longer leak. When a tool failed, the error the model read, and could say to the caller, included the tool's full URL. Webhook URLs, which often carry a secret, are now logged as scheme and host only.
- New guidance in the README and SECURITY.md: tools should treat the model's arguments as untrusted input (prompt injection).
Fixed
- The owner can't lock themselves out anymore: wrong passwords typed on the server's own computer don't count toward the sign-in limit.
- A campaign never calls the same person twice, even when a number is written two ways or appears in two lists. Customer numbers need 7 to 15 digits, with the country code.
npx openringright after a release no longer says the new version doesn't exist: it asks PyPI again, once.- With its output going to a pipe (Docker logs, systemd),
openringprinted nothing at startup; it does now, and says when an example API key was ignored and where the new one is. - Deleting a model route updates the assistants that used it. Measure speed reports a model that no longer resolves instead of failing.
- A Genesys connection with a malformed signature time is refused cleanly.
- Dashboard: dates in English, like the rest of the page; a call's cards in even rows; the overview's bars lined up.
Added
- The new-campaign form warns when calls could reach people before 8 AM or after 9 PM their time.
Full list of changes: CHANGELOG.md
OpenRing 0.1.4: security fixes, Whisper on Apple Silicon, Twilio calls out of beta
A security and fixes release. If you deployed with Docker or copied .env.example, update now.
npx openring # installs 0.1.4
pip install -U "openring[kokoro,whisper]" # or with pipSecurity
- Example API keys are refused.
.env.exampleshippedOPENRING_API_KEY=change-me, and the Docker setup copied it, so a server deployed that way accepted a key anyone could guess. That key could read transcripts, change assistants and place calls on your Twilio account. Example keys now count as no key.openringreplaces one with a generated key, saves it so it stays the same across restarts, and shows it under Settings in the dashboard. - A server without an API key only answers its own computer. Before, its API answered anyone who could reach it. Requests through tunnels or the network are now refused, and the dashboard keeps working through its sign-in.
- Every API route is now checked in CI: a new route without a key or session check fails the build.
Fixed
- The local Whisper transcriber starts on Apple Silicon Macs. On M1 and later Macs it failed unless MLX Whisper was installed: Pipecat requires it just to load its Whisper module there, though OpenRing uses faster-whisper.
- Phone numbers are checked when saved: 7 to 15 digits, with the country code. Before, a text with no digits could match an anonymous caller, and an import could skip a real number.
- Lists created in the same instant now always come back newest first.
- The Providers page no longer scrolls sideways on a phone.
Changed
- Incoming calls through Twilio are no longer beta. A real phone call went through end to end: a caller in Brazil to a US number, with Deepgram, Groq and the Kokoro voice. Greeting, conversation, interruptions, hang-up and the cost record all worked. Outgoing Twilio calls, and so campaigns, stay beta until one is confirmed on a real call.
Full list of changes: CHANGELOG.md
OpenRing 0.1.3: campaigns, a free local stack, model routes and cost per call
Self-hosted voice AI agents with a Vapi-compatible API, and still no platform fee. This release adds outbound campaigns, a stack that runs entirely on your computer for free, model routes that switch when a model fails or gets slow, and the dollar cost of every call.
npx openring # installs 0.1.3
pip install -U "openring[kokoro,whisper]" # or with pipHighlights
Campaigns (beta). One assistant calls a list of people from a Twilio number, a few at a time, inside a time window, using Vapi's /campaign API. Paste a list or upload a CSV on the new Campaigns page; extra columns become {{variables}}, so the assistant can greet each person by name. A restarted server resumes its campaigns without calling anyone twice.
A 100% local, free stack. The new whisper transcriber (faster-whisper) runs on your machine. With Ollama for the model and Kokoro for the voice, nothing is billed per minute and the audio never leaves the computer. Use the free local stack in the assistant editor sets up all three.
Model routes (beta). A route is a saved list of models that several assistants share, like OmniRoute's combos. When a model fails (a rejected key, no credit, a rate limit, an outage) or is slow to start answering, the next one takes over and answers the same turn. Pick a preset:
| Preset | Puts first | Switches after |
|---|---|---|
| Fastest | The model with the quickest measured answers | 1.5 s |
| Cheapest | The lowest price, with local models before paid ones | 3 s |
| Reliable | Your own order, and a failing model rests 15 min | 2 s |
| Custom | You set the order, the wait and the rest | You choose |
Cost per call, in dollars. Every call records what its model, transcriber and voice cost at list prices, in Vapi's cost and costBreakdown fields. The dashboard shows the cost per call, per minute and in total. Prices for 1,281 models ship with OpenRing, and ~/.openring/prices.json takes your own rates.
Genesys Cloud (beta). Assistants can take calls inside Architect flows through the Audio Connector. Connections are signed and verified.
Also new
- Provider fallback in Vapi's format (
fallbackPlan,fallbackModels), including a fallback on another provider (beta). "language": "multi": the assistant answers in the caller's language and switches when they do.assistantOverridesand{{customer.name}}-style variables onPOST /calland campaigns.- Fixed: after a model switch, the caller hears one answer, not two.
Good to know
- Known issue: on Apple Silicon Macs, the local
whispertranscriber doesn't start. Pipecat looks for MLX Whisper there. A fix is on the way; until then, use another transcriber on those Macs, such as Deepgram. Kokoro and Ollama work. - Features marked beta work in our tests but haven't been confirmed on enough real calls yet. If you try them, please tell us how it goes.
- The cost per call leaves out the phone line (Twilio, Telnyx). A provider without a known price is listed in
costBreakdown.unpricedinstead of being guessed. - Campaigns place real calls. Call only people who agreed to be called.
npx openringnow also installs Whisper, so the first install downloads more than before.
Full list of changes: CHANGELOG.md