Local voice assistant that learns new abilities via auto-discovered n8n workflows exposed as tools via MCP
Find a file
cmac86 5fea2c3748
fix: reload-tools endpoint uses correct MCP server attribute (#20)
The reload-tools webhook was referencing agent._n8n_mcp which was
removed in commit 2aa0d1e when multi-MCP support was added. Now
correctly retrieves n8n MCP client from agent._caal_mcp_servers dict.

Fixes #18
2026-01-07 17:09:57 -08:00
.github docs: add GitHub community standards and restructure README (#10) 2026-01-04 14:42:36 -08:00
docs Fix Apple Silicon startup and improve mlx-audio reliability (#12) 2026-01-04 19:13:30 -08:00
frontend feat: add turn detection settings (allow_interruptions, min_endpointing_delay) 2026-01-05 22:02:20 -08:00
mobile feat: add turn detection settings (allow_interruptions, min_endpointing_delay) 2026-01-05 22:02:20 -08:00
models Add wake word models to repository 2026-01-03 19:21:34 -08:00
n8n-workflows Fix CAAL_HOST placeholder in workflow builder seed 2025-12-24 00:50:56 -08:00
prompt Improve default prompt for better tool calling behavior 2026-01-05 21:20:42 -08:00
src/caal fix: reload-tools endpoint uses correct MCP server attribute (#20) 2026-01-07 17:09:57 -08:00
.dockerignore Fix server-side wake word detection with StreamAdapter 2026-01-02 01:28:49 -08:00
.env.example Add distributed deployment support (GPU backend + macOS frontend) (#8) 2026-01-03 20:20:30 -08:00
.gitattributes Add .gitattributes to fix Windows line ending issues 2025-12-31 10:50:41 -08:00
.gitignore Add wake word models to repository 2026-01-03 19:21:34 -08:00
CODE_OF_CONDUCT.md docs: add GitHub community standards and restructure README (#10) 2026-01-04 14:42:36 -08:00
CONTRIBUTING.md docs: add GitHub community standards and restructure README (#10) 2026-01-04 14:42:36 -08:00
docker-compose.apple.yaml Fix Apple Silicon startup and improve mlx-audio reliability (#12) 2026-01-04 19:13:30 -08:00
docker-compose.dev.yml Initial commit - CAAL Voice Framework 2025-12-24 00:22:19 -08:00
docker-compose.distributed.yml Add distributed deployment support (GPU backend + macOS frontend) (#8) 2026-01-03 20:20:30 -08:00
docker-compose.yaml Fix docker compose startup with missing config files 2026-01-02 20:52:02 -08:00
Dockerfile Fix docker compose startup with missing config files 2026-01-02 20:52:02 -08:00
entrypoint.sh Fix docker compose startup with missing config files 2026-01-02 20:52:02 -08:00
LICENSE Initial commit - CAAL Voice Framework 2025-12-24 00:22:19 -08:00
livekit-tailscale.yaml Add distributed deployment support (GPU backend + macOS frontend) (#8) 2026-01-03 20:20:30 -08:00
livekit-tailscale.yaml.template Initial commit - CAAL Voice Framework 2025-12-24 00:22:19 -08:00
livekit.yaml Initial commit - CAAL Voice Framework 2025-12-24 00:22:19 -08:00
mcp_servers.default.json Fix docker compose startup with missing config files 2026-01-02 20:52:02 -08:00
mcp_servers.json.example Add multi-MCP server support via JSON config (#3) 2025-12-31 13:51:31 -08:00
nginx-distributed.conf Add distributed deployment support (GPU backend + macOS frontend) (#8) 2026-01-03 20:20:30 -08:00
nginx.conf Initial commit - CAAL Voice Framework 2025-12-24 00:22:19 -08:00
pyproject.toml Add server-side OpenWakeWord wake word detection 2026-01-02 00:04:52 -08:00
README.md Update README hero image with CoreWorxLab branding 2026-01-04 14:50:22 -08:00
SECURITY.md docs: add GitHub community standards and restructure README (#10) 2026-01-04 14:42:36 -08:00
settings.default.json Fix default model and dynamic wake word tooltip 2026-01-03 20:34:34 -08:00
start-apple.sh Fix Apple Silicon startup and improve mlx-audio reliability (#12) 2026-01-04 19:13:30 -08:00
uv.lock Fix server-side wake word detection with StreamAdapter 2026-01-02 01:28:49 -08:00
voice_agent.py feat: add turn detection settings (allow_interruptions, min_endpointing_delay) 2026-01-05 22:02:20 -08:00

CAAL

License: MIT Python 3.10+ LiveKit

Local voice assistant that learns new abilities via auto-discovered n8n workflows exposed as tools via MCP

Built on LiveKit Agents with fully local STT/TTS/LLM using Speaches, Kokoro, and Ollama.

CAAL Voice Assistant

Features

  • Local Voice Pipeline - Speaches (Faster-Whisper STT) + Kokoro (TTS) + Ollama LLM
  • Wake Word Detection - "Hey Cal" activation via Picovoice Porcupine
  • n8n Integrations - Home Assistant, APIs, databases - anything n8n can connect to
  • Web Search - DuckDuckGo integration for real-time information
  • Webhook API - External triggers for announcements and tool reload
  • Mobile App - Flutter client for Android and iOS

Quick Start

Choose your deployment mode:

Mode Hardware Command Documentation
NVIDIA GPU Linux + NVIDIA GPU docker compose up -d Below
Apple Silicon M1/M2/M3/M4 Mac ./start-apple.sh docs/APPLE-SILICON.md
Distributed GPU Server + macOS See docs docs/DISTRIBUTED-DEPLOYMENT.md

NVIDIA GPU (Linux)

Requirements

Installation

# Clone and configure
git clone https://github.com/CoreWorxLab/caal.git
cd caal
cp .env.example .env
nano .env  # Set CAAL_HOST_IP, OLLAMA_HOST, N8N_MCP_URL, N8N_MCP_TOKEN

# Deploy
docker compose up -d

Open http://YOUR_SERVER_IP:3000 from any device on your network.


Apple Silicon (macOS)

CAAL runs on Apple Silicon Macs using mlx-audio for Metal-accelerated STT/TTS.

./start-apple.sh

See docs/APPLE-SILICON.md for full setup instructions.


Distributed Deployment

Run the GPU-intensive backend on a Linux server while using the frontend on a Mac or another device.

See docs/DISTRIBUTED-DEPLOYMENT.md for full setup instructions.


Network Modes

CAAL supports three network configurations:

Mode Voice From Access URL Command
LAN HTTP Host machine only http://localhost:3000 docker compose up -d
LAN HTTPS Any LAN device https://192.168.1.100 docker compose --profile https up -d
Tailscale Anywhere https://your-machine.tailnet.ts.net docker compose --profile https up -d

Why? Browsers block microphone access on HTTP except from localhost. HTTPS is required for voice from other devices.

LAN HTTP (Default)

CAAL_HOST_IP=192.168.1.100  # Set in .env
docker compose up -d

LAN HTTPS (mkcert)

# Generate certificates
mkcert -install
mkcert 192.168.1.100
mkdir -p certs && mv 192.168.1.100.pem certs/server.crt && mv 192.168.1.100-key.pem certs/server.key
chmod 644 certs/server.key

# Configure .env
CAAL_HOST_IP=192.168.1.100
HTTPS_DOMAIN=192.168.1.100

# Build and start
docker compose --profile https build frontend
docker compose --profile https up -d

Tailscale (Remote Access)

# Generate Tailscale certs
tailscale cert your-machine.tailnet.ts.net
mkdir -p certs && mv your-machine.tailnet.ts.net.crt certs/server.crt && mv your-machine.tailnet.ts.net.key certs/server.key

# Configure .env
CAAL_HOST_IP=100.x.x.x                         # tailscale ip -4
HTTPS_DOMAIN=your-machine.tailnet.ts.net

# Build and start
docker compose --profile https build frontend
docker compose --profile https up -d

Configuration

Essential Environment Variables

Variable Description Required
CAAL_HOST_IP Your server's LAN/Tailscale IP Yes
OLLAMA_HOST Ollama server URL Yes
N8N_MCP_URL n8n MCP endpoint Yes
N8N_MCP_TOKEN n8n access token Yes
OLLAMA_MODEL LLM model (default: ministral-3:8b) No
TTS_VOICE Kokoro voice (default: am_puck) No
PORCUPINE_ACCESS_KEY Picovoice key for wake word No

See .env.example for full configuration options.


Integrations

n8n Workflows

CAAL discovers tools from n8n workflows via MCP. Each workflow with a webhook trigger becomes a voice command.

cd n8n-workflows
cp config.env.example config.env
nano config.env  # Set your n8n IP and API key
python setup.py  # Creates all workflows

Setup n8n:

  1. Enable MCP: Settings > MCP Access > Enable MCP
  2. Set connection method to Access Token and copy the token
  3. Set N8N_MCP_URL in .env

See n8n-workflows/README.md for included workflows.

Wake Word Detection

  1. Get a free access key from Picovoice Console
  2. Train "Hey Cal" wake word, download Web (WASM) model
  3. Place hey_cal.ppn in frontend/public/
  4. Set PORCUPINE_ACCESS_KEY in .env
  5. Rebuild: docker compose build frontend && docker compose up -d

Webhook API

Endpoint Method Description
/announce POST Make CAAL speak a message
/wake POST Trigger wake word greeting
/reload-tools POST Refresh MCP tool cache
/health GET Health check
curl -X POST http://localhost:8889/announce \
  -H "Content-Type: application/json" \
  -d '{"message": "Package delivered"}'

Mobile App

Flutter client for Android and iOS in mobile/.

cd mobile
flutter pub get
flutter run

See mobile/README.md for full documentation.


Development

# Install dependencies
uv sync

# Start infrastructure
docker compose up -d livekit speaches kokoro

# Run agent locally
uv run voice_agent.py dev

# Run frontend locally
cd frontend && pnpm install && pnpm dev

Commands:

uv run ruff check src/   # Lint
uv run mypy src/         # Type check
uv run pytest            # Test

Architecture

┌───────────────────────────────────────────────────────────────────────┐
│  Docker Compose Stack                                                 │
│                                                                       │
│  ┌────────────┐  ┌────────────┐  ┌────────────┐  ┌────────────┐       │
│  │  Frontend  │  │  LiveKit   │  │  Speaches  │  │   Kokoro   │       │
│  │  (Next.js) │  │   Server   │  │ (STT, GPU) │  │ (TTS, GPU) │       │
│  │   :3000    │  │   :7880    │  │   :8000    │  │   :8880    │       │
│  └─────┬──────┘  └─────┬──────┘  └─────┬──────┘  └─────┬──────┘       │
│        │               │               │               │              │
│        │               └───────────────┼───────────────┘              │
│        └───────────────────────┐       │                              │
│                                │       │                              │
│                          ┌─────┴───────┴─────┐                        │
│                          │       Agent       │                        │
│                          │  (Voice Pipeline) │                        │
│                          │  :8889 (webhooks) │                        │
│                          └─────────┬─────────┘                        │
│                                    │                                  │
└────────────────────────────────────┼──────────────────────────────────┘
                                     │
                   ┌─────────────────┼─────────────────┐
                   │                 │                 │
             ┌─────┴─────┐     ┌─────┴─────┐     ┌─────┴─────┐
             │  Ollama   │     │    n8n    │     │   Your    │
             │   (LLM)   │     │ Workflows │     │   APIs    │
             └───────────┘     └───────────┘     └───────────┘
                    External Services (on your network)

Troubleshooting

WebRTC Not Connecting

  1. Check CAAL_HOST_IP matches your network mode
  2. Verify firewall ports: 3000, 7880, 7881, 50000-50100 (UDP)
  3. Check logs: docker compose logs livekit | grep -i "ice\|error"

Ollama Connection Failed

# Ensure Ollama binds to network
OLLAMA_HOST=0.0.0.0 ollama serve

# From Docker, use host.docker.internal
OLLAMA_HOST=http://host.docker.internal:11434

First Start Is Slow

Normal - models download on first run (~2-5 minutes):

docker compose logs -f speaches kokoro


Contributing

We welcome contributions! See CONTRIBUTING.md for guidelines.

License

MIT License - see LICENSE for details.