Bolna is the bottom layer of three tiers, and the other two are closed source
Conversational voice AI agents
At a glance
- What is it?
- Bolna is an open source orchestration platform for LLM voice agents, combining ASR, LLM and TTS providers over websockets so you can build voice agents from JSON and Python. It is the layer the hosted product sits on, and the seams are worth mapping: the default branch is master while the README links to main, both Python examples stop inside a constructor, and the streaming output has no fixed shape.
- Who is it for?
- Take Bolna if you need a voice agent orchestration layer you can read and modify, and you are willing to wire your own telephony credentials and a tunnel. Leave it if you need the hosted API or the no-code playground, because both are closed source, or if you need a documented streaming schema, because the README says the result keys depend on your configuration.
- 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 October 5, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Three tiers, two of them closed, and a deliberate order of publication
The product is described as three components. The first is the orchestration platform, which is this repository. The second is a set of hosted APIs built on top of that orchestration, currently closed source. The third is a no-code playground at platform.bolna.ai using those hosted APIs plus Tailwind CSS, also currently closed source.
The development philosophy explains why that split is not an accident. Every integration or feature lands in the open source package first, because that package is the backbone of the hosted APIs and the dashboard. Only then are APIs exposed or changed, and only after that does the work reach the UI. A flow diagram states the same chain in one line: open source, then hosted APIs, then hosted playground.
Read that as a promise and as a limit. It means new provider support lands where you can read it, which is unusual. It also means the interface most people try first, the playground, is not in this tree, and the hosted API reference is a separate site from the repository's own API.md.
The default branch is master and the README links point at main
This repository's default branch is `master`, while the badge links at the top of the README point to `blob/main/LICENSE` and `blob/main/CONTRIBUTING.md`. GitHub will usually resolve a link written for the wrong branch through its redirect behaviour, which is why this survives, but it means the page's own links are not the repository's actual branch names.
Versioning is unusually mechanical, and the mechanism is visible in the project configuration rather than in a release policy document. commitizen is configured with conventional commits, reads the version from the project metadata, and uses `tag_format = "$version"`, so a release is tagged `0.10.269` rather than `v0.10.269`. The only version file it maintains is `bolna/__init__.py:__version__`, and changelog updates on bump are switched off.
The cadence that produces is fast. Releases 0.10.267, 0.10.268 and 0.10.269 landed on 2026-10-01 and 2026-10-02, and the project version in the manifest matches the newest tag. Three releases in two days is normal for this repository, which makes the branch inconsistency and the missing changelog the two things worth complaining about.
The provider list, the env sample and the dependency file disagree three ways
The provider inventory is described in four sentences: telephony for initiating calls, transcription, LLMs, and synthesis. Two telephony providers carry a marker, Exotel and Vonage, and both are marked coming soon. The rest are unmarked, so the list mixes shipped and planned entries with only two flags.
The environment sample is narrower than that list. `.env.sample` holds a Deepgram token, a Soniox key, an ElevenLabs key, an OpenAI key, a default OpenAI model of gpt-3.5-turbo, a Redis URL, three Twilio fields and three Plivo fields. Soniox is the odd one out, because Soniox appears nowhere in the provider sentences. Azure, Cartesia, Smallest, Maya, Kalpa and Polly are the other way round: named in the prose, absent from the sample.
The dependency file is wider than both. `requirements.txt` pins google-cloud-speech, groq, google-genai and litellm alongside the providers the README names, so Groq and the Google models are reachable in code but absent from the documentation's provider list, where they fall under the word etc. Read the sample as a starting point for Twilio or Plivo with Deepgram and OpenAI, not as a description of what the code can reach.
The local setup tunnels through ngrok, and its heading says it will move out
The runnable example lives in `local_setup/`, and the heading carrying it is annotated with a note that it will be moved to a different repository. That single parenthetical tells you the Docker environment is not where this example is going to live.
Four containers make it up. A telephony web server, which is either Twilio or Plivo. The Bolna server that creates and handles agents. ngrok, for tunnelling, where you add your `authtoken` to `ngrok-config.yml`. And redis, for persisting agents and prompt data.
The quick path is one script:
cd local_setup
chmod +x start.sh
./start.shIt checks for Docker dependencies, builds all services with BuildKit enabled and starts them detached. The manual path spells out what the script hides, and both of those environment variables matter:
export DOCKER_BUILDKIT=1
export COMPOSE_DOCKER_CLI_BUILD=1
docker compose build
docker compose up -d
docker compose up -d bolna-app twilio-appNote what the tunnel means. With ngrok in the middle, the telephony server in your local environment is reachable from outside, which is what lets a telephony provider call it. That is the intended design, and it is also the reason this setup is a developer demo rather than something to leave running.
Both Python examples stop inside a constructor, so neither one is copyable
The programmatic path is two example files, `examples/simple_assistant.py` and `examples/text_only_assistant.py`, and the README shows both. Neither snippet is complete: the first ends inside the `LlmAgent` constructor right after the model line, and the second ends on a line reading `enable_text` with no value and no closing parenthesis.
What the visible part does establish is the shape of the configuration. The voice example builds an `Assistant`, a `Transcriber` on Deepgram with model nova-2, streaming enabled and language en, and an `LlmAgent` with `agent_type` set to simple_llm_agent, an `agent_flow_type` of streaming, and an OpenAI `SimpleLlmAgent` on gpt-4o-mini. The text-only example drops the transcriber and synthesizer entirely and adds `temperature=0.2`.
Running either needs keys in the environment:
export OPENAI_API_KEY=...
export DEEPGRAM_AUTH_TOKEN=...
export ELEVENLABS_API_KEY=...
python examples/simple_assistant.pyThe text-only example needs only the OpenAI key. In both cases the missing half is in the example file itself rather than in a snippet you can reconstruct from the page.
The streaming result has no fixed shape, and the README admits it
The most useful sentence about the output is also the most cautionary one. `assistant.execute()` is an async generator that yields per-task result dicts described as event-like chunks, and the exact keys depend on which tools and providers you configured. The instruction is to treat it as a stream and process it incrementally. For the text-only pipeline the wording is the same with one difference: it yields streaming dicts per task step, and the fields vary by configuration.
That is an honest description of an event protocol and a poor contract for an application. There is no typed event union, no version field and no list of guaranteed keys, so a consumer has to handle whatever arrives. Code written against one provider configuration will need to be defensive about another.
The HTTP surface is the other half of the picture and it lives elsewhere. Agent CRUD over HTTP is described in `API.md` at the repository root, so the REST contract and the streaming contract are documented in two different documents with two different levels of precision.
A deliberately tiny lint with a written roadmap, and a dependency file that mixes pins
The lint configuration is an admission rather than a standard. ruff runs with line length 120 and target py310, and selects exactly three rules: E721 for type comparison, F811 for a redefined unused name, and ISC for implicit string concatenation bugs. The comment above them says to start minimal and grow over time, then gives the order: F541, UP, F401, F841, isort, then pycodestyle.
Testing is configured to match that style of incrementalism. pytest runs in asyncio auto mode, so coroutine tests need no marker, with `--strict-markers` on and `testpaths` set to tests. The dev extras are pip-tools, pre-commit, pytest, pytest-asyncio and ruff, and the root also carries a pre-commit configuration and a `.git-blame-ignore-revs` file, which is how formatting-only commits get kept out of blame.
Dependencies are declared dynamic and read from `requirements.txt`, which is thirty-one packages of mixed policy: most are pinned exactly, a dozen carry only a lower bound, and protobuf is the single entry with an upper bound as well. That file is the real shape of this project, and it is worth reading before you decide how much of the stack you want to inherit.
Editorial conclusion
Take Bolna if you need a voice agent orchestration layer you can read and modify, and you are willing to wire your own telephony credentials and a tunnel. Leave it if you need the hosted API or the no-code playground, because both are closed source, or if you need a documented streaming schema, because the README says the result keys depend on your configuration. Three things to check first: which telephony service you will actually pay for, since Exotel and Vonage are marked coming soon while Twilio and Plivo are wired into the local setup, whether the version you pin still matches `bolna/__init__.py`, since tags are bare numbers written by commitizen, and whether you accept that the example environment exposes a tunnel to the internet through ngrok.
Frequently asked questions
What does bolna do?
It is the orchestration platform for building LLM based voice agents. It technically orchestrates voice conversations using a combination of ASR, LLM and TTS providers and models over websockets, and you can define an agent from JSON or drive it from Python.
Is bolna open source?
The orchestration platform is open source under the MIT license. The hosted APIs and the no-code playground at platform.bolna.ai are both currently closed source, and the README states the order of work: open source first, then hosted APIs, then the dashboard.
Which telephony providers does bolna support?
Twilio and Plivo are wired into the local setup, with a separate twilio-app or plivo-app compose service for each. Exotel and Vonage are listed but marked coming soon. You supply your own credentials through a .env file populated from .env.sample.
How do I run bolna locally?
Use the script in local_setup: `cd local_setup`, `chmod +x start.sh`, `./start.sh`. It checks Docker dependencies, builds the services with BuildKit and starts them detached. The manual path needs Docker Compose V2, `export DOCKER_BUILDKIT=1`, `export COMPOSE_DOCKER_CLI_BUILD=1`, then `docker compose build` and `docker compose up -d`.
Can I use bolna without telephony?
Yes. examples/simple_assistant.py runs a voice pipeline with a Deepgram transcriber and an OpenAI LLM, and examples/text_only_assistant.py runs a text-only pipeline with no transcriber or synthesizer. Both need OPENAI_API_KEY exported, and the voice example also expects DEEPGRAM_AUTH_TOKEN and ELEVENLABS_API_KEY.
Is the bolna project looking for maintainers?
The README carries a note saying they are actively looking for maintainers. Releases move quickly: 0.10.269, 0.10.268 and 0.10.267 all landed on 2026-10-01 and 2026-10-02, and tags are written as bare version numbers by commitizen rather than with a v prefix.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/bolna-ai-bolna)