
如果你写过 AI Agent,一定经历过这种崩溃:
提示词在一个 YAML 文件里,工具定义在另一个 JSON schema 里,流程图在第三个文件里画成有向图,回调函数散落在第四处。改一个字段名,你得在三种文件格式里做全局替换。想设个断点?对不起,YAML 的边上打不了断点。
NVIDIA 昨天开源的 NOOA,一句话干掉了这一切:
一个 Agent,就是一个 Python 类。
方法就是它能做的动作,字段就是它的状态,文档字符串就是提示词,类型注解就是运行时强制执行的契约。没有单独的工具注册,没有提示词模板字典,没有 schema 声明。类定义本身,就是 Agent 规格说明书。
Apache 2.0 协议,pip install nooa 一行装完。这篇我带你从装到跑通,把这个思路彻底讲明白。
第一章 核心思想:你的 Agent 本来就该是个类
NOOA 全称 NVIDIA Object-Oriented Agents(对象导向智能体)。它的中心论点很朴素但很扎心:Agent 的每一个组成部分,Python 类里本来就有对应物。
对照表长这样:
- Agent 能做什么 → 类的方法
- Agent 的记忆和状态 → 实例字段
- 给模型的指令 → docstring 文档字符串
- 输入输出契约 → 类型注解(运行时真校验,不是摆设)
这不只是审美问题,是实打实的工程收益。当你的 Agent 就是一个普通 Python 对象,你就能用 pytest 测它、用 mypy 检查它、用 git blame 追责、用 IDE 跳转定义。整套 Python 工具链原封不动全能用。
对比一下图式框架:在 LangGraph 这类框架里,Agent 是”数据”——节点、边、穿针引线的状态对象,加上另外存放的提示词模板和工具 schema。当控制流本身很复杂、你想可视化时,这确实有价值。但代价是你的 Agent 不再是代码,于是你所有的程序员直觉都失效了。
第二章 两种方法:让模型写的,和你自己写的
这是 NOOA 最妙的设计,也是你必须一次记牢的规则。
生成式方法(GENERATION):函数体只写三个点 ...。运行时由 LLM 驱动的循环来实现它。它的签名 + docstring 就是提示词,返回类型会被自动校验。
确定性方法(DETERMINISTIC):正常的 Python 代码,你自己写。用来放那些绝对不能交给模型决定的逻辑——花钱上限、资格校验、数据库写入。
看一段真实代码你就懂了:
from nooa import Agent
class CodeReviewer(Agent):
"""你是资深 Python 代码审查员。关注正确性、性能、安全、可读性。
永远解释为什么这是问题,而不只是说它是问题。"""
recent_files: list[str] = []
severity_threshold: str = "medium"
def review_file(self, path: str, content: str) -> str:
"""审查单个 Python 文件,返回结构化反馈。"""
...
def check_security(self, code: str) -> list[str]:
"""扫描常见安全漏洞,返回问题列表。"""
...
看明白了吗?类的 docstring 变成系统提示词,方法的 docstring 变成工具描述,类型注解变成运行时校验,实例字段变成跨调用持久的状态。整个 Agent 规格,就这一段。
第三章 三分钟跑起来:安装到第一次 run
环境要求先说清楚:Python 3.12–3.13,版本不对直接装不上。
第一步 安装:pip install nooa(或 uv add nooa)。当前版本 v0.0.8,PyPI 上标注为 alpha,NVIDIA 自己定位是研究预览版。
第二步 写类:继承 Agent,写生成式方法(... 体)和确定性方法(正常代码体)。
第三步 跑:它是异步的,用 asyncio。
import asyncio
from nooa import Agent
class ResearchAgent(Agent):
"""你是技术研究 Agent。被问到某个话题时,搜索最新信息、批判性分析、给出关键发现和你自己的判断。"""
sources_consulted: list[str] = []
def search_web(self, query: str) -> str:
"""搜索某个话题的最新信息。"""
...
async def main():
agent = ResearchAgent(model="claude-opus-5")
result = await agent.run("NOOA 和 LangGraph 的核心差异是什么?")
print(result)
asyncio.run(main())
模型随便换:通过 LiteLLM 接入,Claude、GPT、Gemini、本地 Ollama、自托管 vLLM,同一套代码全都能跑。名字带 NVIDIA,但它不绑 GPU、不绑任何厂商。

第四章 两种执行策略与那个”扔掉压缩”的记忆
NOOA 内置两种执行策略,用途完全不同。
PredictStrategy:单次带类型的 LLM 调用,校验失败就本地重试。适合结构化抽取、分类这类”一问一答”的活。
CodeActStrategy:跑一个迭代式的 Python REPL,模型不断调用 execute_python(...),直到提交 return_result(...),返回值按注解校验。适合需要多步探索的复杂任务。
但真正让长任务 Agent 开发者眼前一亮的,是 nooa[memory] 这个扩展。
它给 Agent 一个带类型的关系型 SQLite 存储,并且按引用传递活对象——运行时递给模型的是一个”句柄”,而不是把整个上下文重新序列化一遍。
这意味着什么?大部分长时运行 Agent 都得外挂的那套”上下文压缩 / 摘要”流水线,NOOA 声称可以直接扔掉。如果你被 context 爆炸折磨过,这一条的分量你懂。

第五章 跑分怎么看:强,但别当排行榜
NVIDIA 公布的数字确实好看:
- SWE-bench Verified:82.2%
- CyberGym L1:86.8%
- ARC-AGI-3 平均 RHAE:85.1%
- 而且据称只用了对比开源框架约一半的 token
对一个 alpha 阶段的框架来说,这成绩很能打。NVIDIA 还把 LangGraph、Google ADK、PydanticAI、smolagents、Claude Agent SDK、OpenAI Codex、OpenHands 等 14 个框架放在同一套维度上打了分。
但请务必冷静。NOOA 是”外壳”(harness),不是模型。Agent 跑分永远是外壳和底层模型纠缠在一起的结果——换个模型,数字就变。SWE-bench Verified 尤其有个老毛病:任务来自热门开源项目,模型很可能见过。
更诚实的读法是:NOOA 靠 docstring 和类型注解把工具定义、提示词构造标准化了,减少了提示词的不一致性,所以结构化任务上更稳。它不是让模型变聪明了,是让你少犯错了。
真正该决定你选不选的,是你拿自己的任务、自己的模型跑出来的那个数。好在它就是普通 Python,这个测量成本低得离谱。
第六章 安全红线:这句话请抄十遍
NVIDIA 在 README 里写得非常直白,我原样搬给你:
AST 检查和模块黑名单,是纵深防御的护栏,不是隔离边界。
翻译成人话:NOOA 会执行 LLM 生成的代码。它内置的静态检查能挡住误伤,但挡不住一段主动想逃逸沙箱的代码。真正的隔离边界只有三个:容器、虚拟机,或者 NVIDIA OpenShell。
还有个更隐蔽的点:模型生成的代码跑在能触达 Agent 字段和方法的 REPL 上下文里。这既是它强大的原因(模型可以调用你写好的确定性方法,而不是自己蹩脚地重造一遍),也意味着爆炸半径 = 这个对象能碰到的一切。一个持有活数据库连接的类,就是一个连接随时可能被循环用掉的类。
实操建议,三条:
- 把对象暴露面收窄,别什么都往字段上挂。
- 不可逆操作全部放进确定性方法,写真实代码体,别让模型决定。
- 读 trace 再放宽权限。NOOA 内置追踪,每次模型调用、每次代码执行都默认记录——这是它比很多框架厚道的地方。
第七章 该不该现在上:一份取舍清单
适合现在就试的:
- AI 原生创业团队、中型平台团队做内部 Agent
- 企业 AI 平台组、应用研究组做评估和试点
- 典型场景:代码仓库 issue 分诊与修补、终端与基础设施自动化、漏洞验证流水线、大批量分类抽取、带类型的多 Agent 编排
建议再等等的:
- 受监管的生产负载——等稳定版,v0.0.x 就是 v0.0.x
- 真正复杂的分支多步工作流——这种场景图式框架仍然更合适,类继承结构反而是劣势,NOOA 没有让这个问题消失
- 只想最快出个 Demo——那用编排框架更快,NOOA 的价值在”能测、能追、能辩护”
最后说个我很在意的信号:NVIDIA 把这个项目贡献给了开放安全 AI 联盟(Open Secure AI Alliance),源码在 GitHub 上的 NVIDIA-NeMo/labs-OO-Agents,Apache 2.0。至少姿态上,它不想只做一个 NVIDIA 家的框架。
Agent 框架这两年出了太多,每一个都说自己解决了复杂度问题,然后每一个都变成新的调试摩擦源。NOOA 换了个思路:不在 Python 之上再造一层框架,而是让 Python 类本身成为框架。
这个赌注对不对,一年后看提交记录。但今天这个想法本身,值得每一个写过 Agent 的人认真想十分钟。
暂无评论内容