NVIDIA a publie NOOA le 7 aout, un cadre Python sous licence Apache 2.0 dont tout le principe tient en une phrase : un agent IA doit etre une classe ordinaire. Les methodes sont les actions disponibles, les champs portent l'etat, les docstrings deviennent les prompts et les annotations de types servent de contrats. Une methode dont le corps se resume a trois points est completee a l'execution par un modele, une methode avec du vrai code reste du Python deterministe. L'interet n'est pas la nouveaute. C'est qu'un agent ecrit ainsi se relit, se teste et se refactorise avec l'outillage que vous possedez deja.
The short answer
NOOA est le cadre Object-Oriented Agents de NVIDIA, publie le 7 aout sous licence Apache 2.0. Un agent y est une seule classe Python. Les champs portent son etat, les methodes sont les actions disponibles, les docstrings servent de prompts et les annotations de types deviennent des contrats verifies sur ce qui revient. Une methode dont le corps se reduit a trois points est completee a l'execution par une boucle pilotee par le modele, une methode avec du vrai code reste deterministe. Les appels de modele et les executions de code sont traces par defaut. Le cadre est agnostique via LiteLLM, donc rien n'exige de silicium ni de modeles NVIDIA.
Demandez a quelqu'un qui maintient un agent depuis six mois ce qui a derape, la reponse porte rarement sur le modele. Elle porte sur le fait que la chose est devenue impossible a relire. Le prompt vit dans un fichier de gabarit, les definitions d'outils dans un schema JSON, le flot de controle dans un constructeur de graphe, et la seule facon de savoir ce qu'un changement produit consiste a l'executer et a regarder. NOOA est l'argument de NVIDIA selon lequel ce probleme est auto-infflige, et que le remede consiste a cesser d'inventer un univers parallele d'abstractions.
Une classe, et les regles qui en decoulent
Le cadre ramene tout a une definition de classe Python. Voici la forme, tiree de l'exemple du projet :
from nooa import Agent
class SupportAgent(Agent):
"""You are a support agent."""
order_db: OrderDB
def is_refund_eligible(self, order: Order) -> bool:
return order.delivered and order.days_since_delivery <= 30
async def triage(self, message: str, order: Order) -> Ticket:
"""Create a typed support ticket."""
...
Quatre conventions font tout le travail. La docstring de classe est le prompt systeme. Les champs annotes comme order_db constituent l'etat de l'agent, injecte et disponible pour tout ce que l'agent execute. is_refund_eligible a un vrai corps, donc c'est du Python ordinaire qui s'execute de la meme facon a chaque fois et se teste sans aucun modele dans la boucle. triage a un corps de trois points, signal que le modele l'implemente, guide par la signature, la docstring et le type de retour Ticket.
Ce dernier point merite qu'on s'y arrete. L'annotation de retour n'est pas de la documentation, c'est le contrat que la sortie doit satisfaire. La sortie structuree est le point penible du travail sur les agents depuis deux ans, generalement resolu par un schema defini loin de la fonction qui en a besoin. Le mettre dans la signature garantit que le contrat et le site d'appel ne peuvent pas diverger, puisque c'est la meme ligne.
Le code genere s'execute dans un contexte de type REPL qui accede a l'objet, donc le modele peut appeler is_refund_eligible plutot que de raisonner lui-meme sur les delais de remboursement. Chaque appel de modele et chaque execution sont traces par defaut.
Pourquoi le choix ennuyeux est le choix interessant
L'argument pratique, c'est qu'un agent exprime comme une classe herite de tout ce que Python possede deja. pytest exerce directement les methodes deterministes. Un verificateur de types voit les contrats. git blame pointe vers une docstring quand le comportement change, ce qui est la premiere fois dans ce domaine qu'une modification de prompt apparait en revue comme un diff normal. Les outils de refactorisation fonctionnent parce qu'il n'y a rien d'autre a refactoriser que du code.
Comparez a l'alternative en forme de graphe, ou l'agent est assemble a partir de noeuds et d'aretes et ou les prompts vivent dans des gabarits. Les graphes se justifient quand le flot de controle est reellement la partie difficile et que vous voulez le voir depliee. Mais une bonne part des agents en production ne sont pas cela. Ce sont un prompt, trois outils et une reprise sur erreur, emballes dans assez de cadre pour transformer un probleme de deux cents lignes en une affaire de quatre fichiers.
Il y a la un vrai compromis et autant le nommer. L'heritage de classes exprime maladroitement des workflows ramifies en plusieurs etapes, et si votre agent est reellement une machine a etats, le dessiner comme telle n'est pas une erreur. NOOA ne resout pas ce cas. Ce qu'il resout, c'est le cas bien plus courant ou le cadre pese plus lourd que l'agent.
Ce que nous en ferions
L'evaluation coute peu, ce qui reste le meilleur argument pour y consacrer une heure :
uv init my-agent-project && cd my-agent-project && uv add nooa
Pointez-le vers le modele que vous payez deja via LiteLLM, puis portez un petit agent que vous maintenez actuellement et regardez la tete du resultat. Le test n'est pas de savoir si cela fonctionne, cela fonctionnera. C'est de savoir si le fichier obtenu est quelque chose qu'un collegue peut lire en cinq minutes en predisant correctement le comportement. C'est la propriete que ce cadre vend, et la seule qui merite d'etre mesuree.
Deux precautions avant de reecrire une flotte. Le projet est neuf, publie la meme semaine que son article, donc considerez la surface d'API comme instable. Et le modele d'execution de code merite la revue que vous accorderiez a n'importe quel hote de greffons : gardez petite la surface atteignable de l'objet, placez les operations irreversibles derriere des methodes deterministes a corps reel, et lisez les traces. Le tracage actif par defaut est reellement le bon choix ici, parce que le mode de defaillance des cadres d'agents n'est generalement pas un plantage. C'est que personne ne sait expliquer ce qui s'est passe.
Sources et pour aller plus loin
- NVIDIA-NeMo/labs-OO-Agents, le depot des sources sous Apache 2.0 sur GitHub
- Nvidia's NOOA makes an agent one Python class, The New Stack
- NVIDIA AI releases NOOA, an object-oriented Python framework, MarkTechPost, 7 aout 2026
- NVIDIA-labs OO Agents: Native Python Object-Oriented Agents, arXiv 2607.20709
- Six agent harness capabilities for higher model performance, blog technique NVIDIA
Questions fréquentes
Que se passe-t-il exactement quand le corps d'une methode se reduit a trois points ?
Ces points de suspension sont le marqueur par lequel NOOA declare que la methode est implementee par le modele et non par vous. A l'execution, le cadre lit la signature, les annotations de types et la docstring, transmet le tout a une boucle d'agent, et cette boucle produit du Python execute dans un contexte de type REPL qui accede a l'etat de l'objet et a ses autres methodes. La valeur de retour est verifiee contre le type annote, et c'est la que se joue l'essentiel : une methode declaree comme renvoyant un Ticket doit produire quelque chose qui a la forme d'un Ticket, pas un paragraphe de prose que vous decoupez ensuite a coups d'expressions regulieres. Les methodes qui ont un corps normal ne sont pas touchees et s'executent comme du Python ordinaire. Concretement, une meme classe porte donc la logique deterministe que vous refusez de confier a un modele, par exemple les regles d'eligibilite a un remboursement, et les parties floues que vous voulez lui laisser, par exemple la lecture d'un message client. La frontiere entre les deux est un corps de methode, ce qui est a peu pres la frontiere la plus lisible que l'on puisse demander.
Faut-il du materiel ou des modeles NVIDIA pour utiliser NOOA ?
Non, et il vaut la peine de le dire clairement parce que le nom suggere l'inverse. NOOA est agnostique et passe par LiteLLM, si bien que les backends documentes incluent Claude d'Anthropic, GPT d'OpenAI, Ollama pour les modeles locaux et vLLM pour l'auto-hebergement. Rien dans le modele de programmation ne suppose un fournisseur de GPU. L'installation se fait avec `pip install nooa` ou `uv add nooa`, et les sources sont sous Apache 2.0 sur github.com/NVIDIA-NeMo/labs-OO-Agents, avec des extras optionnels pour la ligne de commande, la memoire et le harnais de benchmark. NVIDIA verse par ailleurs le projet a l'Open Secure AI Alliance, le groupement industriel qu'il a reuni autour d'outils ouverts partages, ce qui signale au moins que le cadre n'a pas vocation a rester une affaire interne. Savoir s'il restera reellement neutre se lira dans l'historique des commits dans un an, pas dans le fichier de licence aujourd'hui.
Qu'est-ce que cela change par rapport aux cadres d'agents a base de graphes ?
La difference tient a l'endroit ou vit la structure. Dans un cadre a base de graphes, l'agent est une donnee : des noeuds, des aretes, un objet d'etat qui circule, plus des gabarits de prompts et des schemas d'outils ranges ailleurs. C'est reellement utile quand le flot de controle est la partie interessante et que vous voulez le visualiser. Le cout, c'est que votre agent cesse d'etre du code, donc vos reflexes cessent de fonctionner. On ne pose pas de point d'arret sur une arete de YAML, un renommage devient un rechercher-remplacer sur trois formats de fichiers, et la revue montre un changement de gabarit sans montrer ce qu'il produit. Le pari de NOOA, c'est que la plupart des agents ne sont pas assez compliques pour justifier cela, et qu'une classe redonne acces a toute la chaine Python : pytest, mypy, git blame, un IDE qui saute a la definition. Le contre-argument honnete, c'est qu'une hierarchie de classes convient moins bien qu'un graphe quand vous avez vraiment des workflows ramifies en plusieurs etapes, et rien ici ne fait disparaitre ce cas.
Quelle confiance accorder aux chiffres de benchmark publies par NVIDIA ?
Prenez-les comme une preuve de competence, pas comme un classement. NVIDIA annonce 82,2 pour cent sur SWE-bench Verified et un RHAE moyen de 85,1 pour cent sur ARC-AGI-3, l'article associe sur arXiv sous la reference 2607.20709 couvrant aussi Terminal-Bench 2.0. Ce sont des resultats respectables pour un harnais. Le piege de tout resultat de benchmark d'agents, c'est que le harnais et le modele sous-jacent sont indissociables : un chiffre vous dit ce qu'un cadre a obtenu avec un modele a un instant donne, et changer l'un des deux le deplace. SWE-bench Verified en particulier traine une longue histoire de resultats qui ne se transferent pas aux depots inconnus, parce que les taches proviennent de projets open source populaires que les modeles ont deja vus. Si vous evaluez NOOA, le chiffre qui doit trancher est celui que vous mesurez sur vos propres taches avec votre propre modele, et le fait que le cadre soit du Python ordinaire rend cette mesure inhabituellement rapide a mettre en place.
Quel est le risque a laisser un modele generer du code qui touche a l'etat de l'objet ?
C'est le risque de toute boucle d'execution de code, rendu plus visible plutot que plus grave. NOOA execute le Python genere par le modele dans un contexte de type REPL qui atteint les champs et les methodes de l'agent, ce qui fait precisement sa force : le modele appelle vos fonctions deterministes au lieu de les reimplementer mal. Cela veut aussi dire que la portee d'une instruction generee correspond a tout ce que cet objet peut atteindre, donc une classe qui detient une connexion de base de donnees vivante est une classe dont la boucle peut se servir. La reponse du cadre, c'est le tracage integre : chaque appel de modele et chaque execution de code sont journalises, donc la trace de ce qui s'est passe existe par defaut au lieu d'etre une chose que l'on pense a ajouter. Notre lecture, c'est que cela se relit comme un systeme de greffons : gardez la surface de l'objet petite, placez les operations irreversibles derriere des methodes deterministes a corps reel, et lisez les traces avant d'elargir quoi que ce soit.