技术解构 2026-10-28 24 分钟阅读 进阶

Cursor Agent SDK 解构:把智能体写成一个小软件项目

指令进 Markdown、工具进 TypeScript、评测进版本库 — 这套目录约定真正改变的不是智能体能力,而是「改一句提示词」这件事的成本与后果

摘要

2026 年 10 月 20 日,Cursor 发布 Agent SDK,把公司自用来构建 Bugbot、Security Reviewer 与 Rollouts 的内部框架对外开放。它的核心主张是一个位置上的挪动:智能体不再是一组仪表盘里的配置项,而是一个可以进版本库、可以走评审、可以跑测试的文件夹。项目结构固定在 bot/ 目录下,文件路径决定加载方式——instructions.md 是常驻系统提示词,tools/ 下每个 TypeScript 文件是一个带 zod 模式的类型化工具,subagents/ 下的子目录是带独立会话的子智能体,channels/ 与 schedules/ 决定它何时被唤醒,而 evals/ 独立于 bot/ 放在项目根部。本文拆开这套目录约定与它隐含的四类工程后果,辨析两处官方文档之间的命名出入与时间线出入,并给出五条原文没有直接写出的判断:发现式加载换来的是可发现性而非灵活性、host-connections 与 mcp-connections 的分离才是这套设计里真正的安全边界、hooks 被限定为只观察意味着拦截能力不在 SDK 层、以及「一天建成」的真实含义是脚手架而非智能体开发变简单了。

背景:智能体配置正在从仪表盘搬回仓库

过去两年,企业级智能体的搭建方式大致有三种:在低代码平台上拖出一条流程、在 SaaS 产品的设置页里填一段提示词、或者自己用脚本把模型调用与工具调用粘起来。三者有一个共同点——智能体的行为定义散落在版本控制之外。

这个共同点带来的代价是具体的。出问题时只能靠截图和手工复现来定位;工程师离职时,关于「为什么这个智能体会这样」的知识一并带走;改一句提示词之后,没有任何机制告诉你别的地方是否坏了。Cursor 在官方文档里把这一点讲得很直白:仪表盘配置的自动化活在版本控制之外,而 Agent SDK 把智能体的提示词、工具与测试用例都放进仓库,走拉取请求评审,并像其他系统组件一样积累历史。

需要说明的是两处文档的口径差异。官方博客标注发布日期为 2026 年 10 月 20 日,署名 Rustam Lalkaka,正文称「Agent SDK 今天正式可用(generally available today)」;第三方分析文章引用官方 changelog 时给出的 GA 日期为 10 月 23 日。两处都来自 Cursor 官方渠道而彼此不一致,本文并列标注,不作取舍。另有一处命名差异:博客称这套 harness 支撑的托管智能体为 Bugbot、Security Reviewer 与 Rollouts,文档中的表述为 Bugbot、Security Review、Approval Bot 与 Rollouts。差异不大,但读取时应知道存在两种写法。

Agent SDK 的形态:一个 bot/ 目录

官方文档给出的项目结构如下,evals/ 位于项目根部、与 bot/ 并列:

路径 作用 加载要点
bot/agent.ts 智能体配置,defineAgent,含 model 与 local 根智能体必填,模型与本地工作目录在此声明
bot/instructions.md 常驻系统提示词 根智能体上为必需项,缺则不通过校验
bot/tools/ 类型化工具,一个文件一个工具 工具名取自文件名,用 zod 声明输入模式
bot/skills/ 按需加载的流程说明 与工具不同,是程序性知识而非可执行函数
bot/mcp-connections/ 给模型看的 MCP 服务器、服务器工具与处理器 模型可见
bot/host-connections/ 给宿主代码用的 MCP 服务器与 mcp oauth 模型始终看不到这一层
bot/subagents/<id>/ 子智能体目录,含自身 agent.ts 与 instructions.md 必须带 description,拥有独立工具与会话上下文
bot/extensions/ 扩展或 Cursor 插件挂载点 贡献项会变成 <ns>__<name> 形式
bot/channels/ HTTP 路由,挂在 /v1/channels/<name> 事件入口,如 GitHub 拉取请求事件
bot/hooks/ 事件订阅者 官方限定为只观察(observe-only)
bot/artifacts.ts 产物类型、tag_artifact 开关与保留策略 产物与存储由平台托管
bot/schedules/、bot/reminders/ 定时触发的运行与具名提醒处理器 对应 cron 类场景
bot/sandbox/workspace/ 种子文件,会被复制进每个本地会话工作区 会话隔离下的初始状态
bot/lib/ 共享导入 明确标注永不被发现,不会被误当成工具
evals/ 评测套件,evals.config.ts 为必需 每个 *.eval.ts 为一个套件,用例 ID 来自路径

官方给出的最小配置示例只有几行:defineAgent 里声明 name、model(示例中使用 composer-2.5,参数含 effort 为 high、fast 为 true)与 local 的工作目录。也就是说,模型选择与运行位置是在代码里定死的,不在运行时由平台决定。

命名上有两条硬约束值得记下:当一台服务器托管多个智能体时,每个 slug 取自该智能体的目录名,必须匹配 [A-Za-z0-9][A-Za-z0-9_-]*,且不能是 v1、playground 或 docs——后三个被平台自身的路由占用了。这类细节在自托管多智能体时才暴露出来,提前知道能省掉一次排查。

🧵 一句话版本

Agent SDK 不是一个新算法,而是一套目录约定:把智能体的每一部分都变成文件,从而把版本控制、代码评审与回归测试这三件软件工程里最成熟的机制,原样搬到智能体身上。

目录即约定:发现式加载的四类后果

这套设计里最值得琢磨的是「文件路径即声明」。官方文档的原话是:文件放在 bot/ 下,每个文件的路径决定 Agent SDK 如何加载它。发现式加载(convention over configuration)带来的后果有四类,利弊并存。

其一,能力边界变得可枚举。官方提供两个命令:agent-sdk validate --dir . 输出诊断并在有错误时以非零码退出,agent-sdk info --dir . 列出被发现的全部能力面,加 --json 后与 GET /v1/info 返回同构。这意味着一个智能体「能做什么」不再是靠读提示词猜,而是机器可读的清单。文档还给出一条实用的排错经验:当 info 的输出里缺某个工具或 channel,原因是文件放错了目录或扩展名不对。

其二,错误的表达方式从报错变成静默。服务启动时遇到错误会拒绝启动,但警告不阻塞启动;无法识别的目录只产生一条校验警告。这是一个偏松的默认策略:好处是老项目不会被一次升级卡死,代价是拼写错误可能安静地躺在生产里。

其三,例外需要显式记住。文档里明确列出两个「不被发现」的位置:lib/ 用于共享导入、永不被发现;sandbox/workspace/** 是种子文件而非工具。官方 quickstart 里正好用到了这一点——两个工具都要解析拉取请求 URL,于是把解析函数放进 bot/lib/github.ts,注释写明「Agent SDK 不会在这里找工具」。开发者必须记住这两处例外,否则要么共享代码被当成工具,要么工具被当成普通文件。

其四,语法层面引入了迁移成本。文档显示安装命令为 npm install --global @grok/agent-sdk,并注明该包此前名为 @cursor/bdk;quickstart 中的导入路径与技能目录也随之变化(技能名写作 bdk-create-agent,目录为 skills/create-agent/)。文档还说明 Agent SDK 仍会加载以 agent/ 为根的旧项目。也就是说,这条产品线的包名与品牌仍在变动中,按文档写的代码在下一轮重命名后可能需要改导入路径。

确定性代码与模型判断的分界线

Agent SDK 对「什么交给代码、什么交给模型」有一条清晰的线,官方把智能体的行为描述为「把确定性代码与模型判断组合起来的 Markdown 与 TypeScript 文件夹」。工具是这条线的具体形态。

官方 quickstart 里的 PR 审阅智能体给了两个工具,两者的分工很能说明问题:

工具 由谁决定 行为 验证方式
inspect_pr 确定性代码 取拉取请求的标题、补丁,按行数与文件数算出 trivial / moderate / large,超过阈值时不再返回补丁并把补丁截断到 3000 字符 agent-sdk tool call 直接调用,不经过模型轮次
submit_review 模型判断 + 代码执行 按模型给出的 approve 或 request_human_review 结论,调用 GitHub API 提交评审意见 运行一次完整回合后在 GitHub 上查看结果

这里有一个容易被忽略的设计价值:复杂度的判定标准被写进了代码,而不是交给模型去感觉。rateComplexity 用 25 行 / 2 个文件、400 行 / 15 个文件两档阈值明确划分,模型读到的是已经算好的结论。这类「把可判定的部分钉死」的做法,正是智能体从演示走向生产的常见前提——它把模型的自由度限制在真正需要判断的环节上。

指令文件则承担了阈值之上的策略部分。quickstart 的 instructions.md 要求智能体在判断前先调用 inspect_pr,然后按复杂度分三档行动:trivial 档在差异与标题相符且看不出风险时批准;moderate 档仅在完全理解每一处补丁且看不到风险时批准,否则要求人工评审并点名担心的文件;large 档直接要求人工评审并指出最大的几个文件。此外还有两条硬规则:绝不批准草稿(draft),以及结尾必须给出一句包含结论与理由的话。

把这三档策略与上面两档阈值放在一起看,会发现一个有意思的不对称:复杂度阈值是硬的(25 行、400 行),而每一档里「有没有风险」仍是模型判断。这套设计并没有消灭不确定性,只是把不确定性收窄到了一个可枚举的集合里。

事件入口:channels、schedules 与 reminders

智能体何时被唤醒,由三类入口决定。官方博客列出的事件源包括 GitHub、GitLab 与 Bitbucket 的拉取请求事件、Slack 的提及与私信、任意服务的 webhook,以及用于周期性任务的 cron 调度;文档结构上则对应 channels/、schedules/ 与 reminders/ 三处。

quickstart 给出的 GitHub channel 是一个只有十几行的文件:githubChannel 里声明 bot 名称与作用的仓库范围,onPullRequest 回调里判断事件动作是否属于 opened / reopened / ready_for_review、拉取请求是否为草稿,不满足就返回 null 表示不触发,满足则返回鉴权方式、任务标题与上下文。这段代码的形态很能说明这套框架的取向——触发条件是显式的白名单,而不是「来了就处理」。

配套的重放命令是 agent-sdk github replay <pr-url> --dir . --action opened,只需拉取权限即可把一个已存在的拉取请求按 opened 动作重放一遍。它把「线上出了一次问题」变成「本地精确复现一次」,这是事件驱动系统里非常稀缺的能力,也直接决定了后面 evals 能不能落地。

子智能体、技能与两种 MCP 连接

上下文管理方面,Agent SDK 提供了三层机制,各有明确的适用位置。

子智能体位于 subagents/<id>/,每个子目录包含自己的 agent.ts 与 instructions.md,并必须带 description。官方博客描述其行为:对于更复杂的工作,智能体可以把任务交给另一个拥有自己工具与会话上下文的专门智能体,也可以把一项工作拆给并行运行的子智能体再等待结果。子智能体的价值在这里是上下文隔离——子任务的过程不会污染父智能体的对话历史。

技能位于 skills/,官方定义为「按需加载的流程(procedures loaded on demand)」。它和工具的区别值得强调:工具是可执行函数,技能是程序性知识。这与 2026 年主流 Harness 收敛到的 SKILL.md 形态一致,本栏目在 TanStack AI 1.0 的解构中讨论过同一趋势。

两种 MCP 连接是这套设计里最值得单独拿出来说的一点。文档把 MCP 连接分成两处:mcp-connections/ 下的服务器是给模型的,模型可以看见并使用;host-connections/ 下的服务器是给宿主代码与 mcp oauth 用的,官方原话是「模型永远看不到它们(The model never sees them)」。这条分离的意义在于:凭证、OAuth 流程、不希望进入模型上下文的管理类操作,可以放在一个结构性不可见的位置,而不是靠提示词要求模型别去看。quickstart 中的 ctx.host.github.getOctokit() 正是走这一层——智能体拿到的已经是一个可用的客户端,而不是一枚令牌。

evals 与事件回放:给改提示词装上回归网

Agent SDK 内置 evals 与事件回放,官方给出的理由是「在快速开发的同时确保关键工作流按预期执行」。evals/ 独立于 bot/ 放在项目根部,每个项目都需要 evals/evals.config.ts,每个 evals/**/*.eval.ts 是一个套件,用例 ID 由文件路径生成。

工作流是这样的:部署一个改过的智能体之前,先对一组固定输入跑 evals,确认这次改动带来的是改进,或者至少没有回退。PGA Tour 是被官方具名的企业用户,其首席工程师 Michael Gyarmathy 的引述里,被特意强调的正是「内置 evals 支持让我们能快速迭代新想法并可靠地优化现有能力」。

这里要给出本文的第四条判断:evals 的价值与它的覆盖面严格同界。evals 能挡住的只有你已经写下来的用例。quickstart 结尾给出的下一步建议正是把刚才那两个拉取请求变成回归检查——这说明官方推荐的用法是把每次线上遇到的具体案例沉淀成用例,而不是指望一份通用评测集覆盖全部风险。换句话说,evals 是一个会逐渐变好的机制,但它在启用初期是最弱的。

部署:单 Node 进程、托管与自托管

部署侧的两条路径与它们的约束如下:

维度 托管(Cursor 基础设施) 自托管(自有基础设施)
上线方式 在项目目录执行 agent-sdk deploy,从当前 Git ref 构建、分配 URL 并启动 把智能体打包成容器运行
运行形态 平台托管 单个 Node.js 进程
编排依赖 无需自建 文档称可运行在 Kubernetes、ECS 或任意容器运行时,无需特殊依赖
密钥与集成 在仪表盘中管理 由自有环境承担
可观测 日志、evals 与 playground 与本地开发时一致 需自行对接
合规约束 使用 Privacy Mode 的团队可用托管,享受与其他 Cursor 请求相同的隐私处理 仍在 Legacy Privacy Mode 的团队必须自托管

「从当前 Git ref 构建」这一条是不可忽略的设计:部署的产物与一个具名的提交绑定,这为审计与回滚提供了天然锚点。配合前面提到的评审与 evals,官方想传递的治理主张就完整了——智能体的变更要经过评审、有测试、并且从可追溯的提交发布。

本文推算:五条原文没有直说的判断

其一,发现式加载换来的是可发现性,不是灵活性。把「能做什么」变成机器可读的 agent-sdk info 输出,收益是审查与自动化;代价是能力的位置被目录结构定死,想把一段逻辑放在别处就得遵守例外规则(lib/)。这是一次典型的取舍,不是设计缺陷,但它意味着团队在组织代码时的自由度低于普通项目。

其二,真正的安全边界是 host-connections 与 mcp-connections 的分离,而不是沙箱。公开材料对沙箱的描述停留在架构图层面,而两层 MCP 的可见性差异是写进目录约定的结构性约束。对需要凭证与 OAuth 的企业场景,这一条比任何提示词层面的约束都更可靠。

其三,hooks 被限定为只观察,意味着拦截能力不在 SDK 层。想做「动作执行前的强制审批」,按现有文档只能把它写进工具内部(如在 submit_review 里判断),而不能指望一个统一的钩子。这会让拦截逻辑分散在各个工具里,需要在代码规范层面统一约束。

其四,「一天建成」说明的是脚手架完备,不是智能体开发变简单了。官方给出的 kb-reviewer 例子是:某团队用约一天时间建成一个把每个拉取请求与经验教训知识库对照检查的智能体,它会标出与既有决策冲突的改动并引用具体条目。这个速度成立的前提是事件源、鉴权、知识库接入、部署全部由框架提供;真正的工作量其实被前置到了「知识库本身是否够好」上——而这一步框架帮不上忙。

其五,工具里的阈值是在替代模型判断,也因此在限制上限。25 行 / 2 文件、400 行 / 15 文件这两档阈值让复杂度判定变稳定,代价是它们与具体代码库的实际风险分布未必匹配。对一个动辄上千行机械性改动的代码库,这套阈值会把大量本可自动批准的改动推给人工;反之对少量改动即可能引入严重风险的代码库,它又可能放得太松。阈值应当按自家仓库的历史数据重新标定。

尚未披露的部分

几项对工程决策有直接影响的信息,在公开材料中未给出:托管模式下的并发上限、单次运行的时长与 token 预算、失败重试与去重语义(同一事件被重复投递时如何处理)、artifacts 的默认保留时长与容量、自托管模式下日志与 evals 的接入方式、以及 @grok/agent-sdk 这一包名与 @cursor/bdk 之间的迁移计划与兼容期。GA 日期在官方博客与第三方引用的 changelog 之间存在 10 月 20 日与 10 月 23 日两种说法,本文已并列标注。目前官方及行业暂未披露更多细节,后续将持续跟进迭代动态。

采用前六问

  1. 先确认事件源是不是你已经有的。三处代码托管平台的拉取请求、Slack、webhook、cron——如果你的触发源不在其中,channel 需要自己写,收益会明显缩水。
  2. 把阈值当参数而不是常量。复用 quickstart 的两档复杂度阈值之前,先用自家仓库近三个月的拉取请求跑一遍分布,看分档是否合理。
  3. 凭证一律放进 host-connections。凡是模型不需要看见的,就别放在它够得着的地方;这条约束是框架免费提供的,不用可惜。
  4. 上线前先把一个真实故障做成 eval 用例。evals 在启用初期最弱,能加速它变强的主要办法是把每次线上问题沉淀进去。
  5. 拦截逻辑集中管理。由于 hooks 只观察,审批与熔断必须写在工具里,建议抽到 lib 下的共享函数并纳入评审清单,避免各工具各写一套。
  6. 先自托管跑一遍再决定托管。隐私模式的要求(Legacy Privacy Mode 必须自托管)与审计需求往往在合规评审时才暴露,提前验证容器化路径可以避免返工。

冷静判断:它改变了什么,没改变什么

它改变了智能体的维护方式。提示词、工具、评测、触发条件全部成为文件之后,智能体首次可以被当作普通软件来评审、测试与回滚。这条价值与模型能力无关,也不会因为换模型而失效。

它改变了凭证与上下文的默认安全姿态。两层 MCP 连接的可见性分离、子智能体的上下文隔离、从 Git ref 部署的可追溯性,这三处都是结构性而非提示词层面的约束。

它没有改变智能体本身的可靠性。框架提供的是回归网,不是更高的首次正确率。一个在 eval 集上表现良好的智能体,遇到集外情况时仍然会失败——XYEval 与 Δτ-Bench 这两份近期基准恰好说明,输入被误导或工具生态发生变化时,能力会明显下滑。

它也没有把治理问题做完。框架给出的是审计线索与可复现性,而策略本身(什么可以自动批准、什么必须人工、谁为结果负责)仍要由团队自己定义并写进指令与工具里。官方文档对并发、预算、重试语义的留白,也意味着生产级的限流与熔断仍要自建。

综合来看,Agent SDK 属于那种「不改变能力上限但改变犯错成本」的基础设施。对已经在用多个脚本与 webhook 拼装智能体的团队,把其中一到两个迁进版本库试试,成本很低而收益立竿见影;对还没有任何智能体在运行、指望靠一个框架一步到位的团队,它解决的是后面那一半问题。

核心发现

参考来源

  1. Cursor 官方博客 — Introducing the Agent SDK(2026 年 10 月 20 日,Rustam Lalkaka;含事件源清单、kb-reviewer 案例、PGA Tour 引述、agent-sdk deploy 与单 Node 进程说明)
  2. Cursor 官方文档 — Agent SDK(架构分层、与 Cursor Automations 和 Grok Bot 的适用条件对照、安装命令 @grok/agent-sdk 及其前身 @cursor/bdk、技能目录 bdk-create-agent)
  3. Cursor 官方文档 — Project layout(bot/ 与 evals/ 完整目录结构、各路径加载规则、slug 命名约束、validate 与 info 命令语义、lib 不被发现的说明)
  4. Cursor 官方文档 — Build a PR reviewer(instructions.md 三档策略、inspect_pr 与 submit_review 完整实现、rateComplexity 阈值、channels/github.ts 写法、github replay 命令)
  5. Enera — Cursor Agent SDK: Deploy Custom AI Agents as Code(2026 年 10 月 27 日;含五个 starter 模板清单、容器化部署说明、Privacy Mode 与 Legacy Privacy Mode 的自托管要求、changelog 中的 GA 日期 10 月 23 日)
  6. 本栏目 R-TECH-47 — TanStack AI 1.0 架构解构(2026 年 10 月 24 日;用于对照 Portable Agent Skills 与 SKILL.md 这一跨框架收敛趋势)