Model or dataset
bolna-ai/bolna avatar
bolna-ai/bolna

Bolna: A JSON-Configured Orchestration Layer for Voice Agents Over Twilio and Plivo

Conversational voice AI agents

762 stars359 forksPythonMIT

At a glance

What is it?
Bolna wires ASR, an LLM, and TTS into one streaming pipeline that can be driven from a Python object graph or a JSON agent definition. The open repository is the orchestration core; the hosted APIs and the no-code dashboard that sit on top of it are closed source.
Who is it for?
Adopt Bolna if you already run Twilio or Plivo numbers and want the ASR, LLM, and TTS hops in one Python process you can read and modify, and if you are comfortable that telephony, Redis, and ngrok are things you operate yourself. Do not adopt it if you need a managed dashboard or a vendor SLA, because those live in the closed hosted layer, and do not adopt it if you need Exotel or Vonage today, since the README lists both as coming soon.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap Bolna fills between a telephony account and a working voice loop

Bolna targets the person who has a phone number and a set of provider API keys but no glue between them. A voice agent needs four things to happen in order and without dead air: audio arrives from the carrier, a transcriber turns it into text, an LLM decides what to say, and a synthesizer turns that text back into audio that returns over the same call leg. Bolna's README describes the repository as the orchestration platform that does exactly this, combining ASR, LLM, and TTS providers over websockets. The intended user is a developer who wants that loop as code rather than as a hosted product. The README is explicit that the repository is one of three components: the open orchestration platform, hosted APIs built on top of it, and a no-code playground built on those APIs. Only the first is in this repository. The development philosophy section states the order plainly: features land in the open package first, then surface in the hosted APIs, then in the dashboard. That ordering is the strongest argument for reading the source, because the open package is where a change exists before anywhere else.

How the pipeline is assembled: tasks, transcriber, synthesizer, llm_agent

The Python example in the README is the clearest statement of the architecture. You construct an Assistant with a name, then build three independent objects: a Transcriber configured with a provider and model, an LlmAgent wrapping a provider config, and a Synthesizer carrying a provider config and an audio format. Those three are handed to assistant.add_task with task_type set to conversation, which the comment in the example describes as building a single coherent pipeline from transcriber to llm to synthesizer. Output comes from assistant.execute(), which the README says is an async generator yielding per-task result dicts described as event-like chunks, with keys that depend on the configured tools and providers. That last detail matters more than it looks. Because the chunk shape varies with configuration, code that consumes the stream has to be written defensively rather than against a fixed schema. The README does not publish a stable event contract, and it says so. The provider list is broad on paper. Telephony covers Twilio and Plivo, with Exotel and Vonage marked coming soon. Transcription names Deepgram and Azure. LLMs include OpenAI, DeepSeek, Llama, Cohere, and Mistral. Synthesis names AWS Polly, ElevenLabs, Deepgram, OpenAI, Azure, Cartesia, Smallest, Maya, and Kalpa. The repository topics mention Cartesia, Deepgram, ElevenLabs, Plivo, Twilio, Whisper, and several model names, which is consistent with that provider list but is not independent confirmation that every integration is complete.

Running the local stack: four containers, a .env file, and ngrok

The README directs you to local_setup/ and describes four containers. A telephony web server handles either Twilio or Plivo, with separate entry files named in the README as twilio_api_server.py and plivo_api_server.py. The Bolna server creates and handles agents. An ngrok container tunnels traffic, and you are told to add an authtoken to ngrok-config.yml. Redis persists agents and prompt data. You populate a .env from .env.sample before any of this works. The quick path is a script: cd local_setup, chmod +x start.sh, then ./start.sh, which the README says checks Docker dependencies, builds with BuildKit enabled, and starts detached. The manual path sets DOCKER_BUILDKIT=1 and COMPOSE_DOCKER_CLI_BUILD=1, runs docker compose build, then docker compose up -d. You can narrow the set with docker compose up -d bolna-app twilio-app or the plivo-app equivalent. If you skip telephony entirely, the programmatic path needs only three environment variables: OPENAI_API_KEY, DEEPGRAM_AUTH_TOKEN, and ELEVENLABS_API_KEY, followed by python examples/simple_assistant.py. Note that the README itself flags the local setup as something that will be moved to a different repository, so treat those paths as provisional. For HTTP rather than Python, the README points at API.md in the repository root for agent CRUD.

Where the open repository stops and the closed product begins

This is the constraint that should drive an adoption decision, and it is stated in the README rather than buried. The hosted APIs and the no-code playground are both marked currently closed source. If you want a dashboard where a non-engineer edits prompts and voices, or a REST service someone else operates, you are not getting it from this repository. You are getting the orchestration core and the expectation that you run it. That has concrete consequences. Redis is part of the local setup because agents and prompt data are persisted there, so Redis becomes a piece of your production topology, not an implementation detail you can ignore. ngrok appears in the same setup, which is fine for a laptop and a phone call to yourself, but a tunnel is not a deployment story. The README gives no production deployment guidance beyond the local containers. It also carries a note that the project is actively looking for maintainers, which is worth weighing against the release cadence described below. None of this makes the open package unusable. It means the boundary is sharp: the orchestration is yours to run, and the convenience layer is the vendor's.

Release cadence and what upgrading actually costs you

The three most recent releases listed are 0.10.233, 0.10.232, and 0.10.231, dated within a day or two of each other in early September 2026, with the latest push a couple of days after that. Patch-level version numbers moving that fast suggest frequent small releases rather than occasional large ones. For a pinned dependency that is manageable; for a service you deploy from master it means you are tracking a moving target. The practical upgrade question is whether the interfaces you touch are stable. The README's own description of execute() output, that the exact keys depend on configured tools and providers, suggests the streaming surface is not a frozen contract. The provider configuration objects shown in the example, Transcriber, Synthesizer, ElevenLabsConfig, LlmAgent, and SimpleLlmAgent, are the things your code imports, so a rename or a field change there reaches you directly. The README does not include a changelog or a compatibility policy, so the only way to judge the risk of a given bump is to read the diff between two version tags. Licence-wise, the repository is MIT, which the README's badge restates. MIT is permissive and places few conditions on redistribution, but it also means no warranty and no support obligation from the maintainers. That is a statement about the licence text, not advice about your situation.

The alternative worth comparing: a managed voice agent platform

The obvious alternative is a hosted conversational voice product where you configure an agent in a web console and the vendor owns the media path, the scaling, and the provider relationships. The difference is not feature count, it is where the code lives and who is paged when a call drops. With a managed platform you get an SLA-shaped relationship and you give up the ability to change what happens between the transcriber and the synthesizer. With Bolna you get the orchestration source, an MIT licence, and the ability to swap Deepgram for Azure or ElevenLabs for Cartesia by editing a config object rather than filing a feature request. You also get the operational load: Redis, the telephony web server, and whatever replaces ngrok in production are yours. There is a middle option that is easy to miss, and it is inside Bolna's own architecture. The README notes that the hosted APIs are built on top of this orchestration platform, so choosing the hosted route is not choosing a different engine, it is choosing to rent the layer above it. If your reason for considering Bolna is provider flexibility, the open package is the only version of it you can inspect. If your reason is that you do not want to run Redis and a tunnel, the open package is the wrong end of the stack.

What to verify before you commit a production number

Three things are checkable from the material and worth doing before anything customer-facing. First, confirm the synthesizer provider you intend to use is genuinely wired, not just listed. The README names nine TTS providers and the repository topics name a partly different set, and a list in a README is not the same as a working integration. Second, run the local_setup stack once with a real Twilio or Plivo number and watch a full turn complete, because the interesting failures in voice systems are timing failures and a text-only example will not surface them. The README provides a text-only pipeline example as well, which is useful for exercising the LLM hop in isolation but tells you nothing about latency across the media path. Third, read API.md and decide whether the HTTP surface or the Python Assistant object is your integration point, since the README presents them as separate routes and only the Python one has an example in the README itself. If you need Exotel or Vonage, wait: both are marked coming soon, and the topics list does not include either.

Editorial conclusion

Adopt Bolna if you already run Twilio or Plivo numbers and want the ASR, LLM, and TTS hops in one Python process you can read and modify, and if you are comfortable that telephony, Redis, and ngrok are things you operate yourself. Do not adopt it if you need a managed dashboard or a vendor SLA, because those live in the closed hosted layer, and do not adopt it if you need Exotel or Vonage today, since the README lists both as coming soon. Before committing, read API.md for the HTTP surface, run the four-container local_setup stack once end to end, and check whether the provider you intend to use for TTS appears in the synthesizer list rather than only in the topics.

Official sources

  1. bolna-ai/bolna on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Community notes

Community notes