Aller au contenu principal

Pi Harness : architecture et frontières des extensions

Deux jugements tirés de Pi valent aussi pour d’autres outils. Le premier : ranger chaque personnalisation dans sa couche. Les règles stables vont dans le contexte du projet, une amorce réutilisable devient un modèle de prompt, une méthode chargée à la demande devient un skill, et l’on n’écrit une extension que si l’on a vraiment besoin d’un nouvel outil, d’un hook d’événement ou d’une interface. Le second : une extension exécute du code arbitraire avec les droits du compte qui l’a lancée, si bien qu’un package est une unité de distribution, pas une frontière de sécurité. Il en va de même des hooks de Claude Code, qui s’exécutent hors de sa sandbox avec tous vos droits (documentation de la sandbox).

Pi garde un noyau de harness très petit et laisse l’utilisateur ajouter tout le reste par couches. Le noyau est donc plus facile à comprendre et à modifier, mais politique de sécurité et qualité du workflow n’apparaissent pas automatiquement ; la complexité n’a pas disparu, elle est reportée sur la personne qui construit le workflow. Tout ce qui suit a été vérifié sur Pi 1.4.0 (publiée le 21 octobre 2026), le 2026-10-29.

Pi : un harness minimal programmable​

Pi se présente comme un harness minimal de code en terminal. Son noyau conserve les appels de modèles, la boucle d’agent, l’exécution des outils, les sessions arborescentes et l’interface terminal, puis confie les comportements propres à chaque workflow à des ressources composables. D’après la documentation CLI, seuls quatre outils sont activés par défaut, read, bash, edit et write, et le réglage defaultTools peut changer cette liste. Des noms simples passés à --tools remplacent toute la sélection ; depuis la 1.1.0, on peut aussi écrire +name / -name pour ajouter ou retirer un outil par rapport aux quatre par défaut, par exemple pi --tools +codemode,-write. grep, find et ls sont aussi intégrés, mais n’apparaissent que si on les sélectionne explicitement. Depuis la 1.3.0, une session reprise garde les outils qu’elle avait activés.

Outre le TUI interactif, Pi offre la sortie ponctuelle -p, un flux d’événements JSON, un RPC sur stdin/stdout et un SDK pour intégrer l’agent à une application Node.js. Les fournisseurs de modèles peuvent être remplacés. Les sessions sont des arbres JSONL : /tree, /fork, /clone et /compact couvrent l’exploration dans un même fichier, les sessions séparées et la compression du contexte.

Rôle de chaque couche de personnalisation​

CouchePoint d’entrée typiqueBon emplacement pourÀ ne pas confondre avec
Contexte du projetAGENTS.md, CLAUDE.md, .pi/SYSTEM.mdrègles stables, périmètres de chemins, commandes d’acceptationun plugin ou une sandbox
Modèle de prompt.pi/prompts/review.md → /reviewune amorce répétable et paramétréeun workflow exécuté automatiquement
Skill (Compétences d’agent).agents/skills/*/SKILL.md → /skill:nameprocédures, scripts et références chargés à la demandeune frontière de permission ou un processus séparé
Extension.pi/extensions/*.tsoutils, commandes, politiques d’événements, UI, fournisseurs et comportement de sessionun « petit plugin » naturellement sûr
Package Pipi install ..., pi configdistribution d’extensions, skills, prompts et thèmes par npm, Git ou chemin localisolation ou signature de confiance
SDK / RPCcreateAgentSession(), pi --mode rpcintégration, tests ou communication interprocessus entre langagesune couche obligatoire pour un dépôt ordinaire

Les ressources globales résident généralement sous ~/.pi/agent/, celles du projet sous .pi/ ou .agents/skills/. Un modèle de prompt ne fait que développer une commande comme /review en un texte déjà rédigé. Un skill n’expose que son nom et sa description tant qu’on n’en a pas besoin, puis charge son contenu à la demande. Une extension modifie directement le harness. Préférer un skill lorsqu’il manque une méthode, un prompt lorsqu’il manque une entrée réutilisable, et une extension seulement lorsqu’un nouvel outil, hook d’événement ou élément d’UI est réellement nécessaire.

Comment tourne la boucle d’agent de Pi​

À la lecture d’agent-loop.ts et d’AgentSession, une exécution compte trois couches : la session prépare la requête, la boucle de bas niveau coordonne modèle et outils, puis la session gère persistance, compaction et reprises.

1. Beaucoup de choses précèdent l’appel au modèle​

L’entrée utilisateur ne va pas directement au modèle. Dans le cycle de vie décrit par la documentation des extensions, les commandes d’extension passent d’abord, l’événement input peut intercepter ou réécrire l’entrée, et ce n’est qu’ensuite que les Skills et modèles de prompt appelés explicitement sont développés.

Si l’Agent travaille déjà, le nouveau message ne s’insère pas au milieu d’un appel d’outil : il entre dans l’une de deux files. Un message Steering est inséré avant le prochain appel au modèle, pour corriger la direction en cours de route ; un message Follow-up attend que la tâche courante soit sur le point de se terminer, puis relance le travail de l’Agent.

La session vérifie ensuite le modèle et l’authentification, puis décide si l’ancien contexte doit être compacté. Un événement before_agent_start peut aussi ajouter des messages personnalisés ou modifier le prompt système de cette exécution. Ce n’est qu’après ces étapes que le message utilisateur rejoint la boucle de bas niveau.

2. L’implémentation de bas niveau contient deux boucles​

La boucle interne enchaîne les appels au modèle. Avant l’appel suivant, Pi peut actualiser le prompt système, les outils, le modèle et le niveau de raisonnement, puis injecter les messages Steering à une frontière de tour sûre. Le contexte est ensuite converti au format attendu par le fournisseur actif, avant la génération en streaming d’un message de l’assistant.

Si cette réponse contient des appels d’outils, Pi les exécute, transforme chaque résultat en message toolResult, puis rappelle le modèle. La boucle interne ne s’arrête que lorsqu’il ne reste ni appel d’outil ni message Steering. La boucle externe traite les messages Follow-up : elle ne les récupère qu’une fois la chaîne d’outils et la file Steering épuisées, puis relance la boucle interne.

Dans la référence des raccourcis de la 1.4.0, un message envoyé avec Enter pendant l’exécution va dans Steering et Alt+Enter le met en Follow-up (Ctrl+Q sous Windows et WSL) ; Alt+Up remet les messages en attente dans l’éditeur (Alt+Q sous Windows et WSL), et Escape interrompt l’exécution.

3. Un appel d’outil passe d’abord validation et hooks​

Pi vérifie d’abord que l’outil existe, puis prépare et valide ses arguments ; un appel à un outil inconnu ou aux arguments invalides ne s’exécute jamais. L’événement tool_call d’une extension peut bloquer l’appel ou en modifier l’entrée, et l’événement tool_result, après exécution, peut réécrire le résultat. Les appels peuvent être parallèles ; un outil marqué Sequential, ou un réglage global séquentiel, impose une exécution en série. Si la sortie du modèle est tronquée par sa limite de longueur, tous les appels d’outils de cette réponse sont marqués en échec et le modèle doit les soumettre à nouveau.

4. Après agent_end, l’exécution peut continuer​

La boucle de bas niveau émet agent_end lorsqu’il ne reste ni appel d’outil ni message en file, ou lorsqu’une erreur ou une annulation y met fin. Ce n’est pas encore l’inactivité : une reprise, une reprise après compaction consécutive à un dépassement, ou un message en file peuvent relancer un tour, et une extension peut demander une dernière continuation dans agent_before_settle. Seul agent_settled signifie que Pi ne poursuivra plus de lui-même. Tests, contrôles de schéma, assertions navigateur et validation humaine restent hors de la boucle et viennent ensuite.

5. La compaction et les reprises appartiennent à la session​

D’après la documentation de la compaction, Pi vérifie le contexte à trois moments : avant un nouveau Prompt, après l’ajout des résultats d’outils et avant la réponse suivante du modèle, et après la fin d’une exécution de bas niveau. Lorsque le seuil est franchi, les anciens messages deviennent un résumé tandis que les plus récents restent disponibles ; si le fournisseur signale un dépassement de contexte, Pi compacte et reprend une fois. Depuis la 1.4.0, les résumés n’ont plus de plafond de sortie fixe et utilisent la limite de sortie du modèle lui-même.

Les messages sont aussi écrits dans une session JSONL arborescente. D’après le format de session, cet arbre conserve messages, résultats d’outils et enregistrements de compaction, sans aucun instantané du système de fichiers : changer de branche de session n’annule donc pas les fichiers déjà écrits sur le disque.

Extensions : la couche de plugins de Pi​

Une extension est un module TypeScript chargé directement par Pi. Elle peut :

  • enregistrer des outils appelables par le modèle et des commandes slash utilisateur ;
  • intercepter tours du modèle, appels et résultats d’outils, changements de modèle et cycle de vie des sessions ;
  • bloquer ou réécrire les appels dangereux et ajouter chemins protégés ou UI d’approbation ;
  • personnaliser compaction, état de session, composants du terminal et rendu ;
  • enregistrer des fournisseurs, ou implémenter MCP, sous-agents, mode plan et intégration à un bac à sable.

Sous-agents, mode plan et intégration sandbox viennent toujours d’exemples ou de packages tiers et ne font pas partie des valeurs par défaut du noyau ; MCP est une extension intégrée depuis la 0.99.0 (voir la section suivante). Un petit noyau autorise plusieurs conceptions, tout en rendant l’installateur responsable de leurs politiques, de leur maintenance et de leur récupération après erreur.

Les extensions découvertes automatiquement vont dans ~/.pi/agent/extensions/ ou .pi/extensions/ d’un projet approuvé ; après modification, exécuter /reload. Pour un essai temporaire sans installation, utiliser pi -e ./extension.ts. Une extension exécute du code arbitraire avec les droits de l’utilisateur courant, et un skill peut demander au modèle d’exécuter des scripts inclus. Lire le code source et les dépendances avant installation, fixer les versions et n’activer que les ressources nécessaires.

De la 0.99 à la 1.4 : MCP et codemode deviennent des extensions intégrées​

Le changement le plus important date de la 0.99.0, le 29 septembre : depuis cette version, codemode, la recherche d’outils et MCP sont des extensions intégrées, toutes désactivables dans pi config. Codemode permet au modèle d’écrire du JavaScript qui appelle les outils de Pi en parallèle dans un bac à sable QuickJS ; seule la sortie du script parvient au modèle. La recherche d’outils retrouve, au besoin, des outils encore inconnus du modèle pour que l’appel suivant puisse s’en servir. Chacune correspond à un outil, codemode et tool_search, tous deux désactivés par défaut ; l’extension MCP les active lorsqu’un serveur MCP connecté en a besoin. La même version a ajouté des modèles de classification ; voir Jev et Laya.

Les serveurs Model Context Protocol (MCP) fonctionnent en stdio ou en Streamable HTTP, prennent en charge OAuth, se configurent via mcp.json et se gèrent avec /mcp et pi mcp add|remove|list|login|logout. Les versions suivantes ont ajouté :

  • 1.0.0 : vérification de la valeur iss des réponses d’autorisation et stockage des identifiants par serveur ; l’interface plein écran devient celle par défaut.
  • 1.0.1 : le .pi/mcp.json d’un projet peut activer, désactiver ou ajuster un serveur de niveau utilisateur pour ce projet ; enregistrement par Client ID Metadata Document.
  • 1.0.4 : --no-mcp désactive MCP pour une exécution ; --tools accepte des motifs comme mcp__<serveur>__*.

Usage quotidien​

Le premier jour, un projet ordinaire n’a besoin que d’AGENTS.md pour les règles et les commandes d’acceptation ; .pi/prompts/, .agents/skills/ et .pi/extensions/ viendront quand quelque chose se répétera vraiment. Commandes courantes :

pi --name "parser repair" # session interactive
pi -c # continuer la dernière session
pi -r # ouvrir la liste des sessions
pi --no-session -p "Summarize this repository" # tâche ponctuelle éphémère
pi --no-session --tools read,grep,find,ls -p "Review the change" # outils en lecture seule
pi --no-extensions -e ./.pi/extensions/policy.ts # ne charger que l’extension testée

Dans une session, /model change de modèle, /tree, /fork et /clone gèrent les branches, /compact compacte à la main et /reload recharge extensions, skills et fichiers de contexte.

Sécurité : deux réglages propres à Pi​

Pi ne demande pas d’approbation avant les appels d’outils et n’a pas de sandbox intégrée ; son socle et la comparaison avec les autres outils se trouvent dans Sécurité des agents. Seuls deux points sont propres à Pi :

  1. La confiance accordée au projet décide seulement si Pi charge les réglages .pi, la configuration MCP et les extensions du projet ; elle ne limite pas ce que les outils peuvent atteindre. Les modes print, JSON et RPC ne peuvent pas afficher la demande de confiance : une exécution automatisée doit donc passer --approve ou --no-approve explicitement (documentation de sécurité).
  2. Utiliser --tools read,grep,find,ls pour une revue, et n’élargir les outils que si l’écriture devient nécessaire.
Explorer les liensOuvrir le réseau