Self-hosted, multi-user AI assistant platform. Run a team of specialist agents, choose the LLM providers they use, and keep each user's data isolated on your own server.
OpenEnsemble is a single Node.js server that serves a web UI on port 3737. Create the owner account, connect at least one model provider, create an agent, and start a conversation.
Built-in roles create dedicated specialists for coding, email, research, calendar, expenses, image generation, and more. A coordinator can delegate work between them: "Give me a briefing on the latest advancements in AI and email it to me" can route research to a research agent and delivery to an email agent.
Multi-profile accounts keep each user's workspace, agents, skills, files, and settings separate. Owners and admins can enable or disable features and choose which models each user can access.
- Run
./install.sh. - Open http://{ip}:3737.
- Create the owner account, or restore an existing backup.
- Connect one provider in Settings -> Providers.
- Create a coordinator or specialist agent and send a message.
Everything else - email, calendar, MCP servers, remote nodes, voice devices, tunnels, and backups - can be added later.
Multi-agent chat. A roster of specialist agents each tuned for a role. The Coordinator reads incoming messages and delegates to the right specialist, or you can talk to one directly.
Bring your own LLMs. Providers include Anthropic, OpenAI (API key or ChatGPT-login/OAuth), Grok, Gemini, DeepSeek, Mistral, Groq, Together, Perplexity, Fireworks, OpenRouter, Z.ai, Ollama, and LM Studio. Enable what you want; assign different models per agent.
Skills. Capabilities agents can use, each defined by a small manifest:
| Skill | What the agent can do |
|---|---|
coder |
Edit files and run shell commands inside a bubblewrap sandbox; manage multi-file projects |
coordinator |
Delegate incoming messages to specialist agents |
deep_research |
Multi-step web research saved as persistent research documents |
email |
Unified Gmail / Microsoft-Exchange / IMAP mailbox access |
expenses |
Parse receipts, invoices, bank statements; track spending across groups |
gcal |
View and manage Google Calendar events |
image_generator |
Text-to-image via Fireworks Flux |
nodes |
Run commands and transfer files to remote machines via the OE node agent |
role_tutor |
Adaptive tutor that tracks per-subject progress and mastery |
role_video_generator |
Text-to-video generation |
shared-docs |
Read uploaded documents, photos, and videos |
skill-builder |
Create and edit custom skills at runtime |
tasks |
Schedule recurring and one-time agent tasks |
web |
Brave Search and URL fetch |
Use the built-in skill builder to add new capabilities at runtime. A blueprint ships with the installation, so you can ask your coding agent or coordinator to create a skill for something like Home Assistant control without editing the core app by hand.
Roles. Swap the persona/prompt on any agent without rebuilding it — role instructions live on the role, not the agent, so the coordinator can reassign roles cleanly.
Cortex — private reasoning & embeddings. Bundled local models run in-process via node-llama-cpp: a reasoning model (openensemble-reason-v1, SmolLM2-based GGUF) and nomic-embed-text-v1 embeddings. Retrieval, summarization, and classification can run without external calls or a GPU. Once OpenEnsemble is installed, run oe bench in the terminal to measure local performance.
Desktop & documents drawer. A unified view of everything the user has: uploaded docs, AI-generated images, AI-generated videos, research reports, files shared from other users, and code projects — each with its own tab. Code projects are downloadable as zip archives.
Expenses. Groups, books, receipt parsing, and per-user / per-group activity.
Background scheduler. Cron-like recurring tasks. Custom built-in LLM to set and parse tasks. (e.g. a daily news briefing, a nightly uploads-folder cleanup) plus one-shot tasks an agent schedules for itself.
Per-user everything. Agents, custom skills, sessions, chat history, uploads, AI outputs, code projects, and settings are all stored under users/{userId}/ — a fresh install with multiple accounts is fully isolated.
Remote nodes. Pair a machine with the server using a one-time code; the oe-node-agent then accepts exec and file-transfer commands scoped to that user. Useful for driving a homelab, a Raspberry Pi, or a workshop rig from the web UI. Have your agents keep your software up to date automatically, install new software, or debug your node. All from the chat interface.
Backup / restore. Compressed tar.gz snapshots of the entire install; restore works from the first-run screen too, so a fresh box can pull in an existing user base in one step.
Public and private access. Cloudflare Tunnel and Tailscale integrations can make an install reachable for OAuth callbacks, webhooks, sharing links, or private-network access without hand-rolling every host setup.
MCP servers. Connect local or remote Model Context Protocol servers and assign their tools to specific agents. Each user manages their own MCP servers and credentials.
Voice devices (beta). Pair a physical wake-word device — say "hey ensemble" (or any of the bundled wake words) and talk to your agents hands-free; the reply gets spoken back through the device's speaker or 3.5 mm jack. Includes a browser-based flash wizard (WebUSB + Web Serial — no dfu-util or esptool needed), per-slot voice and wake-word routing, household sharing (one device can route "hey roommate" to a different user's account), and a fast-path voice-control router for "volume up / pause / stop" without an LLM round-trip. Currently the only supported hardware is the Seeed reSpeaker XVF3800 4-Mic Array + XIAO ESP32-S3 carrier board. See the in-app Guide -> Voice devices section for pairing and flashing. The device firmware is open source at openensemble/voice-device-firmware; prebuilt binaries ship with OE, so you only need that repo to hack on the firmware itself.
- Linux (tested on Debian-family LXCs and VMs); macOS works for local dev
- Node.js ≥ 18 (the installer pulls one via
nvmif missing) build-essential,python3,python3-full,zip,bubblewrap,git,ffmpeg,openssl(installer offers to install them —gitis required for in-app auto-update; if you grabbed the source as a zip instead of cloning, installgitand rungit cloneover the install dir or auto-update will be disabled)- For voice devices (beta, optional): a Seeed reSpeaker XVF3800 4-Mic Array + XIAO ESP32-S3 carrier board. This is currently the only supported hardware. Other voice-hardware combinations may work but aren't tested or shipped with matching firmware. Chrome or Edge browser required for the in-app flash wizard (WebUSB + Web Serial).
git clone https://github.com/openensemble/openensemble.git
cd openensemble
./install.shThe installer:
- Checks for build tools and offers to install them
- Installs Node.js via
nvmif needed - Runs
npm install - Writes a default
config.json(providers all disabled) - Optionally registers a systemd user service so OE comes up at boot
Then open http://{ip}:3737 and walk through first-run setup. The required path is short: create the owner account, connect one model provider, create an agent, and chat. Optional integrations can wait.
For a clean Docker deployment:
docker build -t openensemble .
docker run -p 3737:3737 -v oe-data:/app/users openensembleProviders start disabled. Enable them from the web UI under Settings → Providers, or by editing config.json:
Environment variables override config values: ANTHROPIC_API_KEY, OPENAI_API_KEY, BRAVE_API_KEY, FIREWORKS_API_KEY, GROK_API_KEY, OPENROUTER_API_KEY, OLLAMA_API_KEY, OE_SESSION_EXPIRY, OE_VISION_PROVIDER, OE_VISION_MODEL.
Admin users see an "Update available" badge in the status bar and can apply updates from Settings → System → Software Update without dropping to a terminal. The server polls the configured git remote (default origin) every hour, fast-forwards the working tree on demand, runs npm install if package.json changed, then restarts itself using the same detached-respawn mechanism as the manual Restart button.
Tunable in config.json:
| Key | Default | Purpose |
|---|---|---|
updateCheckEnabled |
true |
Master switch for periodic polling |
updateCheckIntervalMs |
3600000 |
Poll interval (ms) — minimum 60000 |
updateRemote |
'origin' |
Git remote to follow |
The flow refuses to update when the working tree is dirty or has unpushed commits — it will never git stash or git reset --hard. Resolve those manually with git status first.
Trust note: auto-update means anyone with push access to the configured
updateRemotecan ship code that runs on every install. If you don't fully trust the upstream, fork the repo and setupdateRemoteto your fork.
- Session tokens live in the
Authorization: Bearerheader — never in URLs (URLs leak via Referer and access logs). - Media tokens are short-lived (10 min) URL-embedded tokens minted on demand, so
<img>/<video>/<iframe>elements can authenticate. Downloads that can't use fetch use these. - Coder shell sandbox wraps every shell command with
bubblewrap, giving the agent a read-only view of the system plus a writable bind-mount of just its own project directory. Network stays open (needed for npm / pip / git). - Role-based access:
owner,admin,user— plus per-user access schedules that can block logins outside chosen hours. - File-ownership enforcement: every path going to shell / download / delete is
realpath-checked against the caller's workspace before use, so symlinks can't escape.
agents/ default agent definitions
drawers/ built-in UI drawers (loaded alongside plugin drawers)
plugins/ bundled plugins (markets, news, tutor-today)
public/ static front-end (HTML, CSS, JS)
routes/ HTTP route modules
skills/ built-in skills and SKILL_BLUEPRINT.md
users/ per-user state (created on first run; ignored by git)
config.template.json template copied to config.json on install
server.mjs entry point
GNU Affero General Public License v3.0 or later. In plain English:
- Allowed: running OpenEnsemble yourself or for any commercial purpose, modifying it, redistributing it, and offering it as a hosted service.
- Required: if you modify OpenEnsemble and let anyone else use it (including over a network — hosting it for users counts), you must offer them the source of your modifications under the same AGPL-3.0 license.
- Required: preserve the copyright and license notices.
See LICENSE for the full text. For organizations that want to embed OpenEnsemble without the AGPL's copyleft obligation, a separate commercial license is available — get in touch.

{ "enabledProviders": { "anthropic": true, "openai": true, "ollama": true }, "anthropicApiKey": "sk-ant-…", "openrouterApiKey": "sk-or-…", "cortex": { "reasonProvider": "auto", // built-in, ollama, or lmstudio "lmstudioUrl": "http://127.0.0.1:1234" } }