IBM 开源 CUGA:轻量级智能体框架,提供二十余个单文件示例应用
CUGA 把 agent 的规划、状态、策略等繁琐工程压缩成配置,开发者只写工具列表和 prompt 就能跑起 agent,配套的二十多个单文件应用是现成的模板库,对自建 agent 的团队来说省去了八成重复工作。
IBM 开源了 CUGA(Configurable Generalist Agent),一个处理规划、执行循环、工具调用和状态管理的轻量级智能体框架。开发者只需提供工具列表和提示词即可构建 CugaAgent。内置计划-执行-反思循环,在 AppWorld(2025年7月–2026年2月)和 WebArena(2025年2月–9月)基准上排名第一。支持 Fast / Balanced / Accurate 三种推理模式,代码执行可在本地、Docker 或 E2B 沙箱中运行。可互换工具支持 OpenAPI、MCP 和 LangChain 函数,通过环境变量一键切换 OpenAI、watsonx、Ollama 等提供商。随框架发布二十余个单文件示例应用,涵盖电影推荐、IBM Cloud 架构顾问等场景,每个应用仅需一个 FastAPI 文件。
使用 CUGA 构建真正的智能体应用:轻量级框架上的二十几个可运行示例
摘要——构建智能体大部分是管道工作:工具、状态、护栏、从单个智能体扩展到多个智能体。CUGA(`pip install cuga`),全称可配置通用智能体(Configurable Generalist Agent),是 IBM 面向企业的智能体框架,它替你处理这些,你只需编写工具列表和提示词。我们构建了二十几个单文件应用来证明这一点。在这里从头到尾阅读其中一个,然后看看同一个智能体如何无重写地以受管控和受治理的方式在生产环境中运行。
大多数智能体应用在智能体做任何有用的事情之前,先花一周时间做管道工作。你挑选一个框架,连接模型客户端,编写工具适配器,构建某种将状态流式传输到 UI 的方式,然后在这过程中你还得决定智能体到底用来做什么。有趣的部分最后才到来。
CUGA 颠覆了这一点。它是 IBM 的开源智能体框架,替你处理规划、执行循环、工具调用和状态管道。剩下的才是真正属于你的部分:智能体可以访问哪些工具,以及你告诉它做什么。为了展示这在实践中是什么感觉,我们构建了 `cuga-apps`:二十几个小型但可运行的应用,每个都是一个包装了单个 `CugaAgent` 的 FastAPI 文件,从电影推荐器到 IBM Cloud 架构顾问。它们的存在是为了被阅读和复制。你可以点击浏览实时展示页。
本文详细解析其中一个应用,指出该框架为你省去了什么工作,并展示当你需要以受治理的方式投入生产时,同样的代码会去往何处。无需先学习新框架。如果你写过 FastAPI 路由,你就能读懂每一行。
为什么是框架(harness),而不是框架(framework)
在这个领域,对任何东西的合理问题是:它让你免于编写什么?CUGA 的回答是:围绕模型的编排工作,否则你每次都要重新构建。
它在行动前先计划,然后通过工具调用和生成代码(CodeAct)的组合来执行。在需要执行二十步的长时间任务中,大多数智能体失败的原因是丢失中间结果的跟踪,并在下一轮重新推导(常常出错);而CUGA则保持这些状态,并运行一个反思步骤,能够捕获错误的调用并重新规划,而不是一味地向前推进。正是这种机制使其在AppWorld和WebArena等智能体基准测试中名列前茅,而不是通过手动调参来达到的效果。
你还可以通过配置文件而非代码来设置成本/延迟权衡:Fast、Balanced、Accurate三种推理模式,代码执行可置于任何你信任的沙箱(本地、Docker/Podman或E2B云)。相同的智能体定义,不同的旋钮。这个旋钮的重要性远超表面所见。大多数框架假设底层有一个前沿模型,并在计划偏离时依赖它进行恢复;而CUGA则自行完成这项工作。规划、反思步骤、使长时间运行保持正轨的变量跟踪——这些正是框架承载的负载,否则模型将不得不自己承担,这使得较小的开源权重模型在通常无法胜任的场景下也能坚持运行。这也是为什么托管应用运行在gpt-oss-120b上,而不是前沿API上。调用能调用的最大模型是常见的赌注;而CUGA的赌注是一个较小的开源模型就足够了。
没有任何单个组件是CUGA独有的。不同之处在于它们被预先组装好,因此你只需配置它们,而无需将它们逐一连接。你接触的API非常精简——用工具列表和提示词构建一个CugaAgent,然后await agent.invoke(...)。这行代码以下的一切都是框架。
具体来说,就是可互换的工具(OpenAPI、MCP 和 LangChain 函数都以相同方式绑定)、带有变量管理和自我修正的长周期规划(驱动 AppWorld 从 07/25 到 02/26 以及 WebArena 从 02/25 到 09/25 排行第一的底层机制)、声明式护栏、基于 A2A 的多智能体委派、由 Docling 驱动的 RAG,以及通过一个环境变量切换提供商(`pip install cuga`,然后可选 OpenAI、watsonx、Ollama 等)——每项功能都是你原本需要自己构建的东西。名字的首个词点明了作用:可配置(Configurable);难点已由框架处理,你的工作只剩下任务本身。
一个应用,从头到尾
下面是 IBM Cloud 顾问——一个能够为架构推荐真实 IBM Cloud 服务的智能体。整个功能都放在一个文件里:一个包含 agent 工厂、工具和提示词的 main.py,外加一个小型 UI。
整个 agent 就是这样的:
def make_agent():
from cuga import CugaAgent
from _llm import create_llm
return CugaAgent(
model=create_llm(
provider=os.getenv("LLM_PROVIDER"),
model=os.getenv("LLM_MODEL"),
),
tools=_make_tools(),
special_instructions=_SYSTEM,
cuga_folder=str(_DIR / ".cuga"),
)
四个参数。模型来自一个小型工厂(create_llm),它根据环境变量与 OpenAI、Anthropic、watsonx、LiteLLM 或 Ollama 对接。应用代码里完全不知道背后是哪个模型。cuga_folder 是此应用保存状态和策略的地方。承载应用的两个参数是 tools 和 special_instructions。
工具将本地函数与托管函数混合在一起:
def _make_tools():
from langchain_core.tools import tool
@tool
def search_ibm_catalog(query: str) -> str:
"""Search the IBM Cloud Global Catalog for real IBM Cloud services.
Always call this before recommending services to verify they exist."""
...
from _mcp_bridge import load_tools
web_tools = load_tools(["web"])
return [search_ibm_catalog, *web_tools]
这里有一个适用于每个应用的固定模式:MCP 工具与内联工具的分隔。通用、无状态的能力来自共享的 MCP 服务器;`load_tools(["web"])` 会拉取网络搜索能力,而你无需托管任何东西。任何特定于此应用的能力都以内联方式定义为普通的 Python 函数,比如 `search_ibm_catalog`,其文档字符串就是 agent 判断何时调用它的依据。你只需编写那个属于你自己的工具,其余部分借用即可。
云顾问的提示词指示智能体在提及任何服务之前先搜索目录,推荐三到七项服务并说明每项服务在设计中的作用,且绝不可编造服务名称。最后这条规则至关重要:推荐不存在的 IBM Cloud 服务的智能体比没有智能体更糟,因此提示词强制要求每项推荐都必须先经过目录查询。按有序步骤编写、包含明确“不许编造”规则的提示词表现良好;而基于角色设定的提示词则容易偏离主题。
这就是应用本身:一个工具、一个流程、四行构造函数。围绕它的 FastAPI 路由是普通的 web 代码:浏览器向 /ask 端点发送问题,实时面板轮询 /session/{thread_id} 端点获取状态。没有数据库;状态是基于 thread_id 的 Python 字典,只有智能体通过其工具写入。当智能体在运行中途调用某个工具时,面板会立即重绘。UI 并非逻辑的第二个副本,而是智能体修改过的状态的视图。
承担主要工作的约定
有一个细节很容易被忽略,却实际承担着关键作用:每个内联工具都返回相同的小型信封结构。成功时返回 `{"ok": true, "data": {...}}`;失败时返回 `{"ok": false, "code": "...", "error": "..."}`。
这看起来像样板代码,其实不然。CUGA 的计划器能够优雅地处理声明过的错误(例如“地理编码未返回任何结果,跳过该部分继续执行”),但遇到未声明的错误时就会卡住——原始堆栈跟踪在计划过程中冒出来,导致运行偏离轨道。在所有应用中,那些运行可靠的应用,其工具从未向智能体抛出未处理的异常。这是一个枯燥的约定,但正因如此,智能体才能恢复运行,而不是当场崩溃。
上述拆分之所以有效,是因为通用部分已经在某处运行。应用反复调用的能力——web 搜索、Wikipedia/arXiv、地理编码和天气、金融行情等——存在于部署在 IBM Code Engine 上的 7 个公共 MCP 服务器(共 36 个工具)中,无需认证即可访问。一个小型桥接器会自动解析它们的 URL,而在线展示区附带了一个 MCP 工具探索器,你可以在将其接入智能体之前,通过表单调用其中任何一个工具。
一个库,而非演示
之所以有二十多个精心打磨的应用,其意义远大于任何一个单独的应用:一旦你了解了云顾问,你就了解了所有应用。它们共享一个骨架——电影推荐器将 IBM 目录工具换成了知识 MCP 服务器,网页研究者几乎完全依赖网页——因此 cuga-apps 实际上是起点的目录。你克隆仓库,找到最接近你创意的应用,然后编辑它的工具列表和提示词(HOW_TO_BUILD_AN_APP_FAST.md 和 ADDING_AN_APP.md 详细介绍了这一点)。有些应用甚至是只给编码助手一个规格文件和一行的简短说明生成的——这种规律性足以让模型重现,也就意味着规律性足以让你学习。在克隆任何东西之前,你可以在实时图库中点击浏览每一个应用。
它们还分布在不同的类别中,因此无论你在构建什么,总有一个应用已经实践了你需要的部分。有一个研究集群(Paper Scout 按引用数对 arXiv 论文排序;Wiki Dive 和 Web Researcher 进行引用综合),一组日常生产力应用(城市简报、旅行、食谱、路线),一个文档和媒体组(对 PDF、音频和视频进行 RAG),一个监控实时指标的运维角落,以及一个基于真实 IBM 产品文档的企业示例。Ouroboros 是一个七智能体的线索生成系统;打开它以了解多智能体架构。Meetup Finder 通过 Playwright 驱动无头 Chromium,从 Meetup、Luma 和 Eventbrite(这些平台都关闭了公共搜索 API)提取结构化活动;打开它以了解浏览器自动化——这正是 CUGA 的起点,也是其强大 WebArena 成绩背后的力量。
在克隆之前有两个注意事项。真实的目录位于内部的 cuga-apps/cuga-apps/apps/ 目录中,而不是外层的那个。而且并非每个应用都同样精心打磨,因此 UI 将其标记为“可投入使用”、“待后续”或“探索性”,默认显示“可投入使用”;从云顾问或电影推荐器开始,以获得一个可工作的基线。
让你的智能体保持在边界之内
一个用来搜索目录的演示智能体是低风险的。把同样的模式用在会写文件、运行 shell 命令或接触生产环境的任务上,问题就变了:如何阻止它做出让你后悔的事?
CUGA 在运行时中回答这个问题,而不是在你事后添加的包装器里。这个开源智能体附带了一个策略系统,你可以把策略附加到同一个智能体对象上:
await agent.policies.add_intent_guard(
name="Block force-push",
keywords=["--force", "--no-verify"],
response="Blocked: destructive git flags are not permitted.",
)
那就是意图守卫,六种策略类型之一,每种策略都回答团队在让智能体投入使用之前会问的一个问题:
- 意图守卫——它能直接拒绝一个请求吗?
- 工具审批——它能在运行有风险的工具之前暂停并等待人工确认吗?
- 工具指南——我能否在不重写工具的情况下,引导某个具体工具的使用方式?
- 剧本——我能否针对一个重复性任务固定一个已知有效的流程?
- 输出格式化器——我能否强制最终响应符合某种要求的形状?
第六种类型 CustomPolicy 是当其他策略都不适用时的逃生口。时机的把握很重要,因为这不只是一个阶段:意图守卫在智能体选择工具之前检查请求,工具审批在智能体生成代码之后运行并检查该代码使用了哪些工具,而输出格式化器只在最终消息生成后才触发。触发条件也不只是关键词匹配:它们存储在一个 sqlite-vec 存储中并进行语义匹配,因此策略是基于用户的实际意图触发,而不仅仅是精确的关键词。可以匹配语义相似度、智能体状态或某个具体工具的触发。策略本身存放在构造函数中提到的 .cuga 文件夹里,与代码一起版本管理,而不是散布在独立的配置中。
以一个工作示例为例:打开 Ouroboros——一个由七个智能体组成的线索生成应用,它为其主管智能体附加了三个策略(一个意图守卫、一个工具指南和一个输出格式化器),因此这是同一个文件里同时演示了治理和多智能体架构的应用。
从一个智能体扩展到更多智能体。
当一个应用超出单次对话循环的规模时,有两种扩展方式变得重要。如果一个智能体会在自己的上下文中陷入困境(工具太多、需要保持的证据太多),就需要拆分工作。一个 CugaSupervisor 将任务委派给专门的 CugaAgent,每个 CugaAgent 都有自己的工具、提示词和隔离的上下文,而 Supervisor 只负责推理应将子任务交给哪个专家。无论底层有多少工具,它的规划面始终保持精简;一个有问题的工具只会让一次委派失败,而不是整个运行失败。专家甚至不必是本地部署的;它可以是通过 A2A 协议访问的外部智能体,以同样的方式被委派。增加一项能力意味着添加一个专家,而不是重写协调器。
另一种扩展方式封装的是知识而非工具:Agent Skills,一个包含 SKILL.md 操作手册的文件夹,只有当任务需要时,智能体才会将该手册拉入上下文,这样单个提示词就不必承载智能体可能需要了解的一切。两者都使用相同的构建模块(工具、提示词、状态、策略),只是组合层级更高一层。
之前的潜在客户开发应用 Ouroboros 让这个模式变得具体。它有一个 Supervisor 管理七个专家(侦察兵、站点审计员、客户之声、人员查找器、技术栈扫描器、收入估算器以及一个汇总并撰写推销邮件的专家)。每个专家都是一个加载到 CugaAgent 中的技能,Supervisor 通过一个自动生成的 `delegate_to_<name>` 工具调用该专家。添加第八个专家只需一行工厂代码,而不是重写协调器。如果你想了解多智能体架构的完整形态,可以阅读它的 main.py 和 ARCHITECTURE.md。
还有第三种扩展方式,它又回到了技能本身。借助 ALTKEvolve(CUGA 的岗位学习框架),智能体可以从自身的运行中优化一项技能,从而使今天完成的任务能让明天的工作更快、更准确。专家加载的 SKILL.md 最终会包含智能体在你编写的内容基础上学习到的东西。同样的构建模块,只是现在,使用一个技能的过程也在教会下一个技能。你不再需要对你上周已经解决的问题重新编写提示词。
由构造方式约束
治理在堆栈中的位置决定了生产环境的故事如何展开。一个极简的智能体库会提供良好的原语,而将治理(策略、审批、审计、身份)留给你自行组装。CUGA 则走另一条路:策略、人工在环审批、.cuga 状态文件夹以及自托管,从第一行代码起就是框架的一部分,而非后来附加的层。
这改变了将智能体投入生产时的工作方向。你不需要为原本为开放访问构建的系统 retrofit 控制措施;控制面已经存在。治理路径是默认路径,而未经治理的快捷方式才是你需要主动选择的。因此,剩下的工作就变得很窄:收紧围绕少数真正接触外部世界的工具的沙箱,而不是凭空发明围绕它们的治理。
同一个智能体最终落地的位置
这就是回报,也是所有东西如此构建的原因。因为框架小、开源、模型无关,并且已经自我治理,你在笔记本电脑上编写的智能体,与在锁定部署中运行的智能体是同一个。你不需要移植它,只需重新部署它。
这是 IBM Sovereign Core 所构建的基础,也是我们下一步将 CUGA 带向的地方。我们单独写了细节,但简短版本是:Sovereign Core 在我们所谓的边界隔离(Boundary Isolation)下运行 CUGA 智能体:数据、控制面和执行引擎都在同一逻辑边界内,智能体在租户自己工作空间内的临时隔离容器中运行。模型也在那里运行。部署默认使用完全气隙运行在你基础设施内的 gpt-oss-120b,工具仅能访问私有 VNET,且每个工具都需要审批。每个推理步骤都会发出 OpenTelemetry 链路追踪数据到租户内部的 Grafana Tempo 后端,没有遥测数据回传。没有任何东西离开边界。
智能体的定义本身无需改变;变化的是其周围的部署环境。而这一切之所以可能,正源于上述所有要素——能力、策略与模型选择都驻留在一个可读取的运行时中。这正是我们构建它时所押注的理念:当智能体的运行时是一个黑箱时,主权不过是一句承诺;但当运行时是开放代码时,主权便成为可验证的事实。你克隆的应用和你编写的智能体,都运行在同一个开放运行时之上,这正是这一主张的基石。
不过,对于开发者而言,核心要点不言自明。一个智能体应用可以只是一个你完全掌握在自己手中的文件。你真正需要编写的只有工具和提示词。这些应用是一套可供学习借鉴的库,而非封闭的演示。当风险升级时,治理机制已经内置于运行时之中——你无需重构智能体来确保其安全。
后续步骤
克隆仓库并运行一个应用。托管的 MCP 服务器意味着你无需第三方密钥,只需一个 LLM 提供商即可。本文中的应用运行于开源权重的 gpt-oss-120b 模型上——与托管画廊及我们 Sovereign Core 部署所使用的模型相同——但由于模型切换仅需一行代码(create_llm 读取单一环境变量),你可以将任何应用指向 OpenAI、Anthropic、watsonx 或本地 Ollama 模型,无需修改代码,且使用本地模型时完全没有 API 成本:
首先,查看我们的快速入门指南,点击此处。如果你想设置所有应用程序,请确保 Docker 正在运行,然后按照以下步骤操作。
git clone https://github.com/cuga-project/cuga-apps.git
cd build
cp .env.example .env
docker compose up --build
然后打开 apps/ibm_cloud_advisor/main.py 并从头到尾通读一遍——这是展示内联工具加 MCP 模式最清晰的示例。修改系统提示词、添加一个工具,然后观察行为的变化。MCP 工具浏览器列出了所有托管工具,并配有直接调用的表单,这是在将工具接入智能体之前快速检查连接是否正常的方式。
所以试试看。运行 pip install cuga,克隆 cuga-apps,然后运行一个应用——或者先直接点击浏览实时画廊。基础设施位于 cuga-agent,项目主页是 cuga.dev。如果出现问题、应用表现异常,或者你有任何想法,我们都期待你的反馈:提交 issue、发起 PR、放入你自己的应用,或者直接联系我们——这个仓库本就是为不断扩充而建,我们会阅读所有收到的反馈。
资源
- cuga-apps — 本文中的应用、MCP 服务器和用户界面
- cuga-apps/apps — 约二十个经过打磨的单文件智能体应用(内部目录;从此处克隆)
- cuga-apps/mcp_servers — 共享的 MCP 服务器(网络、知识、地理、金融、代码、文本……等),应用可调用它们
- 实时应用画廊 + MCP 工具浏览器 — 每个应用都配有启动按钮,外加一个可直接调用各托管 MCP 工具的表单
- cuga-agent — CUGA 运行环境与策略系统
- cuga.dev — CUGA 项目主页(pip install cuga)
- 开放设计:主权核心中的通用型与预构建智能体 — IBM 社区关于 CUGA 如何在 Sovereign Core 内运行的帖子(Srivastava, Marreed, Thomas,2026 年 4 月)
- IBM Sovereign Core — 产品页面
社区
· 或发表评论
