IBM 开源了 CUGA 智能体框架,它提供一套轻量级“工具带”,替你处理规划、工具调用和状态管理。开发者只需定义工具列表和提示词。文章通过 24 个单文件应用演示了 CUGA 如何让一个智能体从笔记本轻松迁移到生产级主权部署。
大多数智能体应用在真正干活之前,都得花上一周时间做“管道工程”:选框架、连接模型、写工具适配器、搭状态流到 UI,然后才想清楚这个智能体到底要干什么。有趣的部分总是最后才到。
CUGA 把顺序倒过来了。这个来自 IBM 的开源智能体框架替你处理规划、执行循环、工具调用和状态管道。你只需关注真正属于自己的部分:智能体能调用的工具,以及你给它的指令。为了展示实际效果,我们构建了 cuga-apps:24 个小巧可运行的应用,每个都是一个包含一个 CugaAgent 的 FastAPI 单文件,从电影推荐到 IBM Cloud 架构顾问应有尽有。它们就是拿来读和复制的。你可以 在线浏览演示画廊。
本文详细拆解其中一个应用,说明这个框架帮你省掉了哪些工作,并展示同一段代码如何在需要治理的生产环境中运行,而不需要重写。如果你写过 FastAPI 路由,就能读懂这里的每一行。
在这个领域,公平的问题是:它能帮你省掉多少代码?CUGA 的答案是:围绕 model 的编排工作——否则你每次都得重新搭。
它先规划再执行,结合工具调用和代码生成(CodeAct)。面对一个需要二十步的长时间任务,多数智能体会在中间结果丢失后重新推导(常常出错);CUGA 会保存状态并执行反思步骤,能捕捉到错误的调用并重新规划,而不是一头扎下去。正是这套机制让它登顶了 AppWorld 和 WebArena 等智能体基准测试,而不是靠手动调优。
你还可在配置中设置成本/延迟权衡:快速、平衡、精确三种推理模式,以及在你信任的沙箱(本地、Docker/Podman 或 E2B 云)中执行代码。同一个智能体定义,不同挡位。这个挡位比听起来更重要:大多数框架假设底层是前沿模型,靠模型自己在计划出错时恢复;CUGA 自己来做这件事。规划、反思、变量追踪让长程任务保持正确方向——这些工作本该由模型承担,现在由框架承担,这让一个小型开放权重的模型也能在它通常无法胜任的地方站住脚。托管应用运行在 gpt-oss-120b 上而非前沿 API,就是明证。运行你能调用的最大模型是常规做法;CUGA 的赌注是:一个小型开放模型就够了。
没有哪个单独的部分是 CUGA 独有的。差别在于它们已预先组装好,你只需配置而不必拼接。你接触的 API 很小——用工具列表和提示词构建一个 CugaAgent,然后 await agent.invoke(...)。那条线之下的所有东西都是框架。
具体来说,包括可互换的工具(OpenAPI、MCP 和 LangChain 函数都能以相同方式绑定)、带变量管理和自我修正的长期规划(背后是从 2025年7月到2026年2月保持 AppWorld 第1名、2025年2月到9月保持 WebArena 第1名的机制)、声明式防护栏、基于 A2A 的多智能体委托、由 Docling 驱动的 RAG,以及通过一个环境变量切换提供商(pip install cuga,然后 OpenAI、watsonx、Ollama 等都有支持)——每一件你原本都得自己造。名字的第一个词说明了重点:可配置;困难的部分都处理好了,你的工作就只剩下任务本身。
以下是 IBM Cloud 顾问——一个为架构推荐真实 IBM Cloud 服务的智能体。整个应用只有一个文件:main.py 包含智能体工厂、工具和提示词,外加一个小型 UI。
整个智能体就是这样的:
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:
"""搜索 IBM Cloud Global Catalog 获取真实 IBM Cloud 服务。
在推荐服务之前务必调用此工具以验证它们是否存在。"""
... # 调用目录 API,返回 JSON
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,它的 docstring 就是智能体决定何时调用它的依据。你只写自己的那个工具,其余的都借用别人的。
云顾问的提示词告诉智能体:在提及任何服务之前先搜索目录,推荐三到七个服务并说明每个在设计中的角色,绝不能编造服务名称。最后一条规则至关重要:一个推荐不存在的 IBM Cloud 服务的智能体比没有更糟,所以提示词强制每次推荐都先查目录。提示词写成有序步骤并明确“不要编造”的规则很有效;写成角色扮演的提示词则会跑偏。
这就是整个应用。一个工具、一个流程、四行构造函数。围绕它的 FastAPI 路由都是普通的网页代码:浏览器把问题发给 /ask,面板轮询 /session/{thread_id} 端点获取状态。没有数据库;状态是每个 thread_id 对应的 Python 字典,只有智能体通过工具才能写入。智能体在运行中调用工具的瞬间,面板就会刷新。UI 不是逻辑的第二副本,而是对智能体改变的视图。
有一个细节容易忽略,却至关重要:每个内联工具返回同一个小巧的信封。成功返回 {"ok": true, "data": {...}};失败返回 {"ok": false, "code": "...", "error": "..."}。
看起来像模板代码,其实不然。CUGA 的规划器能优雅地处理声明过的失败(“地理编码没返回任何东西,跳过那部分继续”),却会卡在未声明的失败上——原始堆栈跟踪在规划中间冒出来,整个运行就脱轨了。在所有应用中,那些运行可靠的应用,其工具从不向智能体抛出裸异常。一个乏味的约定,却是智能体是恢复还是摔跟头的区别。
上面的拆分只有在通用部分已经有人运行在别处时才有效。应用反复依赖的能力——网页搜索、维基百科/arXiv、地理编码和天气、金融报价等——存放在**7 个公共 MCP 服务器(36 个工具)**中,托管在 IBM Code Engine 上,无需认证。一个小桥自动解析它们的 URL,在线演示画廊 还提供了一个 MCP 工具浏览器,让你在将其接入智能体之前通过表单直接调用任意一个。
有 24 个打磨过的应用,其重要性超过任何一个单独的应用:一旦你读懂了云顾问,你就读懂了它们全部。它们共享同一个骨架——电影推荐器把 IBM 目录工具换成了 knowledge MCP 服务器,网页研究者几乎全靠 web——所以 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 将它们标记为 ready-to-ship、for-later 或 exploratory,默认显示 ready-to-ship;从云顾问或电影推荐器开始可以得到一个可工作的基线。
一个只搜索目录的演示智能体风险很低。把同样的模式用于写文件、执行 shell 命令或接触生产系统时,问题就变了:怎么阻止它做出让你后悔的事?
CUGA 在运行时而非事后加包装来解决这个问题。开源智能体自带策略系统,你直接将策略附加到同一智能体对象上:
await agent.policies.add_intent_guard(
name="Block force-push",
keywords=["--force", "--no-verify"],
response="Blocked: destructive git flags are not permitted.",
)
这就是意图防护(Intent Guard),六种策略类型之一,每种回答一个团队在放开智能体之前会问的问题:
第六种 CustomPolicy 是以上都不适用时的逃生舱。时机也很重要:意图防护在智能体选择工具之前检查请求;工具审批在智能体生成代码之后运行,检查代码使用了哪些工具;输出格式化只在最终消息存在时触发。触发器也不只是关键词匹配:它们存储在一个 sqlite-vec 存储中,通过语义匹配触发,所以策略基于用户的意图而非精确关键词触发。可基于语义相似性、智能体状态或某个工具被调用而触发。策略本身存放在构造函数中的 .cuga 文件夹里,与代码版本化在一起,而不是在单独的配置中漂移。
想看看工作示例,打开 Ouroboros——一个七智能体线索生成应用,在其监督者上绑定了三个策略(一个意图防护、一个工具引导、一个输出格式化),因此它是同一个文件中同时展示治理和多智能体架构的应用。
一旦应用超过了单个聊天循环,有两个扩展就很重要了。当一个智能体在自身上下文中淹没了(工具太多、要记住的证据太多),你就拆分工作。一个 CugaSupervisor 将任务委托给专门的 CugaAgent,每个都有自己的工具、提示词和独立的上下文,监督者只负责决定将子任务交给哪个专家。它的规划范围保持很小,不管下面有多少工具;一个出问题的工具只会导致一次委托失败,而不是整个运行失败。专家甚至不必是本地的;它可以是 A2A 上的外部智能体,同样方式委托。增加能力意味着增加一个专家,而不是重写协调者。
另一个扩展打包的是知识而非工具:智能体技能(Agent Skills),一个包含 SKILL.md 剧本的文件夹,只有当任务需要时才将其拉入上下文,因此一个提示词不必承载智能体可能需要的所有知识。两者都使用相同的积木(工具、提示词、状态、策略),只是组合层次更高。
之前的线索生成应用 Ouroboros 使这个模式具体化了。它有一个监督者和七个专家(侦察员、网站审计员、客户之声、人肉搜索、技术栈扫描器、收入估算器、综合撰写推销邮件的写手)。每个专家都是加载到 CugaAgent 中的一个技能,监督者通过自动生成的 delegate_to_<name> 工具调用它。增加第八个专家就是一行工厂代码,而不是重写协调者。如果你想详细了解多智能体架构,可以阅读它的 main.py 和 ARCHITECTURE.md。
还有第三个扩展,它指向技能本身。借助 ALTK-Evolve,CUGA 的在职学习框架,智能体从自己的运行中优化技能,使得今天完成的任务让明天的运行更快更准确。专家加载的 SKILL.md 最终包含了智能体在你写的内容基础上学到的东西。同样积木,只不过现在使用一个技能就是在教下一个。你不再需要每周再次提示已经解决过的问题。
治理在技术栈中的位置决定了生产化的故事如何展开。一个最小化的智能体库给你好的原语,然后把治理(策略、审批、审计、身份)留给你自己组装。CUGA 走了另一条路:策略、人工审批、.cuga 状态文件夹和自托管从一开始就是框架的一部分,而不是事后添加的层。
这改变了将智能体投入生产时的工作方向。你不是在为开放访问构建的系统上强行加入控制;控制平面已经存在。受治理的路径是默认的,不受治理的那些捷径才是你需要选择加入的。因此剩下的工作很窄:收紧仅有的几个实际触及外部世界的工具的沙箱,而不是发明围绕它们的治理。
这就是回报,也是这一切如此构建的原因。因为框架小巧、开源、模型无关且自带治理,你在笔记本上写的智能体就是将在锁定部署中运行的同一个智能体。你不必移植它。你重新部署它就行。
这就是 IBM Sovereign Core 所依赖的基础,也是我们下一步将 CUGA 带去的地方。我们另外写了详细说明,但简短版本是:Sovereign Core 在所谓的“边界隔离”下运行 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 # 设置你的 LLM 提供商和密钥;如果需要使用某些应用,添加 TAVILY_API_KEY / OPENTRIPMAP_API_KEY / ALPHA_VANTAGE_API_KEY
docker compose up --build # 首次构建较大(cuga + Chromium + MCP 依赖)
# 打开 http://localhost:8080
然后打开 apps/ibm_cloud_advisor/main.py 从头读到尾——这是内联工具加 MCP 模式最清晰的例子。修改系统提示词,添加一个工具,观察行为的变化。MCP 工具浏览器列出了每个托管工具并附带可直接调用的表单,这是在你将工具接入智能体之前检查管道的快捷方式。
所以试试看。pip install cuga,克隆 cuga-apps 并运行一个应用——或者先 点击浏览在线画廊。框架位于 cuga-agent,项目主页是 cuga.dev。如果出现问题、应用行为异常或你有想法,我们很乐意听到:开个 Issue、提交 PR、放入你自己的应用,或者直接联系我们——这个仓库就是用来添砖加瓦的,我们阅读每一条反馈。
pip install cuga)原文链接:Hugging Face
本文由前途科技编辑整理
免费获取企业 AI 成熟度诊断报告,发现转型机会
关注公众号

扫码关注,获取最新 AI 资讯
3 步完成企业诊断,获取专属转型建议
已有 200+ 企业完成诊断