Modèle / jeu de données
julep-ai/julep avatar
julep-ai/julep

Julep : des agents IA durables qui reprennent après une panne

Aperçu du projet : Julep, des agents IA durables et composables. Des flux qui se bloquent et reprennent, réessayent en toute sécurité et expliquent chaque étape.

6 587 étoiles970 forksPythonApache-2.0

En bref

De quoi s’agit-il ?
Julep construit des agents IA comme des flux de données durables : les exécutions peuvent échouer, reprendre et tout expliquer. Une approche par graphe, un IR figé et une couche Temporal optionnelle.
À qui s’adresse-t-il ?
Adoptez Julep si vous construisez des agents qui doivent survivre à des pannes, se rejouer sans effets de bord et produire une trace exploitable de chaque étape. Ne l'adoptez pas si votre besoin se limite à un script Python jetable sans exigence de durabilité.
Puis-je l’utiliser commercialement ?
Oui. Apache-2.0 est une licence permissive : vous pouvez utiliser, modifier et vendre un logiciel qui en dépend, à condition de conserver les mentions de droit d’auteur et de licence.
Est-il encore maintenu ?
Oui. Les derniers commits datent d’il y a 41 jours.
En quel langage est-il écrit ?
Principalement Python, d’après les statistiques de langage de GitHub.

Ces réponses reposent sur les données GitHub du projet (dernière synchronisation le 15 septembre 2026) et sur notre analyse. Elles ne constituent pas un avis juridique.

ANALYSE OPEN SOURCE APPROFONDIE

Le problème : des boucles d'agents qui ne survivent pas aux pannes

Les agents IA classiques sont souvent écrits comme des boucles ad hoc : un modèle appelle un outil, récupère un résultat, recommence. Si le processus meurt en plein milieu, tout est perdu. Julep répond à ce problème en construisant les agents comme des flux de données durables, composables. Les flux peuvent planter, reprendre, réessayer en toute sécurité, et expliquer chaque étape via une projection dérivée. Le public visé est celui des développeurs qui passent des prototypes à la production : ceux qui ont besoin de garanties sur l'exécution, pas seulement d'un joli notebook. Le README insiste sur le fait que l'agent peut refuser d'appeler un outil que le modèle n'a pas explicitement le droit d'utiliser. C'est une contrainte de sécurité forte, rare dans les frameworks d'agents.

Le mécanisme : @flow, un graphe défini à la construction

La surface d'écriture principale est le décorateur @flow. Au lieu d'exécuter le code au moment de l'appel, @flow enregistre des étapes dans un graphe. Les fonctions marquées @tool ou @pure, les appels think(...), cond(...), switch(...), each(...), reschedule(...) ne font pas le travail à l'exécution : ils ajoutent des nœuds au graphe. L'opérateur | fusionne des enregistrements, et h["key"] extrait un champ. Le résultat est compilé dans un format intermédiaire (IR) figé, indépendant du runtime. Le README donne l'exemple d'un outil lookup_ticket avec effet "read" et idempotent, et d'une fonction pure ticket_prompt qui prépare le contexte. Un Reasoner encapsule le modèle, ici anthropic:claude-haiku. La fonction deploy(...) fige la surface des outils et des raisonneurs. dry_run(...) exécute localement avec des outils en mémoire et des raisonneurs factices déterministes. Ce mécanisme de construction par définition est proche de ce que fait dbt pour les transformations SQL : on décrit un graphe, pas une séquence d'appels.

Installation et premier lancement : la commande pip

L'installation se fait avec pip install --pre julep. La version 3 est actuellement un candidat de sortie, d'où le drapeau --pre. Le README promet un démarrage en 10 minutes, sans clé API. On écrit un script Python normal avec les décorateurs, puis on le lance. Le CLI julep offre ensuite des commandes pour un module entier d'agents. julep ls liste les agents, julep show triage affiche les détails d'un agent, julep graph génère le graphe inter-agents en DOT, julep run triage --input '"TICKET-42"' exécute localement en streamant l'arbre de trace. julep lint +triage valide un agent et ses dépendances. julep test triage lance pytest pour les agents sélectionnés. julep trace <run-id> affiche une trace mise en cache. Les sélecteurs se composent : tag:support, state:modified, +agent, agent+, @agent, intersections avec des virgules, exclusions avec --exclude. C'est une grammaire de sélection unique pour toutes les commandes. Pour la production, le README recommande de déclarer un objet Application explicite plutôt que de laisser la découverte automatique.

La couche Temporal : durabilité et chiffrement

La durabilité repose sur une couche optionnelle Temporal. Le noyau pur reste sans dépendance, mais la couche Temporal permet les reprises après crash et les retries. En production, on configure un environnement via [tool.julep.env.staging] dans un fichier TOML. temporal_address pointe vers le service Temporal, release_store vers un bucket S3, worker_image vers une image Docker. payload_encryption_secret est obligatoire pour les releases applicatives : il référence un Secret Kubernetes existant avec des entrées keyring et active-key-id. Les variables d'environnement worker peuvent être ordinaires ou secrètes. Les variables secrètes ne sont pas injectées dans le worker : worker_secret_environment contient des références à des Secrets Kubernetes, pas les valeurs. Celles-ci n'existent qu'à l'exécution dans le worker. Le README précise que les credentials par run sont liés à des références secret://name dans les en-têtes MCP, et qu'elles ne voyagent que dans des payloads Temporal chiffrés. Elles sont exclues des données de run stockées et des projections. C'est une séparation nette entre ce qui est traçable et ce qui reste confidentiel.

Sécurité MCP : préflight et dérive de surface

Julep intègre le protocole MCP (Model Context Protocol). mcp_tool(server, tool) crée une référence à un outil MCP dans un @flow. Les schémas et le contrat de comportement proviennent d'un instantané MCP figé. Avant les effets utilisateur, le worker effectue une vérification préflight de la surface d'outils transitivement atteignable. Les nouvelles versions comparent par défaut les empreintes exactes (pin), avec des échappatoires explicites names et off. Si un outil est retiré en cours de run, ou si le schéma est rejeté après validation, l'échec est terminal et qualifié de dérive de surface typée. C'est une protection contre les changements inattendus côté serveur MCP. Mais cela signifie aussi qu'un serveur MCP qui change son schéma sans prévenir cassera le flux. Le README mentionne un exemple avec un faux mcp_call local pour tester les lectures et écritures MCP sans serveur réel.

Limites et cas où Julep n'est pas le bon outil

La première limite est le statut de release candidate. Julep 3 n'est pas encore en version finale, et l'installation exige --pre. Cela implique une API potentiellement instable. La deuxième limite est la complexité de la mise en production : il faut un plan de contrôle auto-hébergé, un cluster Kubernetes avec Temporal, un coffre-fort d'opérateur, et la gestion des Secrets. Pour un petit projet ou un prototype, c'est disproportionné. La troisième limite est la courbe d'apprentissage du paradigme @flow : écrire des flux par construction, avec des handles de données, n'est pas naturel pour qui vient de scripts impératifs. Enfin, le README ne documente pas les performances. Aucun benchmark n'est fourni. On ne sait pas combien de nœuds un graphe peut supporter avant que la compilation ou l'exécution ne devienne lente. Si votre besoin est un agent simple qui appelle une API et renvoie une réponse, Julep est trop lourd.

Alternatives : LangGraph et les boucles manuelles

L'alternative la plus proche est LangGraph, qui modélise aussi les agents comme des graphes avec des états et des transitions. La différence tient à l'approche : LangGraph se construit autour d'un graphe d'états explicite, avec des nœuds et des arêtes que vous définissez à la main. Julep, lui, déduit le graphe à partir de la définition @flow : vous écrivez du code Python qui ressemble à un script, et le framework compile les étapes. C'est une différence de surface d'écriture. LangGraph est plus flexible pour des nœuds personnalisés, mais il ne fournit pas la durabilité intégrée de Temporal ni le mécanisme de dérive de surface. Une autre alternative est d'écrire une boucle manuelle avec des retries et une persistance dans une base de données. C'est plus simple à comprendre, mais vous perdez la reprise après crash et la traçabilité automatique. Le choix dépend de votre besoin de garanties opérationnelles.

Coûts de maintenance et licence

Julep est sous licence Apache-2.0, ce qui permet une utilisation commerciale sans restriction majeure. La maintenance dépend de votre capacité à suivre les évolutions de la version 3. Le README indique que de nouvelles releases par défaut changent le mode de comparaison des outils MCP (passage à pin). Il faut donc prévoir une veille sur les changements de comportement. Le CLI propose julep plan --env staging pour détecter les dérives d'artefacts, de schémas MCP, Helm/KEDA et runtime. C'est un outil de maintenance concret. Enfin, la couche Temporal est optionnelle, mais si vous l'utilisez, vous devez maintenir une infrastructure Temporal en plus de votre cluster Kubernetes. Le coût d'exploitation n'est pas négligeable. Pour un usage simple, dry_run permet de tester sans déployer, ce qui réduit le coût initial.

Conclusion éditoriale

Adoptez Julep si vous construisez des agents qui doivent survivre à des pannes, se rejouer sans effets de bord et produire une trace exploitable de chaque étape. Ne l'adoptez pas si votre besoin se limite à un script Python jetable sans exigence de durabilité. Avant de vous engager, vérifiez que la version 3.0.0 est finalisée (l'installation exige encore --pre), que votre modèle de raisonnement est compatible avec l'encapsulation dans Reasoner, et que votre infrastructure peut héberger le plan de contrôle auto-hébergé, notamment le coffre-fort d'opérateur et le chiffrement des payloads Temporal. Testez d'abord un flux simple avec dry_run pour valider la syntaxe @flow avant de déployer.

Sources officielles

  1. Official documentation
  2. Official README
  3. Project repository
Notes de la communauté

Notes de la communauté