Skip to content

Releases

OpenRing 0.1.6: call limits, voicemail detection, recordings, squads, knowledge bases, SIP, Plivo and Vonage

Choose a tag to compare

@elifalanrocha elifalanrocha released this 09 Nov 03:49

Added

  • The phone line in a call's cost (costBreakdown.line, included in total): Twilio's list prices for US and Canadian
    numbers, rounded up to the minute. Other carriers and countries are named in unpriced until 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
    transferCall on 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) and openring --host, which wins over
    HOST and warns in its help that anything but localhost exposes the dashboard (thanks to Arin Aeruva, arin30).

  • Vapi's createdAtGt, createdAtLt, createdAtGe and createdAtLe on GET /call, /assistant, /tool and
    /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.json now 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, the handoff tool and assistantDestinations, squadId on numbers, calls and assistant-request,
    contextEngineeringPlan, firstMessageMode and tools:append; the call's handoffs lists each change. The import
    brings squads.

  • Knowledge bases (beta), in Vapi's format: POST /file, the query tool, /knowledge-base and
    model.knowledgeBaseId. The search runs on your server with SQLite's full-text index, matching words, or asks your
    own with custom-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-trunk credentials in /credential and byo-phone-number numbers, in and
    out, with login, registration and transfers, over UDP with G.711. Only your trunks' gateways get an answer.
    customer.sipUri works, and Twilio and Telnyx SIP calls find their number.

  • Words the transcriber should get right, in Vapi's transcriber.keyterm, keytermsPrompt and keywords, 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, with artifact.recordingUrl on the call and in the end-of-call-report.
    GET /call/{id}/recording needs the API key or a dashboard session, and DELETE removes 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 with PATCH /settings/recordings (0 keeps them for good).

  • Call limits, in Vapi's fields: a call ends by itself after maxDurationSeconds or after silenceTimeoutSeconds
    without activity (the clock waits while someone talks, the model thinks or a tool runs), with Vapi's endedReason
    (exceeded-max-duration, silence-timed-out),
    saying endCallMessage first. When the caller goes quiet after the assistant spoke,
    messagePlan.idleMessages are said ("Are you still there?"), after idleTimeoutSeconds, up to
    idleMessageMaxSpokenCount times. The assistant editor has the length, the silence and the idle message.
    These limits apply to assistants you already have: give maxDurationSeconds a higher value if their calls can run
    past 10 minutes. endCallMessage is also said when an endCall tool has no message of its own, as on Vapi.

  • Voicemail detection on outgoing calls (beta), in Vapi's fields: with voicemailDetection or a voicemailMessage,
    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 with endedReason: "voicemail", which campaigns count in callsCounterEndedVoicemail; without a message it just hangs up. It stays
    off unless asked for. The assistant editor has the switch and the message.

  • The apiRequest tool, in Vapi's format: the model fills in the body and OpenRing sends it to your URL, such as
    an n8n, Make or Zapier webhook, with no server of your own. The URL, headers and parameters stay yours and
    can use {{variables}}; the model can only send the fields body declares. 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's credentialId isn't available.

  • Tools: request-response-delayed messages are said when a tool runs late, and a request-failed message 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 developer message 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's request-failed message 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 as customer-ended-call,
    a success. The call now ends right away with pipeline-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/event or /vonage/voice for five minutes.
    An outgoing Vonage call that was answered but never connected its websocket now ends with
    vonage-failed-to-connect-call instead of staying queued.

  • OAuth's redirect_uri has to be on the same origin as PUBLIC_URL (or on localhost). It was a prefix match, so
    https://your-host.evil.example passed.

OpenRing 0.1.5: no requests to cloud metadata, no leaked URLs, campaign fixes

Choose a tag to compare

@elifalanrocha elifalanrocha released this 01 Nov 23:54

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 pip

Security

  • No requests to cloud metadata addresses. Tool servers, server.url, custom-llm base URLs and the import source come from assistants, numbers and API calls. On a cloud server, a URL such as http://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 openring right 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), openring printed 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

Choose a tag to compare

@elifalanrocha elifalanrocha released this 01 Nov 17:56

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 pip

Security

  • Example API keys are refused. .env.example shipped OPENRING_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. openring replaces 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

Choose a tag to compare

@elifalanrocha elifalanrocha released this 01 Nov 13:22

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 pip

Highlights

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.
  • assistantOverrides and {{customer.name}}-style variables on POST /call and campaigns.
  • Fixed: after a model switch, the caller hears one answer, not two.

Good to know

  • Known issue: on Apple Silicon Macs, the local whisper transcriber 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.unpriced instead of being guessed.
  • Campaigns place real calls. Call only people who agreed to be called.
  • npx openring now also installs Whisper, so the first install downloads more than before.

Full list of changes: CHANGELOG.md