Présentation
Pi Durable est le nouveau cadre d’exécution publié par Earendil pour les agents codés avec Pi 1.0. Il ne remplace pas l’agent de codage, mais fournit une infrastructure – appelée harness – capable de gérer plusieurs conversations simultanées avec des modèles de langage de grande taille. Le harnais regroupe le stockage persistant, la gestion des tâches et l’environnement d’exécution des outils, le tout dans un runtime JavaScript standard.
Architecture et stockage
Le cœur du système repose sur une interface de stockage minimaliste qui peut être implémentée sur n’importe quel backend. Pi Durable embarque trois implémentations prêtes à l’emploi : mémoire volatile, SQLite et JSONL. Les deux dernières utilisent uniquement du code JavaScript pur, sans API Node, ce qui permet de les exécuter sur Bun ou dans un Cloudflare Durable Object avec un simple adaptateur. Un processus possède le stockage à un instant donné, tandis que d’autres clients se connectent en tant que lecteurs ou soumissionnaires. Sur SQLite, seules les transcriptions actives, les tâches en cours et les soumissions en attente restent en mémoire ; le reste reste sur disque jusqu’à ce qu’il soit requis. La taille des transcriptions est naturellement limitée par la fenêtre de contexte du modèle, car le système compresse les messages anciens avant qu’ils ne dépassent ce seuil, garantissant ainsi que même des conversations contenant des dizaines de milliers d’échanges tiennent en RAM.
Résilience aux pannes
Chaque étape d’une exécution est modélisée comme une task qui écrit un point de contrôle (checkpoint) dans le stockage avant de passer à la suivante. En cas d’arrêt brutal du processus – mise en veille du portable, redéploiement d’un conteneur ou dépassement de mémoire – un nouveau processus rouvre le même stockage, identifie les tâches incomplètes et reprend à partir du dernier checkpoint. Les requêtes de modèle interrompues sont renvoyées, les réponses partielles sont marquées comme aborted, et les appels d’outil sûrs sont relancés. Un identifiant de requête (requestId) assure l’exactitude « exactement‑une‑fois », de sorte que les clients qui retentent après un crash récupèrent la même soumission sans duplication.
Extensibilité et limites
Le harnais expose deux interfaces simples : le stockage et l’environnement d’exécution. L’environnement d’exécution Node fourni donne aux outils l’accès aux fichiers locaux et à un shell, mais l’interface peut être remplacée par un adaptateur distant, permettant à un processus d’exécuter ses outils sur une machine différente. Cette modularité ouvre la voie à des déploiements hybrides où le harnais réside sur un serveur léger tandis que les outils s’exécutent dans un conteneur isolé ou un service cloud. Cependant, le code source complet compte environ 15 000 lignes, dont 3 000 lignes uniquement pour les backends de stockage ; les agents doivent donc charger une partie importante du code même s’ils n’utilisent qu’une fraction des fonctionnalités. De plus, Pi Durable ne fournit pas de sous‑agents natifs ; leur implémentation nécessite quelques lignes supplémentaires, comme le montre l’exemple de l’outil de triage.
import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
import { createModels } from "@earendil-works/pi-ai/models";
import { openaiProvider } from "@earendil-works/pi-ai/providers/openai";
import { createRegistry, Harness } from "@earendil-works/pi-durable";
import { NodeExecutionEnv } from "@earendil-works/pi-durable/env/node";
import { openNodeSqliteStorage } from "@earendil-works/pi-durable/storage/sqlite/node";
import { CodingTools } from "@earendil-works/pi-durable/tools";
const context = BACKGROUND_CONTEXT;
const models = createModels(); models.setProvider(openaiProvider());
const registry = createRegistry(); registry.install(CodingTools);
const env = ({ cwd }) => new NodeExecutionEnv({ cwd: cwd ?? process.cwd() });
const harness = await Harness.open(
await openNodeSqliteStorage("./agent.sqlite"),
{ models, registry, env },
context,
);
const root = await harness.root(context, {
agent: {
model: { provider: "openai", modelId: "gpt-6.1-sol" },
cwd: "/work/repo",
},
});