Open-source project
NVIDIA-NeMo/labs-OO-Agents avatar
NVIDIA-NeMo/labs-OO-Agents

NVIDIA Labs OO Agents (NOOA): agents as Python classes, with an LLM in the method body

NVIDIA Object Oriented Agents: the Pythonic way to build AI Agents.

2,058 stars285 forksPythonNOASSERTION

At a glance

What is it?
NOOA puts agent state, prompts, tools and typed contracts inside one Python class, and lets an LLM fill in methods whose bodies are `...`. It is research software that executes generated code, so the sandbox question comes before the architecture question.
Who is it for?
Adopt NOOA if your agent logic already looks like a Python object with typed fields and methods, and if you can run it inside a sandbox such as NVIDIA OpenShell before anything generated touches a real filesystem. Do not adopt it if you need a stable API surface, a published licence file you can read without ambiguity, or a framework whose generated code you are willing to execute unsandboxed.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The abstraction NOOA is arguing against

Most agent frameworks keep prompts, tool schemas, callbacks and workflow graphs as separate objects that you wire together at runtime. NOOA's README states the project exists because of that split, and proposes instead that an agent be a single Python class. Fields are state, methods are capabilities, docstrings are prompts, and type annotations are contracts. The README's own example is a `SupportAgent` with an `order_db: OrderDB` field, a plain `is_refund_eligible` method that returns a bool, and an `async def triage(self, message: str, order: Order) -> Ticket` whose body is `...`. That last detail is the whole design in one character. A method with a real body is deterministic Python the runtime never touches. A method with `...` becomes an agentic loop the runtime hands to a model. The audience is Python developers who already have domain objects and want the agent to sit inside them rather than beside them, and who find tool-schema JSON a second, worse copy of a function signature they already wrote.

How the `...` body becomes an LLM call

The mechanism visible in the README is code-as-action. The model acts by writing Python in a Jupyter-style REPL with access to `self`, imports and helpers. Because the REPL has `self`, the methods and type annotations you already wrote supply the callable interfaces, which the README frames as reducing the need for separate tool-schema definitions. Arguments can be live objects passed by reference, so a method can receive an `Order` instance rather than a serialised copy. Generation commits one result; the README says deterministic generators are supported but generated streams need a separate stream contract and are rejected clearly, which is a deliberate boundary rather than an oversight. Typed I/O comes with auto-retry. There is also a model-callable context and event API. The README points to a 10-minute tour that walks from one thinking method through tools, typed contracts, deterministic orchestration and object composition, and to an arXiv paper for design principles and evaluation results. I have not run any of this, so treat the loop's behaviour under retry and live-object mutation as something to read in the tour and paper rather than something established here.

Installing the core package and the four extras

The README gives two install paths. With uv: `uv init my-agent-project`, `cd my-agent-project`, `uv add nooa`. With pip: `pip install nooa`. Four optional distributions are separate packages that can also be pulled in as extras of the core package: `nooa-cli` (the `nooa` command, trace viewer, eval runner), `nooa-acp` (a coding agent for Agent Client Protocol hosts such as Zed), `nooa-memory` (the `MemoryManager` long-term memory subsystem), and `nooa-bench` (`BenchAgent` and the Harbor benchmark runner). You can install them by name with `uv add nooa-cli` or as extras with `uv add "nooa[cli]"`, and several at once with `uv add "nooa[cli,memory]"`. One package is not on PyPI: `eval_pipeline` installs from the repository with `uv add "eval_pipeline @ git+https://github.com/NVIDIA-NeMo/labs-OO-Agents.git@main#subdirectory=util/eval_pipeline"`. To track development instead of a release, the README shows `uv add "nooa @ git+https://github.com/NVIDIA-NeMo/labs-OO-Agents.git@main"`, and a tag can be pinned the same way with `@v0.0.7`. Note that the README's own example pins v0.0.7 while the latest release listed is v0.0.10, so the tag in the docs lags the release history.

The sandbox requirement is a design constraint, not a warning label

NOOA's quick start opens with a safety note that calls the project research software and states plainly that agents can be configured to execute LLM-generated code. The note lists what can go wrong: sending private data to uncontrolled locations, deleting files, modifying environments. It recommends running agents in a sandbox isolated from your primary filesystem, and names NVIDIA OpenShell as an example. The framework does apply AST checks to generated code and module deny-lists before execution, but the README is explicit that these are defense-in-depth guardrails and not a containment boundary, existing to keep generated code from freezing the event loop and to catch common mistakes early rather than to stop code that is actively trying to do harm. That sentence should decide your deployment topology. If you cannot isolate the process, the guardrails are not a substitute, and the README does not claim they are. This is the clearest case where NOOA is the wrong tool: an environment where generated code shares a filesystem with anything you care about.

What you give up compared with a graph-based framework

A graph-based agent framework such as LangGraph represents the workflow as nodes and edges you declare up front, which makes the control flow inspectable without reading the model's output. NOOA inverts that: the control flow lives inside a method that the model writes at runtime, and the Python class is the only static structure you get. The trade is legibility for composition. You gain ordinary Python testing, tracing, refactoring and version control over the parts you wrote, and you lose the ability to draw the whole trajectory before a run. The README's claim that this supports familiar Python workflows is credible for the deterministic half of a class and much less so for the `...` methods, where the interesting behaviour is generated. There is a second cost: version churn. Releases listed are v0.0.8, v0.0.9 and v0.0.10 between late July and early September, all in the 0.0.x range, and the README still pins v0.0.7 in its source-install example. Treat every minor bump as a possible breaking change until the project says otherwise.

Licence status and what the repository actually declares

The README carries an Apache 2.0 licence badge linking to a LICENSE file on main, and the badge text reads `license-Apache%202.0-blue`. The repository metadata, however, reports the licence as NOASSERTION, which means the platform's detector could not confirm a recognised licence from the files it inspected. Those two signals disagree, and the disagreement is not something this review can resolve. Neither reading is legal advice, and if you plan to ship NOOA inside a product you should open the LICENSE file yourself and confirm what it contains rather than trusting either the badge or the metadata. The practical consequence of the ambiguity is that a compliance review will stall on it. The four extras are separate distributions, so their licence files need checking separately if you install them.

Maintenance cost you are signing up for

The upgrade surface is wider than one package. Core plus up to four extras plus an unpublished `eval_pipeline` pulled from a git subdirectory means five or six version pins to reconcile, and the extras are installed by name or as extras of core, so a core bump can drag the others with it. Pinning a tag with `uv add "nooa @ git+https://github.com/NVIDIA-NeMo/labs-OO-Agents.git@v0.0.7"` freezes the framework but not the extras, which resolve from PyPI independently. The README's own examples are inconsistent about which version to pin, which is a small signal that the release process is still moving. Budget for reading release notes on each 0.0.x bump, and for re-running your own agent tests whenever the generated-code REPL or the AST validation changes, since those are the parts your code cannot type-check against.

Who should pick this up, and what to check before you commit

NOOA fits teams whose agent logic is already shaped like a domain object: an order, a ticket, a document, with typed fields and a handful of methods where one or two steps need judgement. It fits them if they can run the process in an isolated environment, because the README's safety note is unambiguous about what generated code can do. It does not fit teams that need a frozen API, a licence determination that clears legal without a manual read, or a control flow they can inspect before execution rather than after. Before adopting, verify that the LICENSE file matches the Apache 2.0 badge, that `eval_pipeline` installs from the git subdirectory in your environment, and that your sandbox keeps generated code off your primary filesystem. Then read the paper and the 10-minute tour, in that order, because the tour shows composition and the paper carries the design principles the README only gestures at.

Editorial conclusion

Adopt NOOA if your agent logic already looks like a Python object with typed fields and methods, and if you can run it inside a sandbox such as NVIDIA OpenShell before anything generated touches a real filesystem. Do not adopt it if you need a stable API surface, a published licence file you can read without ambiguity, or a framework whose generated code you are willing to execute unsandboxed. Verify three things first: that the LICENSE file in the repository actually resolves to Apache 2.0, that the eval_pipeline subdirectory installs cleanly from git because it is not on PyPI, and that your deployment keeps generated code away from your primary filesystem. The README's own safety note is the boundary to design around, not a footnote.

Official sources

  1. Issues
  2. NVIDIA-NeMo/labs-OO-Agents on GitHub
  3. README
  4. Releases
Community notes

Community notes