06Ship
Deploy
Size your machine, run workers, and serve in production.
Measure first
cuelo machine checkThis streams real speech through your actual turn-taking stack at rising concurrency, and reports how many calls stay real-time. Inside a project it uses the project's controllers. Elsewhere it uses the default stack. It then sizes worker processes from your CPU and memory and checks them running together.
cuelo machine check --single # one process only
cuelo machine check --seconds 15 # longer per load levelWhat we measured on an M3 Pro (11 cores, 5 performance):
| Stack | Per process | Whole machine | Memory / process |
|---|---|---|---|
| Default (turn-1-mini + MaAI barge-in + MaAI backchannels) | 5 calls | 8 (4 workers × 2) | ~1 GB |
Light (backchannel-detector + vad backchannels) | 64 calls | 72 (2 workers × 36) | ~160 MB |
The Python GIL caps one process at about 4 cores. Beyond that, add workers.
Speech and LLM run at the providers, so their cost doesn't depend on your machine. The turn-taking models run locally.
Serve
cuelo serve # serve.host, serve.port, serve.workers from config.cuelo
cuelo serve --port 8080serve:
host: 0.0.0.0
port: 4141
workers: 4 # from cuelo machine check
api_keys: ["${CUELO_KEY}"] # required on a public host
cors: ["https://app.example.com"]Each worker is a separate process with its own calls and models. A call stays
on the worker its WebSocket landed on. Under cuelo-serve directly, use
--workers N or CUELO_WORKERS.
Checklist
- API keys set (the server refuses a public host without them). See Security.
- TLS at a reverse proxy or load balancer. Browsers need
wss://for the microphone on non-localhost origins. Enable WebSocket upgrades and raise idle timeouts above your longest call. - Store on Postgres or MySQL for more than one machine.
store.audioon a persistent volume. - Weights pre-downloaded in your image (
cuelo models pull --all, orpython -m cuelo.controllers.weights), so the first call doesn't wait.CUELO_MODELSsets the cache directory (default~/.cache/cuelo/models). - Health:
GET /healthreturns{"ok": true, "agent": ...}without a key. - Region: run close to your STT, LLM and TTS endpoints. Network round trips are a large share of latency.
Container
FROM python:3.13-slim
RUN pip install uv
WORKDIR /app
COPY . .
RUN uv sync --frozen
ENV CUELO_MODELS=/app/.models CUELO_TORCH_THREADS=1
RUN uv run python -m cuelo.controllers.weights # bake turn-taking weights into the image
EXPOSE 4141
CMD ["uv", "run", "cuelo-serve", "generated/pipeline.py", "--host", "0.0.0.0", "--port", "4141"]Pass credentials at runtime (--env-file .env or your platform's secrets).
Don't bake them into the image.