Building an AI agent in 2026 usually means juggling four separate artifacts: prompt templates in one folder, JSON tool schemas in another, callback glue code somewhere in between, and a workflow graph tying it all together. Change one, and you quietly break the other three.
On 22 July 2026, NVIDIA Labs published a paper proposing something almost aggressively simple. Its thesis fits in one sentence: an agent is a Python object.
The framework is called NOOA — NVIDIA Object-Oriented Agents — and it is model-agnostic. Its argument is not that we need a better agent framework. It is that we mostly need fewer agent-specific abstractions, because Python already has good ones.
The Core Idea
In NOOA, the mapping between object-oriented programming and agent design is one-to-one:
| Python concept | Agent concept |
|---|---|
| Methods | Actions the model can take |
| Fields | Agent state |
| Docstrings | Prompts |
| Type annotations | Contracts |
The clever part is how a method becomes model-driven. A method whose body is literally ... gets completed at runtime by an LLM-driven agent loop. A method with a normal body stays ordinary, deterministic Python.
from dataclasses import dataclass
@dataclass
class InvoiceAuditor:
"""You audit supplier invoices for a Tunisian SME.
Flag anything that violates TTN e-invoicing rules."""
company_id: str
flagged: list[str]
def load_invoices(self, month: str) -> list[dict]:
# Normal Python. Runs deterministically, every time.
return db.query(self.company_id, month)
def assess(self, invoice: dict) -> tuple[bool, str]:
"""Decide whether this invoice is compliant.
Return the verdict and a one-sentence justification."""
...load_invoices is code you wrote. assess is code the model runs. Both live in the same class, share the same state, and are read the same way by a human reviewer.
That single design decision is what makes the rest interesting. Because the agent is an object, you can test it, trace it, refactor it, subclass it, and put it under version control exactly like any other module in your codebase. There is no separate prompt registry to keep in sync. The docstring is the prompt, so it is reviewed in the same pull request as the code it describes.
Six Ideas on One Surface
The paper's second contribution is a claim about consolidation. NVIDIA identifies six model-facing capabilities and argues NOOA is the first framework to combine all of them in one place:
- Typed input/output — the model's returns are checked against real Python type annotations, not a hand-maintained JSON schema.
- Pass-by-reference over live objects — the model receives handles to actual objects in memory, not serialized snapshots of them.
- Code as action — the model acts by writing and executing Python, rather than emitting tool-call JSON.
- Programmable loop engineering — the agent loop itself is code you can shape, not an opaque runtime.
- Explicit object state — state lives in fields you can inspect, not buried in conversation history.
- Model-callable harness APIs — the model can query its own context and event stream through ordinary method calls.
Notably, the authors are not claiming to have invented these. They explicitly observe that the community is already converging on several of them, often as experimental or partial features, and present the comparison to encourage adoption. That framing is refreshingly honest, and it is probably the more important signal for practitioners: these six properties are becoming the baseline expectation for serious agent runtimes.
Why Pass-by-Reference Matters More Than It Sounds
Of the six, the one worth dwelling on is pass-by-reference over live objects.
Most agent frameworks serialize everything. Your agent needs a customer record, so the framework converts it to JSON, drops it into the context window, the model reasons over the copy, and returns another copy that you must reconcile with reality. Every round trip costs tokens and creates a chance for drift between the model's mental picture and your database.
Passing a live reference changes the economics. The model can call a method on the object to fetch only the field it needs, when it needs it, without ever holding the full record in context. For an agent working over a large dataset — a product catalogue, a codebase, a year of transactions — this is the difference between a system that fits in a context window and one that does not.
It also fixes a correctness problem. If the model mutates a live object, the mutation is real. There is no reconciliation step to get wrong.
Code as Action Beats Tool-Call JSON
The "code as action" idea has been quietly winning for a while. When an agent expresses an action as executable Python instead of a tool-call payload, it gets loops, conditionals, composition, and error handling for free. Three chained tool calls become one line of code. Filtering 500 results down to 3 happens in the interpreter, not by streaming 500 results through the context window.
NOOA formalizes this by making it the default rather than a special execution mode. The model is already writing methods on an object; the natural way to invoke five of them in sequence is to write five lines.
The trade-off is real and should be named: executing model-written code demands a sandbox. Any team adopting this pattern needs process isolation, filesystem restrictions, and network egress control before it reaches production. Convenience at the authoring layer does not remove the need for containment at the execution layer.
What NVIDIA Actually Demonstrated
The paper's third contribution is empirical: current models use this interface effectively. NVIDIA reports results across targeted capability tests plus agentic and reasoning benchmarks including SWE-bench Verified, Terminal-Bench 2.0, and ARC-AGI-3.
The point being made is not a leaderboard claim. It is a usability claim about the interface: models trained on ordinary Python already know how to work with classes, type hints, and docstrings, because those patterns saturate their training data. An agent framework that looks like idiomatic Python is, in a meaningful sense, pre-trained into the model. A bespoke DSL is not.
That is a strong argument, and it explains why the ergonomics keep converging toward "just write normal code."
What This Means If You Are Shipping Agents
You do not need to adopt NOOA to benefit from the paper. The architectural lessons transfer to whatever stack you already run:
Keep the prompt next to the code it governs. If your prompts live in a separate YAML file, a template store, or a prompt-management SaaS, you have created a synchronization problem that will bite you during a refactor. Docstrings are not the only answer, but co-location is.
Make state explicit. Agent state hidden inside accumulated conversation history is state you cannot inspect, assert on, or reset. Named fields on an object are debuggable at 2 a.m.; a 40-turn transcript is not.
Type your boundaries. Validated returns catch a whole class of silent failure that manual JSON parsing does not. If you are on TypeScript, this is the same argument our structured output guide makes from the other direction.
Own your loop. A framework that hides the agent loop hides exactly the thing you will need to tune — retry policy, validation, escalation, budget. We covered this in depth in loop engineering for AI agents.
Test agents like software. The whole promise of agent-as-object is that your existing tooling applies. If you cannot write a unit test against your agent today, the abstraction you chose is working against you.
The Bigger Shift
There is a pattern in how agent tooling has evolved over the past two years. Frameworks started elaborate — graphs, nodes, edges, orchestrators, state machines — and have been steadily shedding abstraction ever since. LangGraph simplified. The OpenAI Agents SDK shipped deliberately thin. smolagents bet on code-as-action. Anthropic's guidance has consistently pushed toward simpler loops with better tools.
NOOA is the most direct expression of that trend so far: not a lighter framework, but an argument that the right framework is mostly the language you are already writing in. Where Python has an abstraction, use Python's. Only add something agent-specific when Python genuinely has no answer — context, events, memory, validated loops.
That is a discipline, not a feature list. And it is one worth applying regardless of which framework name ends up on your pyproject.toml.
Getting Started
The paper is available on arXiv as 2607.20709 under a CC-BY-4.0 licence. At the time of writing, a public repository has not been widely indexed, so the practical move is to read the design principles and apply them to your current stack rather than wait for a package to install.
If you are evaluating agent architecture for a production system — and especially if you are weighing framework lock-in against building on plain language primitives — the six model-facing ideas make an excellent audit checklist. Run your current stack against them. The gaps will tell you where your next production incident is coming from.
At Noqta, we build AI agent systems for businesses across Tunisia and the Gulf, and this is precisely the architectural conversation we have at the start of every engagement: how much framework do you actually need? Increasingly, the answer is less than you think.
Related reading: