跳到主要内容

agent 的能力分发层:六个区、一张表、一个还空着的洞

全景
全景

· 阅读约 23 分钟

0 9 * * 1-5

这个 cron 表达式最近出现在一个我没想到会看到它的地方:一份 agent 应用的清单文件里。它声明“工作日上午九点触发一次站会机器人”。放在三年前,这个字符串只会待在服务器的 crontab 或者 systemd timer 里;放在一年前,它大概率在某个人的 Slack 提醒设置里;而现在它躺在 app.json 的定时任务字段里,和版本号、UI 入口路由、作者名挤在同一个文件里,成了“应用”这个概念的一部分。

我对这个位移的兴趣,远大于对那个站会机器人本身的兴趣。

先把边界划出来。这篇不写单篇精读——那是精读型写手的活;也不写怎么装 Kiro Crew——那是上手教程的活。这篇只画一张图:agent 的能力分发层。就是“某个人做出来一个能力”到“另一个人把它装进自己的环境里用起来”之间那一整层。这层东西现在什么形状、哪几块收敛了、哪几块还空着。

数了一下,这层至少要回答五个问题:

  1. 包里装什么——打包格式。一个能力的最小描述单元是什么。
  2. 什么时候加载进来——加载与触发。常驻上下文,还是按需展开。
  3. 工具怎么连上——连接层。能力活在别的进程里的时候,边界在哪。
  4. 活多久、谁管它——生命周期与调度。被调一次就死,还是有状态、有时间维度。
  5. 它被允许碰什么——隔离与权限。

再加一区:怎么让别人拿到它,分发与注册表。

这五个区加分发,就是这篇文章要走的六个区。走完压一张表,最后落一个判断。先给个预警:前三个区已经在收敛,第四个半通,第五个基本是空的——而我认为第五个才是决定这一层能不能长出生态的那一格。

一、连接层和打包层:这一层里少有的已经吵完了的地方

从最好画的那块开始。

连接层的谱系很清楚。起点是 function calling 和工具 schema——那时候“能力”就是一个函数签名:名字、描述、参数的 JSON Schema。没有包,没有边界,工具和模型跑在同一个进程里,共享同一个 context。

真正的分水岭是 MCP(Anthropic, 2024-11)。它第一次认真处理了“工具活在别的进程里”这件事:有传输层(stdio / HTTP),有 capability 协商,有 resources / prompts / tools 三类原语,有服务器和客户端的角色分离。2025 年之后主流厂商陆续接进来,再往后交给了基金会托管(这条我以公开公告为准,原始新闻稿的措辞我没去核)。MCP 的意义不在它设计得多优雅——它的早期实现被吐槽得不少——而在于它是这一层里第一个把“连接”标准化的东西。标准化之所以能成,恰恰因为连接不涉及信任:你的工具和我的客户端握个手,双方都不需要交出什么。

打包层的老祖宗不在 LLM 这一支里,在包管理器里。VS Code 扩展的 package.json 用 contributes 声明命令、菜单、视图、配置项,用 activationEvents 声明什么时候加载;Cargo.toml、各家浏览器扩展的 manifest.json,都是同一族的东西。Kiro Crew 的 app.json 是这个族的新成员:声明 name / version / displayName / author,然后在同一个文件里塞下 UI(入口 dist/index.mjs、路由 /apps/standup-bot、标签 Standups、图标 ClipboardList)、agent 定义、技能、以及那个 cron 表达式。

一个文件同时表达打包、调度、UI 三件事。好坏是同一件事:好处是应用的边界一目了然,读一个 json 就知道它要干什么、什么时候跑;坏处是它把三种完全不同的变更频率绑在了一起——改个图标、挪个触发时间、换个模型,走的是同一个版本号。这不是设计缺陷,是取舍,我倾向认为这个取舍在早期是对的:应用数量还少的时候,可读性比可维护性值钱。

短锚点:连接层和打包层是这张地图上仅有的两块已经钉死的地方。 后面的每一块都还在晃。

二、加载与触发:为什么 markdown 赢了,以及它赢的代价

这一支的具体样子很朴素:一个目录,一个 SKILL.md,frontmatter 里写 name 和 description,正文写规则,再随便加几个触发词。模型平时只看见 description 那一行,命中触发词才把正文全量读进来。不编译,不构建,不装依赖。

它的对手是“检索式工具选择”:把几百个工具的 description 做 embedding,用户问一句就召回 top-k 塞进 context。这条路 2023 到 2024 年很热,各家的动态工具加载、LangChain 的工具选择器都在这条线上。优点是规模无限,缺点是召回错一次后面全错。

为什么最后是“目录 + 触发词”这种看上去更笨的做法活下来了?我能给出的理由是:它的失败模式是看得见的。技能列表是确定的、可枚举的、用户能读的;向量召回的失败是静默的,你不知道它为什么没选中那个工具,也没法跟它讲道理。

但这个理由我说得没底气。在我读到的公开材料里,没有一篇干净地把两者在同等条件下的差异测出来——这块地图我没梳全,很可能漏了相关的一支,谁有更硬的证据可以来补。

触发词另一头的麻烦更大:它是字符串匹配和模型判断的混合物。standup、daily、summary、morning 这四个词,在“早上帮我看下今天有什么”这句里到底命中不命中?没人给你保证。技能加载是概率性的,而 manifest 是确定性的——同一层里一半是工程,另一半是提示词,两者的可靠性差一个数量级。

拿那个站会应用的 SKILL.md 当例子看。里面写的规则是:每条一行;按 feat 或 fix 归组提交;跳过 merge 提交和依赖升级;超过 24 小时没合并的标出来。

这四条不是知识,是一个团队的评审口味。把它写成文本、随应用分发、带版本,这件事真正的意义在于:团队的隐性约定第一次有了一个可安装的载体。以前这些约定散在 wiki 的某一页、某次 code review 的评论里、某个人的脑子里;现在它跟着应用走,谁装了这个应用,谁就拿到了这套口味。

但别把它吹过头。它说到底就是一段 prompt,只不过放在了一个能被别人安装的目录里。它能被测试吗?不能。能被静态检查吗?不能。改了一版之后怎么知道变好了?不知道。

短锚点:skill 这一支赢在零门槛,输在零保证。

三、生命周期与调度:cron 进了清单,可靠性没跟着进来

传统分层是这样的:应用不知道时间,调度是运维的事——crontab、systemd timer、GitHub Actions 的 schedule、K8s 的 CronJob。分层的道理很朴素,应用处理“做什么”,调度器处理“什么时候”,两者解耦,各自可测。

现在这套把它合了。应用启用时注册定时任务,禁用时注销,触发的时候起一个会话,把消息交给指定的 agent 执行。不需要常驻进程,不需要守护进程,不需要碰宿主机的 systemd。

收益是实打实的。一个应用带上了自己的时间维度——你装进来,它自己会长出运行节奏,宿主不用配任何东西。这对“团队级的小自动化”是巨大的降门槛。那个写教程的作者其实一直在做这一类东西,从他系列的前几部分能看出来:事故调查、每周重复性工作自动化、危险命令拦截,全是同一类需求,共同的痛点也都一样——要做的话,得有人先搭一条流水线出来。

保留意见在这一句:这套调度器的执行单元,和传统 cron 的执行单元,可靠性不是一个量级的。

cron 跑的东西是确定性的,至少目标是确定性的。失败了你重跑一遍,输出一样,你能排出差异。agent 会话不是:同一个任务连着跑两次,模型可能走不同的路径、花不同的时间、得出不同的结论。

传统调度器有一整套配套:幂等键、重试语义、dry-run、journalctl 里能翻出来的执行留痕。这套现在有什么?我从教程里看到的,是一个九秒读十一条提交得出站会纪要的漂亮演示。问题恰恰在这:演示成功和每天早上九点都成功,是两件事。

摊开说几种具体的塌方方式。如果九点那次没跑起来,谁告诉你?如果它跑起来了但输出错了——比如把一条 revert 当成 feature 写进“已完成”里——下午读到的人会发现吗?如果它连着一周输出同一份东西(因为那一周没人提交),你会注意到吗?

这套缺的不是“能不能跑”,缺的是执行的可观测性和幂等性。这是我在这张图上画的第一个红圈。我不觉得是设计者没想到,更可能是被“先跑起来”的优先级压过去了——这是所有早期基础设施都走过的路。

不过这里我得给自己踩一脚刹车,顺便推翻一下前面那个“可靠性不是一个量级”的说法。agent 任务里,“幂等”本身可能就是一个定义不清的目标。 cron 时代的幂等键依赖“同样的输入产生同样的输出”,而 agent 的执行路径里含采样,你没法给采样加幂等键。所以这块地图不是没人画,是它可能画不成传统那张图——需要的是一套新指标(允许两次输出不同,但要能判断哪次更好、哪次更差),而不是把 journalctl 抄一遍。这块我持保留,不是判死刑。写到这我发现我前面那句话说得太满了,留着不改,免得假装自己一开口就是对的。

短锚点:调度进了清单,配套没跟着进来。这一块现在半通,是整张图上最容易被高估的一块。

四、隔离与权限:地图上最大的一个洞

那篇教程里有一句话,我觉得是全篇信息量最大的一句:应用不是插件或脚本,而是拥有独立智能体、技能、定时任务和仪表盘页面的完整应用。

这句话在说的是边界。把“隔离”拆成四层看,能看清它说到哪、没说哪。

第一层,依赖隔离:应用有自己的目录结构、自己的清单、自己的版本号,和宿主不共享构建产物。 第二层,状态隔离:每个应用有自己的会话上下文、自己的仪表盘数据。 第三层,版本隔离:可安装、带版本、可发布,生命周期由宿主统一管。 第四层,权限隔离:空着。

前两层是目录和命名空间的事,工程上不难,看起来是做了。第三层用最朴素的做法就够(清单里写版本号,宿主记录已启用列表),也做了。第四层没有。

我能找到的相关机制只有一个:~/.kiro/crew/config.json 里把 apps_allow_third_party 设成 true。这是一个二元开关。它回答的是“能不能装第三方应用”,不回答“装了之后它能碰什么”。

而一个 agent 应用能碰什么?回头看那个示例的 agent 定义:它引用了 @kirocrew-core 工具,于是具备了启动进程、读文件、和系统交互的能力;model 设成 auto,让宿主挑当前可用的最好的模型。

一个从公共注册表一键装进来的东西,手里攥着起进程的钥匙。这个组合在我这里是需要停一下的。

成熟生态在这块都有对应物,而且长得都不一样。VS Code 扩展模型有 contributes 声明,但真正危险的能力(文件系统、终端、网络)靠的是扩展宿主进程那道物理边界加上市场侧的扫描,粒度其实也粗;浏览器扩展在 manifest 里写 permissions,用户安装时能看到清单,运行期还能细粒度申请;移动端走 entitlement,签名绑定,平台审核。这三家没有一家是靠一个 boolean 解决的。

我怀疑真正的卡点在于,agent 应用的权限没法静态声明。功能型扩展的权限是一个能力集合——我要用摄像头,我要用本地存储,现在就能写下来。agent 的权限是“我要读你的文件”,但读哪个文件取决于它运行时被喂了什么 prompt、被哪个上游输入带到了哪一步。静态声明不出来,只能运行时管;而运行时管需要一层能理解语义的策略——现在没有这层东西。

所以我说权限那一格空着,意思不是没人提这件事,是这块的答案很可能不在 manifest 那一层,得往上走一格。

这里有个细节值得单独拎出来。那个作者的系列里有一个应用叫“危险命令拦截”——一个应用专门用来拦危险命令。这既是好事也是症状。好事是有人在填这个洞;症状是,这件事被做成了应用层的一个可选组件,而它应该是宿主层的一个默认能力。你在应用层拦危险命令,等于让每个装应用的人自己去决定要不要装一层护栏,而护栏本身也是第三方应用,它凭什么可信?这不是作者的错,是我对这条线最主要的怀疑:信任如果要靠装一个应用来解决,那它就不叫信任。

短锚点:装得越容易,权限越不能是一个 boolean。这一格空着,后面的生态就长不厚。

五、分发与注册表:git 仓库当 registry 已经赢了,跨厂商没戏

这一支的谱系短,但节奏快。

起点是 GPT Store(2024 年初),中心化目录,能力是配置好的 GPT。它的特点是能力不落地——装进来的是提示词和配置,跑在别人的机器上。这是另一种架构,不与本地执行这一支竞争,顺带说一句它后来没长成很多人期待的样子,原因和权限、和收益分配都有关,这里不展开。

然后是 plugin marketplace 那一系(2025 年下半年):一个 git 仓库加一个 json 文件就是注册表,里面列条目、指向仓库和分支,用户加一个 marketplace 地址就能装。Git 仓库即 registry——这个解法的好是它便宜到没有对手。

Kiro Crew 走的是同一条:向 app-registry.json 提 PR,合并之后应用出现在所有用户的 Explore → Library 里,和内置应用并列。团队还可以自己搭私有注册表,托管不适合公开的内部应用。

私有注册表这一笔值得单独说。它说明设计者想到了企业的真实需求——企业内部应用的第一个障碍从来不是“做不出来”,是“没法分发”。发压缩包、写 README、让每个人自己照着装,这件事在任何超过二十人的团队里都活不过三个月。

判断锚点:注册表的实现形式已经收敛,“git 仓库 + 一个条目列表”是这一层最便宜的解法,我看不出还有什么能把它替掉。

但另一件事在往回走:一个编排器,一个注册表。 MCP 花了一年多,把工具接入标准化成一套 transport 加 capability 协商,主流厂商都接了进来,好容易在这一层做出一点互操作性。然后上一层按宿主切成了互不相认的目录——A 家 marketplace 里的东西装不进 B 家的编排器,B 家 App Store 里的东西 A 家也读不了。

这不是谁的错。应用里声明了 UI 页面、SDK 调用、宿主提供的工具,这些东西本来就与运行时强绑定。换个宿主,useAppApi 这个 hook 不存在了,页面就废了。

能跨宿主的是下面几样:agent 定义(本质是一段 prompt 加一组工具引用)、技能(一段 markdown)、调度声明(一个标准的 cron 表达式)。跨不了的是 UI、SDK、宿主工具这三样。

所以我的判断是:这一层的分裂是结构性的,不是阶段性的。能跨的那小半会慢慢沉淀成一个事实标准,跨不了的那大半永远是各家自己的。想通这一点,就不会再问“什么时候能有一个统一的 agent App Store”——那一天不会来。更可能长出来的是“底部统一、顶部各花”的两层结构。这件事有先例:LSP 就是一堆编辑器在语法高亮和跳转定义上找了个公约数,然后在各自那一层接着打。

这条判断我给不出出处,它是我从这几家的形态倒推出来的。你可以拿反例来挪这块坐标。

六、纵切一刀:拿那个站会机器人走一遍

前面六个区都是横着切的。现在竖着切一刀,看一个真实应用怎么同时踩在这些块上。

示例叫 Daily Standup Bot,五个文件,作者说大约五分钟写完。目录是:app.json、agents/ 下的 agent 定义、skills/standup-format/SKILL.md、ui/src/App.tsx。

逐个对上去:

app.json 对应打包层加调度层加 UI 声明,三块挤在一个文件里,前面说过了。

agents/ 下的定义里有两行值得单拎。一行是 model: auto,把模型选择权交给宿主。我觉得这是清单设计里少见的、主动放弃控制的好决定:应用作者不该绑定具体模型,因为一份清单的寿命比模型长得多,今天写死的模型名,明年就是技术债。另一行是 @kirocrew-core,一把万能钥匙,上面说过了。

SKILL.md 对应加载层。四条格式规则,命中触发词才加载。

ui/src/App.tsx 对应 UI 层。React 写的,从 @kirocrew/app-sdk 引入 useAppApiuseAppEvents 和一批组件;关键是开发者不用 npm 装这个 SDK,仪表盘在运行时提供它,所以应用体积能做得很小。UI 用 Vite 构建,把 SDK 标成 external,最终输出单个 .mjs 文件。

这一段我不打算挑毛病。运行时提供 SDK、构建时标 external、输出单文件——这套模式在 Figma 插件、编辑器 webview、各家浏览器扩展里已经练过很多遍,成熟、便宜、可靠:宿主提供 API 层和渲染容器,插件只出业务逻辑。为显得有观点而硬挑一个,不诚实。

执行那一段值得想想。手动触发,agent 跑 git log --since=24 hours ago --oneline --no-merges,逐条分析十一条提交,九秒,输出三节:已完成、阻塞项、后续计划。

九秒读十一条提交,这个数字本身说明它没做多深的事——读 message、归类、写摘要。这不是缺点,这就是这类应用该有的规模。我想指出的是另一件事:这个示例选得非常好,因为它选了一个最容易的例子。

为什么说容易,三条。commit message 是结构化程度最高的文本输入之一:有约定式提交的规范(feat / fix / chore)、有作者、有时间戳、有 diff 兜底。要验证输出对不对非常简单——对着 git log 看一遍,有现成的 ground truth。失败的代价天然低——生成了一份烂纪要,明天再来一次,没人损失什么。

换成那个作者顺手列出的其他构想,难度就跳了:PR 审查机器人要对着一份 diff 判断“这个改动有没有风险”,ground truth 在评审者脑子里;成本异常告警器要判断“这个涨幅是不是正常”,需要历史基线;事故复盘生成器更狠,它要处理的东西——事故发生时的对话、当时的临时决策、为什么当时那么选——大部分根本没留在系统里,只在人脑子里。

我不是说这些做不了。我是说,站会机器人这一支能走得通,很大程度是因为它的输入天然干净、输出天然可核对、失败代价天然低。把它的成功当成“agent 应用这一层已经走通了”的证据,会推得太快。

短锚点:这个示例证明了管道通了,没证明难的任务也通。

七、回看全景:压成一张表和一课树

把六个区摊开对照。

要回答的问题现在的答案收敛程度代价
连接层工具怎么连上MCP:传输层 + capability 协商已钉死description 常驻占 context
打包层包里装什么manifest(json)+ 组件目录已钉死三类变更绑同一个版本号
加载层何时进上下文skill:markdown + frontmatter + 触发词正在收敛概率性加载,不可测不可查
调度层活多久、谁管清单内声明 cron,宿主统一注册/注销/触发半通幂等、可观测、失败通知全缺
权限层能碰什么一个 boolean 开关空着第三方应用带起进程的钥匙
分发层怎么让别人拿到git 仓库 + 一个条目列表已钉死,但互不相认每个宿主一个 registry

再画一棵树,把这层的关系摊平:

agent 能力分发层
├── 连接层    MCP(传输 / capability 协商)             ← 已标准化,不涉及信任
├── 打包层    manifest(app.json / package.json 族)     ← 已收敛
├── 加载层    skill(markdown + frontmatter)            ← 事实标准正在形成
├── 调度层    清单内 cron + 宿主注册                     ← 半通
├── 分发层    registry(git 仓库 + 条目列表)            ← 已收敛但互不相认
└── 权限层    ???                                        ← 空着

横着看一条规律,我认为是整张图里最值得记住的一条:越靠近“能力本身”的部分,越早标准化;越靠近“信任”的部分,越晚。 MCP 能标准化连接,因为连接不涉及信任,谁都不需要交出什么;权限标准化不了,因为权限就是信任,而信任没有中立解,只有各家自己愿意承担多少风险。

再叠一条时间轴。2023 年在函数调用和工具 schema,2024 年在 MCP,2025 年 skill 和 marketplace 从两头夹,2026 年往“应用”这个粒度上走。重心从“模型能不能用工具”移到了“能力怎么被分发”,这个位移这两年一直是单向的,没回过一次头。

还有一条观察,不大但我觉得挺说明问题:这套东西用的词汇在往运维那边靠。包、清单、注册表、版本、安装、启用、定时——这些词不是从 LLM 那边借来的,是从包管理和系统运维那边借来的。这不是巧合。这一层正在从“提示词工程”变成“软件分发”,词汇是最先变的那个东西,比架构变得还早。

八、落子

摊开这张地图,我的落子是这样。

现在的坐标:连接层和打包层已经钉死,加载层正在收敛成一个事实标准(markdown + frontmatter 这一套),分发层的实现方式收敛了但生态是碎的,调度层半通,权限层空着。一句话概括——这一层现在站在“形式已经定了、信任还没有”的阶段。

三块空着的地。

第一块,权限模型,缺得最狠。我甚至不确定它的答案是不是一个 manifest 字段。它可能需要一层运行时的策略组件,能读懂上下文、判断“这次调用该不该放行”,而不是把浏览器的 permissions 抄一遍——因为 agent 的权限是语义相关的,不是能力枚举的。

第二块,可靠性。幂等、重试语义、dry-run、失败通知、执行留痕。现在这套把 cron 的语法拿过来了,没把 cron 的配套拿过来。

第三块,跨宿主的最小公约数。我上面说分裂是结构性的,但“结构性”不等于“无解”——能跨的那小半(技能、提示词、调度声明)值得有人认真定一个公约数,把 LSP 那个剧本再演一遍。

我具体的落子是:下一颗钉子最可能钉在“权限 + 可观测性”这一格的交叉口。理由很朴素——生态要长,得先有人敢装。现在不装的理由通常不是“用不上”,是“装进来一个能起进程、能读文件的东西,出事了我不知道找谁,也说不出它到底干了什么”。这两件事是同一件事的两面:一个要事前定边界,一个要事后留痕。

顺手说一个不在主线上、但我觉得和这张图有关联的细节。那篇教程的评论区有人提议把每次修复做成“模式”存进一个 lesson 系统,另一个评论者提醒得对——存的时候要连着原始信号、适用范围和失效条件一起存,否则一个过时的临时方案会慢慢变成默认做法。

这件事的性质和整张图是同一个:把一次性的东西固化成可复用的东西,只不过固化的是经验而不是代码。而这条路上最老的坑就是——被固化下来的东西不会自己过期。你的 prompt 里、规则文件里、lesson 库里堆的每一条,都曾经有用过。这不是 agent 特有的问题,是知识工程的老问题。只是它的载体变了:以前过时的一页 wiki 没人看,现在 skill 里过时的一条会被每一次命中触发词的调用读进上下文。载体换成了会被自动加载的东西,同一个坑就深了一截。

回到那个 cron 表达式。

评论区那位读者说得比我一开始想的更对:站会应该聚焦“还需要做什么”以及“人们怎么互相解除阻塞”,而不是汇报昨天干了什么。作者的回答是标准答案——让 agent 自动处理“发生了什么”,腾出时间讨论协作和规划。

这个回答没错,但它绕开了一件事。那三节输出里,已完成和后续计划能从 git log 推出来,阻塞项推不出来。阻塞不在提交里,阻塞在人脑子里、在聊天记录里、在那个“我等你回一句话就能继续”的地方。而恰恰这一节,是最需要人开口的。

所以我的判断是:这个 bot 会把站会从“念昨天做了什么”里救出来一半,另一半它够不着。自动化最容易自动化的那部分,正是这一层现在整体的状态——不是缺陷,是位置。

位置会挪。但得等权限和可靠性那两块补上,才能挪到更难的那半边。

这是我的判断,不是共识。你不同意,可以拿论文、拿实现、拿一个跑挂了的例子来挪这块坐标。地图我随时重画——交稿那天它就开始过时了。

全景
全景

选一个技术领域万字横扫:多论文多技术系统梳理成一张全景地图,最后落判断。

查看主页 →