Skip to content
Pages of the documentation

Providers

The models, speech services and channels Nestor works with today, what is planned, and how to set each one up.

Nestor needs a language model for the agent, and speech services only to talk aloud. People reach it through channels: Telegram, satellites (in writing, aloud or both), or all of them. Everything is set in nestor.yaml, with the keys in the .env next to it. nestor init asks for the model server and the model, and writes satellites with Telegram, or satellites with their voice on ElevenLabs when the voice extra is installed. To change a provider later, paste its blocks below over the matching ones, then run nestor check.

Language model

The agent talks to any server that speaks the OpenAI Chat Completions API, with streaming. The adapter is tested against OpenRouter; the others speak the same API and are expected to work. Pick a model that supports tool calls: the agent acts through them.

The model’s key is MODEL_API_KEY, in .env, whatever the provider. Local servers need none: leave it empty. OpenRouter, OpenAI, Mistral and Anthropic refuse an empty key, and nestor check names the variable to fill.

One key for models from many vendors, Claude and Gemini included. It is the default, and the provider the adapter is tested against.

MODEL_API_KEY=sk-or-...
model:
  kind: openai-compatible
  base_url: https://openrouter.ai/api/v1
  api_key: ${MODEL_API_KEY}
  model: anthropic/claude-haiku-5.5

The model names are examples: any model of the provider’s catalogue that supports tool calls will do, and any other OpenAI-compatible host works the same way. On most home hardware a local model answers more slowly than a hosted one, and speech feels it first.

With Docker, localhost is the container itself. A model server running on the host is http://host.docker.internal:<port>/v1: http://host.docker.internal:11434/v1 for Ollama, http://host.docker.internal:1234/v1 for LM Studio. On Linux, that address is not the host’s loopback, so the model server must listen beyond it: OLLAMA_HOST=0.0.0.0 for Ollama, --host 0.0.0.0 for llama.cpp.

model also takes extra_body, merged into every request (OpenRouter’s routing, reasoning settings…), connect_timeout_s (5) and read_timeout_s (30). A triage_model with the same keys gives the sorting of incoming items to a smaller model.

Speech

The satellites’ voice transcribes the person and speaks the answer. ElevenLabs is the one provider today, for both; a new one ships once it holds up on reproducible measurements (latency, turn ends, interruptions).

Scribe v2 Realtime transcribes, v4 Turbo speaks; one key covers both.

ELEVENLABS_API_KEY=sk_...
channels:
  - kind: satellites
    host: 0.0.0.0
    voice:
      speech:
        api_key: ${ELEVENLABS_API_KEY}
        voice_id: GPAQQPp9dazaB2bl4zg9

voice_id is any voice of your ElevenLabs library. The voice follows the language of the text; the transcription listens for English unless speech sets another language (see below).

Channels

Each channel is an entry of channels, and several can run side by side with the same memory. Telegram and satellites come with the package. Satellites talk in writing out of the box; their voice is the voice extra (see Install), with the speech services above.

Create a bot with Telegram’s @BotFather and put its token in .env:

TELEGRAM_BOT_TOKEN=123456:ABC-...
channels:
  - kind: telegram
    token: ${TELEGRAM_BOT_TOKEN}

Add "telegram:<your chat id>" to your accounts in household so the bot knows you. It reads text messages; voice notes and pictures are ignored.

In French

nestor init asks for the household’s language. Without it, Nestor speaks English, on UTC. To switch an existing configuration to French, set the persona’s locale (the fixed phrases and the admin), the language the model writes in, the household’s timezone and, with the satellites’ voice, the transcription’s language:

persona:
  locale: fr
  language: French
  timezone: Europe/Paris

channels:
  - kind: satellites
    voice:
      speech:
        language: fr

Where keys live

  • .env, next to nestor.yaml, referred to as ${NAME}: what nestor init writes and the blocks above use. Nestor reads it at each start. A variable already set in the environment (the shell, a service manager, Docker) wins over the file.
  • The vault, encrypted in the data folder, referred to as ${secret:name}: set with nestor secrets set <name> (asked without echo) or from the admin, listed with nestor secrets list. Move keys there once the installation settles: none sits in clear on disk, and the admin can change them.
nestor secrets set openrouter   # then, in nestor.yaml: api_key: ${secret:openrouter}

NESTOR_SECRET_KEY, in .env, opens the vault. nestor init generates it: never change it, or the secrets already stored can no longer be read. Restart Nestor after changing a key.