NVIDIA-labs Object Oriented Agents (NOOA): a Python class as the agent boundary
NVIDIA Object Oriented Agents: the Pythonic way to build AI Agents.
At a glance
- What is it?
- NOOA folds prompts, tools, state and typed interfaces into one Python class and lets the model act by writing code. It is research software from NVIDIA NeMo, and the README says so plainly.
- Who is it for?
- Adopt NOOA if your team already writes Python services and wants agent state, prompts and typed contracts to live in a class you can test, refactor and put under version control, and if you are willing to run generated code inside a sandbox such as NVIDIA OpenShell. Skip it if you need a stable, documented API surface: pyproject.toml still carries Development Status :: 3 - Alpha, and the README describes the project as research software with rough edges.
- 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 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem NOOA solves: agent pieces scattered across abstractions
Most agent frameworks keep prompts, tool schemas, callbacks and workflow state in separate places. You register a tool in one structure, describe it in another, and keep the conversation state somewhere else again. The README frames NOOA as an answer to exactly that split, and the target reader is a Python developer who already knows how to write a class and would rather not learn a parallel vocabulary for the same ideas.
The claim is narrow enough to check. In NOOA, fields on the class are state, methods are capabilities, docstrings are prompts, and type annotations are contracts. That is the whole pitch, and it is why the project calls itself the Pythonic way to build AI agents. Nothing here is about a new runtime model or a hosted service. It is about which object owns the pieces.
Who is this for? Teams building agents that need typed inputs and outputs, retries on malformed model output, and a code path they can unit test without a network call. If your agent is a single prompt with a few retrieval calls, the class-shaped interface adds ceremony you will not get back.
How an agentic method becomes an LLM loop
The mechanism visible in the README is a convention on method bodies. A method whose body is `...` is handed to the runtime and becomes an agentic loop. A method with a real body stays deterministic Python. The docstring supplies the prompt and the annotations supply the contract, so the same class holds both kinds of method side by side.
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."""
...The README states that the model acts by writing Python in a Jupyter-style REPL with access to `self`, imports and helpers. That is the part worth pausing on. Python methods and type annotations supply the callable interfaces, so you do not maintain a separate tool-schema file next to your code. The trade is that the model is now writing code against your object graph, not calling a constrained function signature.
Two smaller details from the README shape the design. Live-object arguments are passed by reference, and generated streams are rejected: deterministic generators are supported, but a generated stream needs a separate stream contract and the framework fails clearly rather than guessing. Typed I/O comes with auto-retry. The package description in pyproject.toml names the same machinery from the other end: code-generating agent orchestration with event sourcing and serialized execution.
Installing NOOA and running a first agentic method
The README uses uv. The core package is `nooa`, and the Python constraint in pyproject.toml is `>=3.12,<3.14`, so a 3.12 or 3.13 interpreter is what you want. Create a project and add the package:
uv init my-agent-project
cd my-agent-project
uv add nooaThe README gives `pip install nooa` as the alternative. Either way you get the core framework only. The CLI, ACP, memory and benchmark pieces are separate distributions, installed by name or as extras:
uv add nooa-cli # or: uv add "nooa[cli]"
uv add nooa-memory # or: uv add "nooa[memory]"
uv add "nooa[cli,memory]" # several at onceYou still need a model provider. The repository ships a `.env.example` that lists `OPENAI_API_KEY` and `ANTHROPIC_API_KEY` as the keys to set, and it also sets `LITELLM_LOCAL_MODEL_COST_MAP=True` to stop litellm from fetching model costs from GitHub. Copy it and fill in one key.
For a first real use, take the class from the README and give the agentic method a typed return. The method body stays as `...`; the runtime supplies the implementation, and the annotation on `triage` is what it must satisfy. Run it the way you would run any Python entry point. What you should see is a `Ticket` object, not a string you have to parse, and a retry rather than a crash if the first generation does not match the type.
One thing the README does not document is rollback. If a generated action changes state you did not want changed, the framework's event sourcing is described in the package metadata but the README does not walk through undoing a step.
The safety boundary NOOA does not claim to be
The README opens its Quick Start with a warning block, and it is unusually direct. NOOA is research software. Agents can be configured to execute LLM-generated code. That code may send private data to uncontrolled locations, delete files, or modify its environments. The recommended posture is a sandbox isolated from your primary filesystem, and the README names NVIDIA OpenShell as an example.
NOOA does validate generated code with AST checks and applies module deny-lists before execution. The README then states what those are for: keeping generated code from freezing the event loop and catching common mistakes early. It says explicitly that they are defense-in-depth guardrails, not a containment boundary, and that they are not intended to stop code that is actively trying to do harm.
That sentence should decide your deployment shape. If your threat model includes a prompt-injected model writing `import os` and walking your home directory, the framework's own documentation tells you the guardrails are not the answer. The sandbox is. Teams that cannot run agents in an isolated environment, or that cannot accept a model writing arbitrary Python against a live object graph, should treat NOOA as the wrong tool regardless of how clean the class interface looks.
The second limitation is maturity, and it is stated in the repository rather than inferred. pyproject.toml carries `Development Status :: 3 - Alpha`, and the README asks readers to expect rough edges. The last push was on 2026-09-10 and the most recent release was v0.0.10 on 2026-09-04, so work is ongoing, but the version numbers are still 0.0.x and the project describes itself as research software.
How NOOA differs from schema-first agent frameworks
The obvious comparison is a framework where you declare tools as JSON schemas or decorated functions and the framework assembles the prompt for you. LangChain-style tool registration and the OpenAI Agents SDK both sit in that family: you describe a capability, the framework serializes it into the model's tool list, and the model returns a structured call the framework dispatches.
NOOA inverts the direction of that description. Instead of writing a tool definition that mirrors a Python function, you write the Python function, and the runtime exposes it to a model that writes code calling it. The README's phrasing is that Python methods and type annotations supply the callable interfaces, reducing the need to write separate tool-schema definitions. The practical difference shows up in composition. A schema-first framework gives the model a flat menu of named tools. A code-writing agent can loop, branch, build intermediate values and call several methods in one generation, because it is writing a program rather than choosing from a list.
That flexibility is also the cost. A schema-first framework constrains what the model can express, which makes its behavior easier to bound and audit. NOOA hands the model a REPL, which is why its own README leads with a sandbox warning and why the AST checks exist at all. If your agents are mostly retrieval plus a couple of API calls, a schema-first framework gives you the same result with a smaller blast radius. NOOA earns its complexity when the task genuinely needs multi-step code.
Package layout, licence and the cost of tracking main
The core install is small and the dependency list in pyproject.toml is short: pydantic, litellm, httpx, openinference-instrumentation-litellm and msgpack. The litellm floor is `>=1.97.0`, and the comment above it records why that floor exists, including staying past CVE-2026-49468 and away from the yanked 1.82.7 and 1.82.8 releases. That is a useful signal: the pin is maintained, and the reasoning is in the file rather than in a changelog nobody reads.
Versioning is derived from git tags by uv-dynamic-versioning. On a tag `vX.Y.Z` the published wheel is `X.Y.Z`. Between tags, the build produces a PEP 440 dev pre-release of the form `X.Y.(Z+1).dev<distance-from-tag>`. If you install from a branch rather than a release, expect a version string that encodes how far you are from the last tag. The README gives the source install for both cases:
# latest development state
uv add "nooa @ git+https://github.com/NVIDIA-NeMo/labs-OO-Agents.git@main"
# pinned to a release tag
uv add "nooa @ git+https://github.com/NVIDIA-NeMo/[email protected]"Note that the README's pinned example uses v0.0.7 while the latest release listed is v0.0.10, so substitute the tag you actually want. Tracking `main` means tracking an alpha branch, and the upgrade cost is the usual one for a fast-moving 0.0.x project: read CHANGELOG.md before bumping, because the README does not promise API stability.
On licensing, pyproject.toml declares `license = {text = "Apache-2.0"}` and the classifier is `License :: OSI Approved :: Apache Software License`, while the repository's licence field resolves to NOASSERTION. The README badge links to Apache 2.0. If you need certainty for redistribution, read the LICENSE file and THIRD_PARTY_NOTICES.md in the repository rather than the metadata.
Editorial conclusion
Adopt NOOA if your team already writes Python services and wants agent state, prompts and typed contracts to live in a class you can test, refactor and put under version control, and if you are willing to run generated code inside a sandbox such as NVIDIA OpenShell. Skip it if you need a stable, documented API surface: pyproject.toml still carries Development Status :: 3 - Alpha, and the README describes the project as research software with rough edges. Before committing, verify two things in your own environment: that your Python version satisfies requires-python >=3.12,<3.14, and how the AST validation and module deny-lists behave against the code your model actually generates, since the README states they are guardrails rather than a containment boundary.
Frequently asked questions
What is NVIDIA-labs OO Agents?
It is NVIDIA-labs Object Oriented Agents (NOOA), a model-agnostic Python framework for building AI agents. The README describes it as an object-oriented interface that brings state, capabilities, prompts and typed interfaces together in a single Python class.
What is NVIDIA-labs Object-Oriented Agents?
The same project, under its full name. Agents are Python objects: fields are state, methods are capabilities, docstrings are prompts and type annotations are contracts, with method bodies of `...` becoming LLM-driven agentic loops.
How do I install NOOA?
The README uses uv: run `uv init my-agent-project`, then `uv add nooa`. It also gives `pip install nooa` as an alternative. The CLI, ACP, memory and benchmark packages are separate distributions, installed as `nooa-cli`, `nooa-acp`, `nooa-memory` and `nooa-bench` or as extras such as `nooa[cli]`.
Which Python version does NOOA require?
pyproject.toml sets `requires-python = ">=3.12,<3.14"`, and the classifiers list Python 3.12 and 3.13. A 3.12 or 3.13 interpreter is what the packaging metadata supports.
Does NOOA run LLM-generated code?
Yes. The README states that agents can be configured to execute LLM-generated code, and that the model acts by writing Python in a Jupyter-style REPL with access to `self`, imports and helpers. It recommends running agents in a sandbox isolated from your primary filesystem, such as NVIDIA OpenShell.
Is NOOA safe to run outside a sandbox?
The README does not claim it is. It says the AST validation and module deny-lists are defense-in-depth guardrails, not a containment boundary, and that they are not intended to stop code that is actively trying to do harm. The README also notes generated code may delete files or send private data to uncontrolled locations.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nvidia-nemo-labs-oo-agents)