Model or dataset
brenpoly/be-more-agent avatar
brenpoly/be-more-agent

be-more-agent: a local voice agent for Raspberry Pi, assembled from Ollama, Whisper.cpp and Piper

Local AI Agent running on Raspberry Pi

1,096 stars212 forksPythonMIT

At a glance

What is it?
The repository wires four offline speech and language components into one Python loop on a Raspberry Pi, with a config file and a folder of PNGs standing in for the character. It is a hardware project as much as a software one, and the README is honest about which parts are still rough.
Who is it for?
Adopt be-more-agent if you already have a Pi 5 or a 4GB Pi 4, a USB microphone and speaker, and you want a wake-word loop whose every component runs locally. Skip it if you need a supported product with pinned dependency versions, or if your audio hardware is unusual, because the sample-rate handling is the part most likely to cost you an evening.
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 last received commits 158 days ago.
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 problem is a voice assistant that keeps working when the network does not

Cloud assistants fail in a specific way on a hobby robot: the microphone works, the speaker works, and nothing else does. be-more-agent is built around removing that dependency. The README states the agent runs 100% locally, with Ollama for the language model, Whisper.cpp for speech-to-text, OpenWakeWord for the wake phrase and Piper for the voice. No API keys appear anywhere in the setup instructions, which is the practical difference. The intended user is someone building a physical character, not someone who wants a chat window. The project structure makes that clear: faces/ holds PNG sequences per state, sounds/ holds .wav files per category, and the README describes the software as a generic framework you give a personality to by replacing assets. If you only want a local LLM on a Pi, this is more machinery than you need. If you want a thing on a shelf that turns its head when you say its name, the asset-swap model is the right shape.

One Python loop, four models, and a state machine expressed as folders

agent.py is described as the main brain script. The data flow implied by the README is a loop: OpenWakeWord listens against wakeword.onnx, Whisper.cpp transcribes the captured speech, the transcript goes to the Ollama model named in config.json, and Piper synthesises the reply. Between those steps the GUI swaps face images, because the README lists listening, thinking, speaking, idle, error and warmup as separate folders under faces/. The state names and the folder names are the same vocabulary, so the face shown is a direct readout of where the loop currently is. Audio handling deserves attention because it is the part the README spends the most words on. The project claims hardware-aware audio: it detects your microphone's sample rate and resamples on the fly to avoid ALSA errors. That is a real mechanism, not a slogan, and it exists because Piper models are trained at a fixed rate. The README states agent.py expects medium quality models and plays audio at 22050 Hz by default, and that a model trained at 48000 Hz or 16000 Hz will sound wrong if played at the default. Search is the other branch: when the model does not know something, the agent queries DuckDuckGo. That is a network call inside an otherwise offline design, and the README does not describe a fallback when the Pi has no route to the internet beyond the troubleshooting note about duckduckgo-search being installed.

setup.sh does the system work, but the model pulls are yours

Installation is four steps and the README gives the exact commands. Update the OS first with sudo apt update && sudo apt upgrade -y and sudo apt install git -y. Then install Ollama with curl -fsSL https://ollama.com/install.sh | sh, followed by ollama pull gemma:2b and ollama pull moondream. Note the mismatch: the install section pulls gemma:2b, while the config.json example in the README sets text_model to gemma3:1b. Either the example is stale or the install list is. Verify which tag you actually pulled before assuming the agent will find it. After cloning, chmod +x setup.sh and ./setup.sh installs system libraries, creates folders, downloads Piper TTS and builds the Python virtual environment. The script also downloads the default wake word, which the README names as Hey Jarvis. To use your own, train a model at OpenWakeWord, drop the .onnx in the root folder and rename it wakeword.onnx. Running is source venv/bin/activate then python agent.py. The BMO voice arrives through the same script: setup.sh fetches bmo.onnx and bmo.onnx.json from the Releases page into a voices/ directory, and you point config.json at it with "voice_model": "voices/bmo.onnx". The config keys worth knowing are text_model, vision_model, voice_model, chat_memory, camera_rotation and system_prompt_extras. chat_memory writes to chat_memory.json, which means conversation history persists across runs unless you delete that file.

Sample rate mismatch is the failure mode the README documents in detail

The troubleshooting section is unusually candid, and the longest passage is about the custom voice sounding deep, slow or demonic. The README attributes this to a sample rate mismatch between the model and the audio player, and states plainly that it is not a Piper installation problem. The fix it gives is to match the rate: agent.py assumes 22050 Hz for medium quality models, so a model trained at 48000 Hz or 16000 Hz needs either a different model or a change on the agent side. This is the kind of bug that reads as a broken project when it is actually a configuration error, and it will hit anyone who trains their own voice. Two other rough edges are documented. Web search fails with "No search library found" if duckduckgo-search is missing from the active virtual environment. And on Ctrl+C you may see Expression 'alsa_snd_pcm_mmap_begin' failed, which the README explicitly calls normal, caused by the audio stream being cut mid-sample. Treating that message as a bug will waste time. The broader limitation is platform scope: the README targets Raspberry Pi 5 as recommended and Pi 4 with 4GB minimum, plus a USB microphone, speaker, LCD screen and camera module. Vision runs through Moondream, which is a small model and will not match a hosted vision API on difficult images. Nothing in the material describes multi-user handling, authentication or any network-facing service, so this is a single-device appliance by design.

Against a cloud voice assistant, the trade is latency and quality for independence

The obvious alternative is a hosted stack: a wake word on device, then cloud speech-to-text, a hosted LLM and a hosted TTS voice. That combination will generally transcribe noisy speech better and answer harder questions, because the models are larger than anything a Pi 4 runs comfortably. The difference in approach is where the compute sits and who pays for it. be-more-agent keeps every model on the device, which removes per-request cost and removes the requirement that the device be online for the core loop. It also means the ceiling is set by the Pi. gemma:2b and gemma3:1b are small models, and the README's own example system prompt asks for short, cute responses, which is a reasonable fit for a 2B model and a poor fit for long analytical answers. A second alternative is assembling the same pieces yourself without this repository: Ollama, Whisper.cpp, OpenWakeWord and Piper all exist independently, and someone comfortable with Python could wire them together. What you would be rebuilding is the state machine, the asset folder conventions and the resampling logic. That is the actual contribution here, and it is worth being clear-eyed about it: the value is integration and the character framework, not any new model.

Maintenance cost is low in code and high in models and hardware

The licence is MIT, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are included. That is a permissive licence, but it covers the repository's code, not the models it downloads. Ollama, Whisper.cpp, Piper, OpenWakeWord and Moondream each carry their own terms, and the BMO voice model is distributed through this project's Releases page with no licence stated in the supplied material. If you plan to ship a product built on this, check the voice model's terms separately; nothing here should be read as legal advice. On the code side, agent.py is a single script, so upgrades are a git pull plus a look at config.json for new keys, and the README notes the script creates config.json on first run if it is missing. That convenience cuts both ways: a config generated at first run will not gain new keys added in later versions, so after an upgrade, compare your config.json against the current example rather than assuming defaults. The heavier cost is the model layer. Ollama tags move, and the gemma:2b versus gemma3:1b discrepancy in the README is a small preview of that. The two releases listed are v1.0-voice, the custom voice model, and v1.0-enclosure, the 3D files for the BMO shell, both dated 2026. That tells you the project's recent activity is in physical and audio assets, not in the Python loop, which is worth weighing if you need something under active development on the software side.

Who this fits, and what to check before you commit an enclosure

The fit is narrow and clear. You have a Pi 5 or a 4GB Pi 4, a USB microphone and speaker, a screen and a camera, and you want a character that responds to a wake word without sending audio anywhere. You are willing to train or source an OpenWakeWord model if Hey Jarvis is not what you want to say. You accept that the language model is small and that web search is the escape hatch for anything current. You should not adopt it if you need pinned, reproducible dependency versions, because setup.sh pulls system libraries and models at install time and the README does not describe a lockfile. You should not adopt it if your audio path is unusual or if you need more than one wake word. The first thing to verify is the voice: run agent.py with the default Piper model before switching to voices/bmo.onnx, so that when the BMO voice sounds wrong you know the loop itself works. The second is the microphone rate, because the resampling claim is the one mechanism that has to hold for everything downstream. The third is the model tag, since the README's install commands and config example disagree. Get those three straight on a bare Pi before you print the enclosure.

Editorial conclusion

Adopt be-more-agent if you already have a Pi 5 or a 4GB Pi 4, a USB microphone and speaker, and you want a wake-word loop whose every component runs locally. Skip it if you need a supported product with pinned dependency versions, or if your audio hardware is unusual, because the sample-rate handling is the part most likely to cost you an evening. Before wiring anything into an enclosure, run agent.py on the desk, confirm your chosen .onnx voice plays at the rate agent.py expects, and check that your microphone's detected rate survives a reboot.

Official sources

  1. brenpoly/be-more-agent on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Community notes

Community notes