模板
从模板中心、命令行,或者你自己 agent 的终端里,装进一个完整的应用——表、界面,以及 agent 动你数据之前要读的那份手册。
模板是一个可以整体装进 space 的、能用的应用:它的表、它的界面、它的示例数据,还有让它区别于"一堆表"的关键部分——作者为 agent 写的那份手册。装一个模板进来,你的 agent 不需要你先解释一遍 schema,就已经知道该怎么动手了。
从机制上说,模板是一个 package,同时也是一个 Agent Skill。同一个目录里,根部的 SKILL.md 与 busabase.json、content/ 并排放着:
busa-email/
├── SKILL.md ← agent 读的那份手册
├── references/ ← 跟着它一起走
├── busabase.json ← 清单,多了一个 `template` 对象
└── content/ ← 一棵普通的 busabase-package@1 树content/ 底下的一切与普通包逐字节相同。这带来三个值得先知道的结论:
- 一个模板目录本身就是合法的包——
busabase-cli install一直都能装它,只是不会落下手册、不会盖归属戳、不会合并示例数据。 - 任何包只要加上根部的
SKILL.md和一个template对象,就变成模板。 不用迁移,也没有格式 v2。 - 没通过模板校验的包永远不会被拒绝安装——它会按普通包安装,跟模板出现之前完全一样。
两个入口,同一批资源
进入你 space 的门有两扇,用哪一扇取决于人当时在哪里:
| 你的起点 | 谁在装 | |
|---|---|---|
| 模板中心 | Busabase 网页端 | 服务端拉取仓库并应用这个包 |
| 你 agent 的终端 | Claude Code、Codex,任何支持 skill 的 agent | 这个 skill 自己的 scripts/setup.mjs,经由 busabase-sdk 走 API |
两条路创建的是同一批资源,并且都会在它们创建的每个节点上写下同一枚归属戳——节点 metadata 里的 appId、一个稳定的 resourceKey、一个 schemaVersion。这枚戳是两扇门互相认得对方成果的唯一依据:你先从画廊装了模板,再在终端里跑同一个 skill,它会找到自己的 Folder 和自己的表,而不是再建一份副本。(万一两边的戳对不上,skill 会以 SETUP_CONFLICT 拒绝动它无法证明属于自己的数据——见模板格式。)
逛模板中心
侧边栏里的模板就在动态和"从 GitHub 安装…"旁边,打开的是你当前所在 space 的模板画廊。
画廊是一格一格的卡片。每张卡片有一张截图(作者没提供就是占位图)、名字、分类徽标、描述,以及一行算出来的数——"3 tables · 1 app · 7 sample rows"——这些数是从包本身读出来的,不是手写的。搜索框按名字、描述、分类和标签过滤。右上角那个链接是这份目录所属的仓库,你随时能看清自己在看谁的模板。
点开卡片是详情页,顺序按人真正拿来做决定的东西排:
- 截图——它长什么样。
- "装好之后你可以让 agent 做什么"——作者预置的提示词。它是对*"那我到底该问它什么"*这个问题最简短的诚实回答;它成立的前提,是模板把手册和表一起装了进来。
- "安装会创建什么"——表、应用、文档、示例行、文件,以及是否附带 agent 手册。
- 阅读源码,外加许可证和作者。
浏览对所有人开放;安装是 space owner/admin 的操作。 模板可以带 AirApp 和 Skill——那是这个 space 的 agent 会真正执行的代码——所以服务端在预览和安装两步都校验角色。成员看到的是卡片,加上一句说明谁能安装,而不是一个点了没反应的按钮。
目录由服务端拉取,不是你的浏览器,并缓存一小时。拉不到时你会看到红色的原因——"Could not reach the template catalog at …"——因为空画廊和坏画廊在人眼里长得一模一样,而只有其中一种是你能采取行动的。
画廊在演示工作区里同样可用:目录列的是公开仓库,和你的数据无关。安装则不行。
装一个
详情页上的 Install 打开的是侧边栏那个同一个 从 GitHub 安装… 对话框,只是预填好了模板的仓库 URL 和目标 Folder 名。这种复用是刻意的:浏览和安装绝不能对"这是什么包、谁能装、会创建什么"产生分歧——而只要你确认的预览就是同一份预览,它们就不可能分歧。
所以三步还是 安装与导出 里那三步:URL → 预览 → 确认。变的是服务端认出这是模板之后所做的事。
模板安装与普通包的差别
| 普通包 | 模板 | |
|---|---|---|
作者的 SKILL.md | 留在仓库里 | 作为 Folder 内的 Skill 节点装进来,连同 references/、agents/、scripts/ |
| 节点 metadata | 没有 | 在根 Folder 和它创建的每个资源上写归属戳 |
| Base slug | 作者写成什么就是什么 | 加上目标 Folder 前缀——settings 变成 busa-email-settings |
| 示例数据 | 提交审核 | 安装时直接合并,这样你打开时应用不是空的 |
| AirApp 代码、Skill、Drive | 提交审核 | 提交审核——不变 |
slug 前缀的存在是因为通用名会撞车:两个模板都带一张 settings 或 contacts 表的话,你装第二个的时候就会为这个名字打架。指向被加前缀的 Base 的 relation 字段会同步改写,已经带前缀的 slug 不会被叠加第二次。
合并示例数据是让*"装完就能用"*这句话成真、而不只是愿景的那一步——但这也正是格式把它限制在每张表 50 行的原因。合并进来的行会触发 webhook 和自动化、会进入提交历史、会被 agent 当作真实数据来读。模板是播一颗演示的种子,不是发一份数据集。
记录里带 relation 值的包通常必须 --auto-merge,因为 relation 存的是它所指向那些行的 id,而这些 id 只有在行被合并之后才存在。模板会自己合并示例数据,所以这条限制对模板不触发。
结构立刻建好,会跑的东西等你审完
安装与导出 里的规则依然成立,而且这是最容易让人意外的部分:
- 立即创建: Folder、Base 及其字段和视图。待审核的 Base 没有 id,没有 id 就无处安放视图、字段和行。
- 立即合并(仅模板): 示例数据。
- 等你审核: AirApp 的源码、承载手册的 Skill 节点、Drive,以及所有文档。
所以刚装完通常会停在*"3 change requests are waiting for you"*,并给出一个通往收件箱的链接。在你合并它们之前,表已经在了,但应用跑不起来,而且 agent 读不到手册——Skill 节点还不存在。
从命令行安装
npx busabase-cli install https://github.com/busabase/templates/tree/main/busa-email安装页上的一切都适用。对模板来说有两个 flag 值得注意:
| Flag | 作用 |
|---|---|
--skill <name> | URL 指向的是一个装着好几个包的仓库,而不是一个包。CLI 会列出它找到的东西——模板排在前面、逐个标注,凡是自称模板却没通过的都会连原因一起列出——然后你挑一个 |
--no-sample-records | 把示例数据改为提交审核,而不是直接合并 |
--skill 只有 CLI 有。网页端对话框要求 URL 本身就是一个包,所以请粘贴完整的 /tree/<ref>/<subdir> URL——模板中心卡片交给它的正是这个。
先跑 --dry-run。URL 里的 git ref 就是版本锁:用 tag 装的就永远是那个 tag 的内容,哪怕分支后来又往前走了。
装完之后
1. 审掉待处理的东西。 打开收件箱读那些变更请求——最重要的是 AirApp 的源码和那份手册,因为前者是会跑起来的东西,后者是你的 agent 会照着做的东西。合并了,应用才真的成立。
2. 让 agent 指过去。 Skill 节点合并之后,通过 MCP 连上来的 agent 自己就能找到它:
| 调用 | 回答 |
|---|---|
busabase_guide,topic 为 apps | 这个工作区里装了哪些 app,各自的 slug 是什么 |
busabase_guide,topic 为 skill:<slug> | 那个 app 的 SKILL.md 全文,以及它的 references/ |
会话指令会要求每个 agent 在动某个 app 的数据之前先查 apps,原因很直接:一个 app 已经写清楚的 schema 还要去猜,正是数据写错表的由来。这份清单做成一次工具调用、而不是塞进指令里的一段文本,是为了让一个装了四十个 app 的工作区,不必在每次会话里为另外三十九份无关手册付费。
3. 用作者写好的提示词。 详情页上那几条就是他给的起点——写它们的人知道这个应用是干什么的。
模板目前还做不到的事
在你围绕它做规划之前值得知道:
- 没有升级路径。 目前还没有
install --upgrade。根 Folder 的戳记录了它来自哪个仓库、哪个 ref、哪个版本,这是将来能提供升级的前提;但今天要装新版本,意味着装进另一个 Folder。 - secret 是声明的,不是创建的。 模板的
secrets和vaultNamespace告诉你这个 app 期望的 Vault 键有哪些。包格式里没有存放 secret 值的位置,也不该长出这样一个位置——所以要你自己填,而且安装当前不会提示你去填。 - 安装不会打开应用。 主 AirApp 在模板校验时就已经解析出来了,但安装流程停在变更请求汇总页,不会停在一个跑起来的应用上。
相关
- 安装与导出(packages)——模板所扩展的格式,以及它复用的那个安装对话框
- 模板格式——一个模板目录里有什么,校验器管什么
- 发布模板——把你做好的 Folder 变成模板
- 节点类型——模板所依赖的 Skill 与 AirApp 节点