NVIDIA-labs OO Agents · NOOA

Seven projects to build on NOOA

Ideas ranked by how hard they would be to build on any other agent framework — with an honest note on the ones that don't really need NOOA at all.

Grounded in a read of labs-OO-Agents at the checked-out revision. Nothing here has been built or executed; every file reference was verified against source, but no claim about runtime behaviour has been tested.

Executive summary

Seven projects that could be built on NVIDIA-labs OO Agents, scored on a single question: how hard would this be to build on any other agent framework? Ideas that would work equally well on LangGraph or a hand-rolled tool loop are marked as such rather than padded out.

The framework has six genuinely distinguishing traits. Two matter most — agents being real Python classes (the axiom everything else derives from) and live objects passed by reference into the model's REPL rather than serialized to JSON. A third, always-on typed ATIF trajectories, is the most underrated. Code-as-action is impactful but not unique — it is published prior art, and projects resting on it alone score poorly.

Two orderings, do not confuse them. Rank answers "which project is worth the most?" Sequence answers "which do you open your editor on Saturday?" They disagree, deliberately — the highest-value project is not the best first move.

So: rank order 03 → 01, build order 01 → 03. Build 03 first and you are writing a regression harness for agents you have not yet learned to write; build 01 first and you arrive already knowing what your own trace looks like when it goes wrong — which is the thing the harness has to detect.

Rank order
03 → 01 → 04 → 05 → 06 → 07 → 02  (by value)
Build order
01 → 03  (by what teaches you the next step — see recommendation)
Scored on
Feature centrality 30% · counterfactual difficulty 30% · compounding impact 25% · low risk 15%. Weights are a judgment call — see how the order flips.
Hard constraint
Three of these run model-generated code. NOOA's AST checks are explicitly not a containment boundary — OS-level isolation is required.
Status
Source-grounded, not executed. File and line references verified; runtime behaviour inferred from source and docstrings.

First: what is actually unique here

"Build something on framework X" is only interesting if the thing you build is hard to build on framework Y. So the projects below are scored against a specific question: does this exercise something NOOA does that LangGraph, CrewAI, or a hand-rolled tool loop does not?

Reading the source, six things qualify. Everything else NOOA offers — MCP clients, LiteLLM model routing, Langfuse/Phoenix/OTLP exporters, a memory package — is table stakes across the ecosystem and earns a project no points.

A · Agents are Python classes

A metaclass turns fields into state, methods into capabilities, the class docstring into the system prompt, and type annotations into the I/O contract. The practical consequence is that agents inherit, compose, get type-checked, and get unit-tested like any other object.

src/nooa/metaclass.py, src/nooa/agent.py

B · An ... body means "an LLM implements this"

Methods whose body is a literal ellipsis become generation methods; methods with real bodies stay deterministic Python. One class holds both, and the visual difference between "this is guessed" and "this is guaranteed" is one token wide.

src/nooa/ellipsis_detection.py, src/nooa/metaclass.py

C · Code as action

The model acts by writing Python into a Jupyter-style REPL that has self, imports, and helpers in scope — not by emitting tool-call JSON. Loops, filters, and intermediate variables come for free, without a schema per operation.

src/nooa/strategies/codeact.py; README.md:64

D · Live objects, passed by reference

The strongest differentiator. Conventional frameworks serialize every tool argument to JSON and hand the model a copy. NOOA puts the real object in the REPL namespace. The model calls methods on the same instance your process is holding, and mutations are simply real.

README.md:65 ("live-object arguments passed by reference")

E · Documentation as a runtime API surface

doc(obj) renders any class, function, module, or instance as a prompt-ready contract, expanding referenced types inline and deduplicating them — and the model can call it mid-run to expand detail on demand. Annotated[str, hidden] keeps fields such as API keys out of that rendering entirely.

src/nooa/agentdoc/core.py:45, src/nooa/agentdoc/_visibility.py

F · Total, structured, on-by-default observability

Every LLM call, code execution, and method invocation is traced with parent-child spans, and runs export to ATIF v1.7 — a versioned Pydantic trajectory schema with normative rules on step ordering, joinability, and context-management boundaries. This is not a log file. It is a typed, diffable artifact.

src/nooa/tracing/, src/nooa/atif/schema.py

Correction to an earlier claim. I previously suggested gating a dangerous method by hiding it until a risk check passes. The source does not support that. src/nooa/_visible.py is an explicit no-op kept only for backward compatibility — its own docstring says "everything is visible by default in nooa" — and hidden is a static Annotated[...] marker resolved per class, not a runtime toggle. The right mechanism for guarding a call is MethodPrecondition / MethodPostcondition in src/nooa/strategy_validation.py: preconditions fail fast before generation, and postconditions raising InvariantError are routed back to the model as correctable feedback rather than crashing the run. That is a better fit anyway — the model learns why it was refused.

The projects

01 Portfolio analyst over live objects Weekend

What it is

An agent class holding your actual position data and broker connection as typed fields — portfolio: DataFrame, broker: Broker, prices: PriceFeed — where analysis happens by the model writing pandas directly against those objects in the REPL.

class PortfolioAnalyst(Agent, llm=llm):
    """You analyse a live portfolio and propose rebalances."""

    portfolio: DataFrame
    broker: Broker
    api_key: Annotated[str, hidden] = ""   # never rendered into a prompt

    def max_position_pct(self) -> float:    # real body: deterministic
        return 0.15

    async def propose_rebalance(self, thesis: str) -> RebalancePlan:
        """Propose a rebalance consistent with the stated thesis."""
        ...                                  # ellipsis: LLM-driven
Why it showcases NOOA

This is the cleanest demonstration of D (live objects) that exists. Consider what the same task costs elsewhere: to let a model compute a rolling correlation, you must anticipate the operation, define a compute_correlation tool with a JSON schema, serialize the frame in, deserialize a result out — and you must do that again for every unanticipated operation. Under C (code as action) the model writes three lines of pandas against the frame that already exists in memory. The set of analyses it can perform is no longer bounded by the set you predicted.

It also lands A and B hard, because a portfolio agent is exactly where the deterministic/generated boundary matters most: max_position_pct() has a real body and is therefore a guarantee, while propose_rebalance() has an ellipsis body and is therefore a guess. Encoding "which parts of my trading logic are allowed to be wrong" as a syntactic property of the class is a genuinely different way to reason about risk.

Add a MethodPrecondition asserting that no proposed order exceeds max_position_pct(), and a postcondition raising InvariantError on violation, and you get J: the model is told why its plan was rejected and retries against the constraint, instead of the run dying.

What it does not showcase
Showcase: high  The best single demonstration of the framework's headline feature, and the smallest thing on this list. Run it read-only against a paper account until you have watched a few hundred traces.

02 MCP aggregator agent Weekend

What it is

One agent class with several MCP servers attached as typed fields — mail, calendar, a notes or knowledge store — performing a real recurring job end to end rather than answering one question per server.

Why it showcases NOOA

Partially, and it is worth being precise about which part. MCP support itself is not a NOOA differentiator; every serious framework has a client, and examples/quickstart/11_mcp.py shows a conventional one. The project earns its place on a narrower claim: under conventional tool-calling, combining three servers means three model turns — call mail, get JSON back, reason, call calendar, get JSON back, reason, call notes. Under C, the model writes one cell that fetches from all three, filters in Python, joins them on a key, and returns a result. The reasoning happens in code rather than across round-trips, which is fewer tokens, fewer opportunities to lose the thread, and one trace span instead of six.

That is a real and measurable benefit. It is also the only unique thing this project demonstrates.

What it does not showcase
Showcase: medium  Genuinely useful, thin as an argument for NOOA. Build it to learn the framework, not to justify it.

03 Golden-trajectory regression CI for agents Substantial

What it is

A pytest plugin that captures real agent runs as ATIF trajectories, stores them as fixtures, and — when you change a prompt, swap a model, or switch strategies — replays and diffs behaviour, not just final output. Did it take more steps? Call a different method? Branch elsewhere? Burn 40% more tokens for the same answer?

Why it showcases NOOA

This is the project I would bet on, because it is the one that is genuinely hard to build anywhere else, and the reason is structural rather than incidental.

Behavioural regression testing for agents needs three things at once. First, a complete and structured record of what happened — F gives you that by default, with parent-child spans preserved across orchestrators, generation methods, and helpers, and with src/nooa/atif/schema.py providing a versioned Pydantic schema whose normative rules (sequential step ids, joinability, context-management boundary semantics) are enforced by tests in the repo. Diffing two typed trajectories is tractable in a way that diffing two log files is not. Second, the agent must be re-instantiable in a test harness with dependencies substituted — which A gives you free, because the agent is a class and the test is just pytest. Third, deterministic replay of non-model state, which the event-sourced storage layer (src/nooa/storage/, snapshots) supports.

Most frameworks give you at most one of the three. Tracing is usually an add-on exporter producing spans shaped for a dashboard, not for assertion; agents are usually graph configurations rather than objects, so there is nothing clean to instantiate; and state is usually held in a runner you cannot snapshot.

The wider point is that prompt engineering is currently done by vibes, because nobody can see regressions. A tool that fails CI on "this prompt edit made the agent call the database twice as often" would be useful to everyone building on the framework.

Honest caveat

packages/nooa-bench/src/nooa_bench/trace_analyzer.py already exists, as do runner.py and protocol.py, and examples/quickstart/14_atif_trajectory.py demonstrates export. So this is extending an existing foundation, not inventing from nothing. Read those three files before scoping — the honest version of this project might be "add trajectory diffing and a pytest fixture API to nooa-bench," which is smaller and more likely to be upstreamed.

Showcase: highest  Exercises A, F, and event-sourced storage together, and each one is load-bearing. Also makes every other project on this list easier to iterate on.

04 Self-extending domain expert Substantial

What it is

An agent that, on completing a task it found difficult, writes the procedure down as a reusable capability and loads it next time. Facts go to long-term memory; procedures become code.

Why it showcases NOOA

Because the framework ships explicit affordances for exactly this, which is unusual. src/nooa/tools/method_writing_lib.py defines a MethodWriting skill whose docstring instructs the model to define helper functions at the top of a REPL cell — and, more interestingly, to decorate standalone async functions with @strategy(PredictStrategy()) and an ellipsis body to create per-item LLM sub-calls fanned out through asyncio.gather. The agent is not merely writing helper code; it is authoring new generation methods at runtime and parallelising them. That is B and C composing in a way that has no clean analogue in a tool-calling framework, where a new capability means a new schema registered out-of-band.

library_writing_lib.py sits alongside it for persisting capabilities beyond a single cell, the skills/nooa-self-extending/ skill documents the pattern, and DynamicMethodAdditionError is a first-class error type in src/nooa/errors — a good sign that dynamic method addition is a supported path with defined failure modes rather than an accident.

Pair it with nooa-memory, whose module list (retrieval.py, reflection.py, forgetting.py, generative.py) is more opinionated than a bare vector store. Then instrument the thing that actually matters: skills written, skills reused, and tokens-per-task over weeks. That last chart is the entire project — without it you have an agent that accumulates clutter and no evidence it is learning.

What it does not showcase
Showcase: high  Highest ceiling, highest risk of producing an impressive demo with no measurable improvement. The instrumentation is not optional.

05 Multi-agent teams by composition, not message bus Substantial

What it is

A small team — say author, reviewer, and integrator — where one agent holds another as a typed field and invokes it as a method: await self.reviewer.critique(patch). No router, no message schema, no graph definition.

Why it showcases NOOA

It is the sharpest available test of the framework's central claim. If agents really are ordinary Python objects (A), then multi-agent orchestration should reduce to ordinary composition, and the entire category of orchestration machinery that other frameworks sell — routers, state graphs, message protocols, handoff schemas — should evaporate into method calls. Nothing else on this list puts the thesis so directly at risk.

Two secondary features carry real weight here. D means the author agent can hand the reviewer a live object rather than a serialized summary, so the reviewer inspects the same artifact rather than a lossy description of it. And F's parent-child spans mean a nested agent call appears as a nested span, so the trace of a three-agent run reads as a call tree — which is what it actually is.

The honest risk

Composition may relocate complexity rather than remove it. Message buses exist partly to solve problems that method calls do not address: retry and backoff at a boundary, cycle detection, concurrency between peers, and observability of a handoff. If you find yourself writing a coordinator class that dispatches, tracks status, and retries, you have rebuilt an orchestrator with worse ergonomics — and that negative result is worth writing up, because it bounds the claim. Build the equivalent in one graph-based framework and compare debuggability honestly rather than charitably.

Showcase: medium-high  The most falsifiable project here, which is a compliment. Its value holds whichever way the result goes.

06 Harness-ablation study on open models Research

What it is

Take an open model at two or three sizes, run one benchmark, and ablate the harness: context blocks on/off, summarization on/off, skills on/off, CodeAct versus Predict versus Prefill. The question worth answering is whether harness capability substitutes for parameter count — and where that substitution breaks down.

Why it showcases NOOA

The repo is built for it. src/nooa/strategies/ contains codeact.py, predict.py, pure_python.py, prefill.py, and composite.py behind a common GenerationStrategy base with set_default_strategy(), so swapping the reasoning loop is a config change rather than a rewrite — that is the ablation axis handed to you. src/nooa/context_blocks/ and the skill registry give two more axes. packages/nooa-bench supplies BenchAgent and a runner, and util/eval_pipeline the scoring. The repo's own framing — a paper and a blog post on harness capabilities and model performance — means there is a baseline to compare against rather than a vacuum.

Local models are first-class: Ollama and vLLM are both supported through LiteLLM with no API key, so a full ablation grid costs GPU time rather than inference spend. That matters when the design calls for dozens of runs per cell to get error bars.

Two caveats before you scope it
Showcase: medium  Research value: high  Publishable shape, modest framework-differentiation. Pick it for the result, not the demo.

07 Cross-episode memory for the existing benchmark agents Research

What it is

examples/arc_agi_3/ and examples/cybergym/ are already in the repo, each with configs, skills, and tests. Both currently start each episode cold. The experiment: give the agent memory that persists across episodes and measure whether it transfers.

Why it showcases NOOA

Modestly, and mostly by combining nooa-memory with the event-sourced snapshot layer to carry state across runs. ARC is the more interesting target because its puzzles are deliberately designed to resist transfer — a positive result there would be a real finding, and a negative one is informative rather than embarrassing. trace_analyzer.py in nooa-bench gives you the measurement apparatus without building it.

What it does not showcase
Showcase: low  Lowest novelty, lowest risk, fastest to a result because the scaffolding exists. A reasonable warm-up before project 06.

Feature coverage at a glance

Project A
Classes
B
...
C
CodeAct
D
Live obj
E
doc()
F
ATIF
Unique?
01 Portfolio analyst●●●●◐○High
02 MCP aggregator◐◐●○○○Medium
03 Trajectory CI●○○○○●Highest
04 Self-extending●●●◐●◐High
05 Composed teams●●◐●○●Med-high
06 Harness ablation◐●●○○●Medium
07 Cross-episode memory◐○◐○○◐Low

● central to the project  ·  ◐ used but incidental  ·  ○ not exercised. "Unique?" answers: how hard would this be on another framework?

Ranking, and why

A ranking is only as good as the axis it sorts on, and the obvious axis — "showcases the most NOOA features" — is the wrong one. Counting features rewards breadth over depth, and a project that touches six features incidentally is worth less than one that makes two features load-bearing. So the ranking below is built in two steps: rank the features by how much they matter, then rank the projects by how centrally they use the features that matter most.

Step 1 — Not all six leverage points are equally valuable

The critical distinction, and the one most write-ups of this framework miss, is that uniqueness and impact are different axes. Some of NOOA's best ideas are not original to it, and some of its most original ideas are not that consequential. Sorting by "importance" means weighing both.

1
A · Agents are Python classes

Most important, because it is load-bearing for everything else. B is syntax on top of it, D is only possible because self is a real object in scope, and the testability that makes project 03 viable falls out of it for free. On its own it looks like an ergonomic preference; structurally it is the axiom the rest of the framework is derived from. Moderately unique — DSPy has module classes, but does not unify state, prompt, and I/O contract into one declaration.

High impact
2
D · Live objects passed by reference

Most unique. Frameworks that support code-as-action mostly still hand the model serialized data; putting the caller's actual in-memory instance in the REPL namespace, mutations and all, is rare. It also has the highest ratio of behaviour change to explanation length — one sentence describes it, and it removes an entire category of stale-copy bugs. Ranked below A only because it depends on A to exist.

High uniqueness
3
F · ATIF trajectories and always-on tracing

The most underrated. Tracing is universal, so the instinct is to discount it — but a versioned Pydantic schema with enforced normative rules is a different artifact from a span exporter aimed at a dashboard. One you can assert against in a test; the other you can only look at. That difference is what makes the highest-ranked project possible at all.

High impact
4
C · Code as action

Very high impact, but not unique — and this is where honest scoring bites. The CodeAct pattern is published prior art and ships in other libraries, notably smolagents. NOOA executes it well and wires it to self, but a project whose entire argument is "the model writes Python" is not an argument for this framework. Discounted accordingly, which is what pushes project 02 to the bottom.

Med uniqueness
5
B · Ellipsis bodies mark generated methods

Genuinely clarifying — encoding "this part is allowed to be wrong" as a one-token syntactic property is a good idea with real review and audit value. But it is sugar over A, and no project succeeds or fails on it.

Med impact
6
E · doc() progressive disclosure

Real engineering, supporting role. It solves context bloat, which matters at scale, but it is a token-efficiency mechanism rather than a capability. Notably it is central to only one project on this list — either a gap in the list, or confirmation that it is infrastructure rather than a headline.

Low standalone

Step 2 — Scoring the projects

Four criteria, weighted. Feature centrality (30%): does it make the high-ranked features load-bearing rather than incidental? Counterfactual difficulty (30%): how hard would this be on another framework — the real test of "showcase"? Compounding impact (25%): does finishing it make other work easier, or help anyone but you? Low cost and risk (15%): effort, and the odds of ending with nothing.

#Project Centrality
×0.30
Counterfactual
×0.30
Compounding
×0.25
Low risk
×0.15
Score
03Trajectory CI45524.25
01Portfolio analyst54253.95
04Self-extending expert54323.75
05Composed teams43433.55
06Harness ablation32422.80
07Cross-episode memory22342.55
02MCP aggregator22252.45

Scores are 1–5 per criterion. The weights are a judgment call, not a measurement — see "if you disagree with the weights" below.

The ranking, with the reasoning

1
03 · Golden-trajectory regression CI  4.25

Wins on the two heaviest criteria at once. Counterfactually it is the hardest thing on this list to build elsewhere, and for a structural reason rather than a convenience one: it needs typed trajectories, always-on nested tracing, and re-instantiable agents simultaneously, and most frameworks supply at most one. It also compounds — every other project becomes measurable instead of anecdotal once it exists, and it is plausibly upstreamable given how much of nooa-bench is already there.

Why it wins despite not touching D or C at all: this is the case for ranking by centrality rather than by feature count. It exercises only two of the six leverage points — but both are load-bearing, one is the framework's axiom and the other its most underrated asset, and the project would be impossible if either were absent. Compare project 02, which touches more surface area and demonstrates almost nothing.

1st
2
01 · Portfolio analyst over live objects  3.95

The best pure showcase, and the only project scoring 5 on centrality: A, B, C, and D are all load-bearing, and D — the single most unique feature — is the entire point. It loses first place solely on compounding impact, because it is a personal tool that helps nobody else. Note the tension this exposes: if you rank by "showcases the most unique feature," this is first, not 03. The weights, not the evidence, decide between them.

2nd
3
04 · Self-extending domain expert  3.75

Ties project 01 on centrality — an agent authoring new generation methods at runtime and fanning them out through asyncio.gather composes B, C, and E in a way tool-calling frameworks cannot express, since there a new capability means a schema registered out-of-band. It ranks third only on risk. This is the project most likely to yield a striking demo and no measurable improvement, and unlike the others that failure mode is invisible unless you instrument tokens-per-task from day one.

3rd
4
05 · Composed teams  3.55

Scores well on compounding because the result is the deliverable — it bounds the framework's central claim either way, and a negative result ("composition relocates orchestration complexity rather than removing it") is as useful as a positive one. Held back on counterfactual difficulty by an awkward fact: composing objects is just Python, so the build is easy and the experiment is what carries the value. That makes it the most falsifiable project here and the one whose worth least depends on it succeeding.

4th
5
06 · Harness ablation  2.80

The clearest case of the two axes diverging. Research value is high and the result would be genuinely interesting, but ablation is generic methodology — NOOA makes it cheap rather than possible, so counterfactual difficulty scores low. Two of the ablation arms also sit on experimental, FutureWarning-gated strategies. Pick this for the finding, not the demonstration.

5th
6
07 · Cross-episode memory  2.55

Ranks low on every axis except risk, where existing scaffolding in examples/arc_agi_3/ gives it a genuine edge. Cross-episode memory is a well-trodden research direction and touches little of the framework. Reasonable as a warm-up for 06; weak as a destination.

6th
7
02 · MCP aggregator  2.45

Last, and the ranking earns its keep here by saying so. This is the project most likely to feel productive and prove least — MCP support is universal, the results arrive as data rather than live objects so D is untouched, and the sole distinctive benefit is that CodeAct collapses three round-trips into one cell. Genuinely useful software; not an argument for the framework. Its 5 on low-risk is the only thing keeping it off the floor.

7th

If you disagree with the weights

The weights encode a specific goal — "demonstrate what makes NOOA different, and leave something useful behind." Under different goals the order changes, and it is worth seeing how much:

Optimise for showcase only

  1. 01 — Portfolio analyst
  2. 04 — Self-extending
  3. 03 — Trajectory CI

Optimise for shipping this week

  1. 01 — Portfolio analyst
  2. 02 — MCP aggregator
  3. 07 — Cross-episode memory

Optimise for a publishable result

  1. 06 — Harness ablation
  2. 05 — Composed teams
  3. 03 — Trajectory CI

Only project 01 appears in the top three of every ordering, including the weighted one. That is a stronger endorsement than its second-place score suggests, and it is the reason the recommendation below hedges the way it does.

One constraint that is not optional

The README is blunt about this at lines 130–133, and it deserves repeating because three of these projects run generated code against real systems. NOOA validates generated code with AST checks and applies module deny-lists — but the README calls these "defense-in-depth guardrails, not a containment boundary." Its reasoning is worth internalising: a static checker over Python cannot provide containment, because open() gives arbitrary file access, importlib loads modules straight from a path, and reflection reaches the rest.

The containment boundary is OS-level isolation — a container, a VM, or NVIDIA OpenShell. For projects 01 and 02 in particular, where the agent touches a broker or a real inbox, that means a container plus credentials scoped to read-only until the traces have earned your trust.

Recommendation

Do 01 then 03, in that order — and the ranking is what argues for the sequence rather than against it.

01, the portfolio analyst, is the only project in the top three of every ordering above. It is a weekend of work, it makes the framework's most unique feature the entire point, and it answers the question you should settle before investing further: does passing live objects into the model's REPL actually change how you build, or is the object-oriented framing an aesthetic preference? That is cheap to find out and expensive to assume.

03, the trajectory regression harness, is the weighted winner and the real destination. It is the one place where NOOA's design gives you something structurally hard to build elsewhere — typed ATIF trajectories, always-on parent-child tracing, and plain-class agents are each common enough alone and rare in combination. It helps anyone else building on the framework, it is plausibly upstreamable into nooa-bench, and it converts every subsequent experiment from anecdote into measurement.

The sequencing matters more than it looks: build 03 first and you will be writing a regression harness for agents you have not yet learned to write. Build 01 first and you arrive at 03 already knowing what a trace of your own agent looks like when it goes wrong — which is precisely the thing the harness has to detect.