Aller au contenu

Construire avec Nestor.

Un runtime Python qui garde un agent en vie pour un foyer. Canaux, satellites, connecteurs, exécutants et fournisseurs d’IA se branchent au cœur par des contrats publics.

  • Python 3.12+ · SQLite · MIT
  • Satellites en WebRTC · SDK Python, TypeScript, Rust
  • Home Assistant · MCP · OAuth 2.1 avec PKCE

Un cœur, et tout le reste branché.

Le cœur ne connaît aucun fournisseur ; tout le reste se branche. Choisissez une partie.

Le cœur

Agent central

Tient la conversation sur tous les canaux avec un modèle rapide et remplaçable, et des outils directs pour ce qui est fréquent et court : la maison, la mémoire, les minuteurs, les recherches rapides.

  • Première phrase en 0,64 s médian, en appel direct
  • Un outil passe de la délégation à l’appel direct seulement si la latence mesurée le justifie

ContratsConversationModelToolProvider

Une veille, à travers le système.

Le colis, tel que le cœur le vit.

  1. hier · 20:40

    Elle le demande une fois.

    Sur Telegram, la veille au soir. Nestor répond dans la foulée et crée une veille : une propriétaire, une source (sa boîte mail), des mots-clés et une fin.

    Préviens-moi quand mon colis Vinted arrive au point relais.

  2. hier · 20:40

    La veille survit à la conversation.

    La discussion est finie, pas l’engagement. La veille est écrite au journal et survit aux redémarrages, aux changements de modèle et aux nuits. Personne n’a besoin de garder un onglet ouvert.

  3. aujourd’hui · 17:48

    Le mail arrive.

    Sa boîte, branchée en IMAP depuis l’administration, reçoit un message du transporteur. C’est un candidat, rien de plus pour l’instant.

  4. aujourd’hui · 17:48

    Le tri, du moins cher au plus cher.

    D’abord des règles déterministes, puis un petit modèle de classification, et l’agent central seulement pour ce qui mérite d’être formulé. La plupart des événements s’arrêtent au premier étage.

  5. aujourd’hui · 17:48

    La présence décide où.

    Home Assistant indique que Léa est au salon. Pas d’heures calmes, pas de conversation en cours : il décide de le dire à voix haute sur le satellite de la pièce, et écrit pourquoi.

  6. aujourd’hui · 17:48

    Nestor le dit au salon.

    Le Reachy Mini du salon parle ; ses antennes suivent la voix. Le message est court, parce qu’il est dit à voix haute dans une pièce partagée.

    Léa, ton colis Vinted t’attend au Tabac de la Place.

  7. aujourd’hui · 18:18

    Pas de réaction ? Un message écrit.

    Léa est partie avant de répondre. Trente minutes sans réponse, et elle n’est plus à la maison : Nestor lui écrit sur Telegram au lieu de se répéter dans une pièce vide.

    Ton colis est au Tabac de la Place jusqu’au 6 novembre.

  8. aujourd’hui · 18:28

    Elle répond. Le fil tient.

    Sa réponse arrive avec le contexte de la veille : Nestor sait de quoi on parle. Déclenchement, tri, décision, livraison : chaque étape est au journal avec sa raison.

    Merci ! J’irai le chercher en rentrant.

    Pourquoi m’a-t-il parlé ? →

N’importe quel appareil peut être un satellite.

Un satellite s’appaire avec un code, déclare ce qu’il sait faire, transmet l’audio en WebRTC et exécute ce que le cœur demande.

L’appairage tient en un code.

L’appareil affiche six chiffres ; vous les tapez dans l’administration. Il reçoit son propre jeton et seulement les capacités autorisées. Refusé par défaut, révocable à tout moment.

enceinte-salon

Code d’appairage

318604

raspberry-pi-4 · salon

enceinte-salon demande à rejoindre

Tapez le code qu’il affiche.

ApprouverAppairé

Son manifeste

{
  "protocol": "nestor.satellite/1",
  "device": {
    "id": "enceinte-salon",
    "model": "raspberry-pi-4",
    "room": "salon"
  },
  "capabilities": [
    {
      "name": "audio.capture"
    },
    {
      "name": "audio.playback"
    },
    {
      "name": "expression.emotion"
    }
  ]
}

Le cœur demande des intentions, jamais des mouvements.

Le cœur envoie intent.expression avec joy pendant que l’audio correspondant est joué. Un Reachy bouge la tête et les antennes, un écran pourrait dessiner un visage, une simple enceinte l’ignore. Rien ne suppose un corps, une caméra ou un écran.

{"type":"intent.expression","payload":{"expression":"joy","intensity":0.7}}

Écrivez le vôtre dans votre langage.

Chaque SDK gère l’appairage, le jeton, le manifeste, le lien WebRTC et l’audio, et passe la suite de conformité boîte noire du serveur. Ou n’écrivez rien du tout :

import asyncio
from nestor_satellite import AUDIO_CAPTURE, AUDIO_PLAYBACK, EXPRESSION, Body, Device, Manifest, Satellite, TokenStore
from nestor_satellite.devices import Microphone, Speaker


class Led(Body):
    def behavior(self, behavior):
        print("attitude:", behavior)

    def expression(self, expression, intensity):
        print("expression:", expression, intensity)


manifest = Manifest.of(Device("enceinte-salon", "raspberry-pi-4", "salon"), AUDIO_CAPTURE, AUDIO_PLAYBACK, EXPRESSION)
satellite = Satellite(
    "http://nestor.local:7860",
    manifest,
    tokens=TokenStore("~/.config/salon.json"),
    body=Led(),
    source=Microphone(),
    sink=Speaker(),
)
asyncio.run(satellite.run())  # shows a pairing code the first time, then reconnects forever
pip install "nestor-satellite[sounddevice]" && nestor-satellite run --core http://nestor.local:7860 --room salon

Les schémas JSON du protocole

Ce qui parle déjà le protocole

  • Reachy Minidisponible

    La tête et les antennes suivent la conversation, pilotées par nestor-reachy.

  • Enceinte Raspberry Pidisponible

    Un micro, un haut-parleur, peut-être un anneau de LED : le minimum de référence, en Python, TypeScript ou Rust.

  • Onglet de navigateurdisponible

    Une tablette murale ou n’importe quel onglet, avec le SDK TypeScript.

  • ESP32prévu

    Par le profil WebSocket plus léger, prévu.

  • Satellites vocaux Home Assistantprévu

    Par une passerelle Wyoming, sur un réseau local de confiance, prévu.

Les satellites dans l’administration : un en ligne, un qui attend son code.Les satellites dans l’administration : un en ligne, un qui attend son code.
Les satellites dans l’administration : un en ligne, un qui attend son code.

Des comptes, branchés depuis l’administration.

Un catalogue, le consentement chez le fournisseur, un interrupteur par outil. Le mail en natif ; tout serveur MCP sans code.

  1. 1

    Choisir

    Gmail et n’importe quelle boîte IMAP en natif. N’importe quel serveur MCP (Linear, Notion, GitHub, vos propres scripts) sans code.

    • Gmail
    • Toute boîte IMAP
    • Tout serveur MCP
    • Linearpar MCP
    • Notionpar MCP
    • GitHubpar MCP
    • Home Assistantpar MCP
    • Google Agendaplus tard
  2. 2

    Consentir

    OAuth 2.1 avec PKCE, chez le fournisseur. Pour Google, votre propre client OAuth, créé pas à pas comme dans Home Assistant.

  3. 3

    Autoriser

    Outil par outil. Ceux qui écrivent, comme envoyer un mail ou créer un ticket, demandent confirmation par défaut.

    • Chercher des courriels par expéditeur, sujet ou date.lecture
    • Lire un courriel et ses pièces jointes texte.lecture
    • Préparer un brouillon de réponse, sans l’envoyer.lecture
    • Envoyer un courriel au nom de la personne.écriture · demande d’abord

Le coffre

Les jetons sont chiffrés au repos, rafraîchis automatiquement et révoqués chez le fournisseur à la déconnexion. Ils ne passent jamais par le modèle, le journal ni les logs.

Une connexion appartient à une personne

Au salon, pièce partagée, Nestor ne lit pas les mails de Léa à voix haute, sauf si elle l’a demandé ou prévu dans une veille.

Une connexion dans l’administration, avec ses outils et leurs permissions.Une connexion dans l’administration, avec ses outils et leurs permissions.
Une connexion dans l’administration, avec ses outils et leurs permissions.

Home Assistant connaît la maison. Nestor lui demande.

Nestor n’invente aucun signal de présence. Il lit ce que la maison sait déjà, au niveau le plus fin disponible, et décide d’où parler. Les appareils se pilotent par le serveur MCP de Home Assistant lui-même.

Allume le salon.

light.salon → allumé · confirmé par Home Assistant

NiveauCe que fournit Home AssistantCe que Nestor en fait
À la maisonentités person : géolocalisation, routeurSait qui est là. Parle sur le satellite principal du foyer, et écrit si personne ne réagit.
Pièce occupéecapteurs de présence ou de mouvement rattachés à une pièceSait qu’une pièce est occupée, pas par qui. Parle dans cette pièce.
Personne dans une piècesuivi par pièce rattaché à une personne, des balises BLE par exempleSait qui est où. Parle à la bonne personne, dans la bonne pièce.

Une source de présence déclare le niveau qu’elle fournit ; la décision de livraison s’y adapte, sans code.

Vif dans la pièce, patient en coulisse.

L’agent central tient la conversation avec un modèle rapide et quelques outils directs. Tout ce qui est long part chez un exécutant, et la conversation continue.

1,15–1,56 s

de la fin de votre phrase à sa voix

Mesuré sur la chaîne réelle (détection de fin de tour, transcription en continu, modèle central, synthèse en continu) dans la preuve de concept, les 28 et 29 octobre 2026.

Pourquoi le harnais d’exécution reste hors de la conversation

Modèle central, appelé directement0,64 s

Le même modèle derrière un harnais d’exécution3,46 s

Délai médian jusqu’à la première phrase, même modèle, mêmes demandes.

À quoi ressemble la délégation

  1. 1Il accuse réception d’abord. « Je regarde ça » est dit avant l’appel d’outil, pas après.
  2. 2La conversation continue pendant qu’Hermes, Codex ou un autre exécutant travaille.
  3. 3Le résultat est annoncé sans qu’on le redemande, à la bonne personne, là où elle est. Une seule fois, même après un redémarrage.
  4. 4L’annulation est confirmée. Demander d’annuler n’est jamais confondu avec avoir annulé.

Ce qu’une voix vous doit

  • Un « mmh » ne le coupe pas ; « attends », si. Au banc : 0 acquiescement sur 8 l’a interrompu, vraies coupures détectées en 0,30 s médian.
  • Quand un fournisseur tombe ou rame, il le dit à voix haute au lieu de se taire.

Le journal fait foi.

Chaque tour, appel d’outil, tâche, changement de mémoire, prise de parole et décision de politique est un événement d’un journal en ajout seul, dans un seul fichier SQLite. L’administration, les tâches durables et le rejeu en découlent : « pourquoi m’a-t-il parlé ? » a toujours une réponse.

Filtrer le journal par personne et par canal dans l’administration.

À vous, sur votre machine.

Ce qu’il sait, ce qu’il peut faire, quand il peut parler : à vous de le voir et de le changer.

Local d’abord
Un fichier SQLite sur votre serveur contient le journal, la mémoire, les tâches et les réglages. Répliquez-le vers un NAS ou S3 avec Litestream si vous le souhaitez.
Une mémoire lisible
Chaque souvenir est daté et sourcé, consultable, corrigeable et supprimable depuis l’administration.
Des comptes au coffre
Chiffrés, jamais montrés au modèle, révoqués chez le fournisseur à la déconnexion.
Reconnaître n’est pas autoriser
L’identification par la voix ou le visage est facultative, personne par personne. Une voix reconnue ne débloque jamais seule une action sensible.
Une initiative bien élevée
Heures calmes, « pas maintenant », jamais au milieu d’une conversation. Urgent seulement si vous l’avez dit.
Un mail est une donnée, pas un ordre
Ce qui arrive (mails, pages, résultats d’outils) n’est jamais traité comme une instruction.
Le foyer a un propriétaire
Comptes, rôles et permissions par personne, canal et outil. Les satellites sont refusés tant qu’ils ne sont pas approuvés.
Les fournisseurs, vous les choisissez
Modèles, voix et exécutants sont des adaptateurs. Les services cloud sont facultatifs par conception ; une distribution qui les utilise a besoin d’Internet.
La page Système : chaque adaptateur, sa santé et ce qu’il déclare.La page Système : chaque adaptateur, sa santé et ce qu’il déclare.
La page Système : chaque adaptateur, sa santé et ce qu’il déclare.

Bilingue par conception, ouvert par licence.

Le cœur, l’administration et ce site parlent anglais et français grâce à des catalogues Project Fluent ; ajouter une langue, c’est ajouter des fichiers. Tout est sous licence MIT.

En route en quatre commandes.

Pas encore publié : construisez-le depuis le dépôt. Il faut Docker et une machine qui reste allumée.

Projet jeune, construit au grand jour.

Lire le README →

Terminal

  1. 1Récupérer le code.

    git clone https://github.com/nestor-home/nestor && cd nestor
  2. 2Écrire une première configuration, ses secrets et le compte propriétaire. Rien n’est jamais écrasé.

    docker compose run --rm nestor init
  3. 3Ajouter la clé de votre fournisseur de modèle aux secrets qui viennent d’être écrits.

    $EDITOR data/.env
  4. 4Démarrer, puis ouvrir l’administration.

    docker compose up -d

L’administration est sur http://localhost:8080