项目结构
Agent Bundle 项目就是普通的 Node 包,加上一份 agent-bundle.config.ts 和约定式源码树。
只创建插件需要的文件:静态 Skill 不需要 MCP 服务器,工具不需要浏览器 App,App 也不需要自己的服务器注册表。
约定负责发现应用,配置提供身份、策略和显式例外。 冲突声明会产生诊断,而不是一律按“配置总是胜出”静默处理。
目录布局
下面是复合插件的示意结构,不是最小模板。这里是普通的手写源码;宿主清单和可执行包装器属于生成输出。
这份结构中没有手写的 application.ts 注册表、生成式 MCP 入口或原生钩子 JSON;框架按需生成它们。
domain/ 和 components/ 只是代码组织方式,不是新的框架约定。
预构建的非 TypeScript 资源或原生可执行文件应显式声明为 payload,不能假定任意源码目录都会被交付。
各个根目录的含义
以 _ 或 . 开头的私有路径段和声明文件不参与路由发现。
事件文件使用 .ts 返回轻量结果,使用 .tsx 渲染 JSX;需要渲染前门控时,从 .ts 处理器调用 ctx.render() 请求同级 .view.tsx。
执行方式与 provider 访问见钩子。
路由元数据使用有界静态语法。工具把它放入 defineTool 的内联对象;资源、提示、App 与兼容路由继续使用
config 导出。运行时工作保留在处理器或领域模块中,Schema 保持唯一权威定义,不要在 CLI 和浏览器里
分别重建协议类型。
添加交互式 App
工具中的 Agent.* JSX 描述面向智能体的文档;MCP App 入口在浏览器中运行,拥有自己的 DOM 或 React UI。
不要把服务器路由导入浏览器,这会把 Node API、领域服务和仅供服务器使用的依赖带入错误的运行环境。
使用已有的 App 资源绑定连接两者。对于 src/mcp/ops/apps/dashboard.tsx,在浏览器入口中声明资源 URI:
这只是浏览器入口的元数据,不是完整 UI。默认 HTML 提供 #root;启动代码需要其他外壳时使用显式模板。
工具可以引用 App,而不重复写 URI 字符串:
浏览器使用 agent-bundle/app 的 createAppClient。
它的 opening-input、result、error 监听器及工具调用就是集成边界;不要重新实现 postMessage 传输、
请求 ID 映射或 MCP 客户端。在连接之前注册 opening 监听器。
使用宿主提供的初始调用结果进行渲染,不要在挂载时自动重跑一次修改性操作。
所属 UI 退役时释放客户端和订阅。
生成的路由声明提供 App 调用类型;它们必须是最新的,并且被浏览器的 TypeScript 项目包含。 这不能替代对不可信数据的运行时校验。导入是浏览器安全的前提下,可以共享纯呈现组件与已验证数据。 Node 渲染的文档组件不会仅因为也使用 JSX,就自动成为 DOM 组件。
要通过可选的生产浏览器表面暴露同一个 App,在 web.apps 中配置已有的 server/app 身份和初始工具。
不存在第二份 src/web/ 注册表。完整示例与策略见
MCP 服务器与 Apps、可工作的 App 示例及
web 配置。浏览器呈现方式与启动服务器的宿主投影是两个不同选择。
配置与约定
约定式起点仍然很小:
仅对约定无法表达的内容增加显式配置,例如指定 target 的普通钩子、预构建 payload、远程服务器、 非标准路径、包专用 bin 或策略。必需能力仍需要支持它的宿主,或者明确限制目标范围。
手写的 src/mcp/<server>.ts 是已声明服务器的互操作路径。
与同名生成式路由共存时,需要明确决定模式,而不是依赖文件系统顺序。
同理,src/cli.ts 与 src/cli/ 是两种备选 CLI 模式。
src/index.ts 是可选库入口,不是应用注册入口;bin: false 和 lib: false 可以退出这些包约定。
声明故意偏离约定时,检查实际路由图,而不是猜测哪个文件胜出:
正确的编译器必须已经安装到当前项目中。 源码选择与迁移诊断的细节见配置和包入口。
输出落在哪里
区分以下职责:
复合插件根目录
产物示意如下:
只有已声明的相关表面才会输出。精确的原生文档和其他 runtime 文件由清单记录;
应用代码不应该根据这张示意图重新推断可执行文件清单。
不存在 artifact/<host>/ 分区。Amp 使用嵌套的原生目录,而框架的清单感知安装入口接受组合根,
并选择正确的宿主表面。
output.distPath 或 CLI --output 移动组合根,不改变其内部布局。
CLI 优先级是 --output、配置、默认 artifact/。
编程式 build() API 的包输出与默认行为另有约定;应查阅它的参考,不要把 CLI 默认值复制到自定义构建中。
清单记录文件摘要和规范的可执行文件身份。重排 targets 不会创建另一个应用。 字节冲突或意外的跨宿主发现应通过校验解决,不应通过手改生成清单修复。 见 Target 与产物。
npm 包构建
dist/ 是完整的生成式 npm 包根目录,不只是 JavaScript 文件夹:
路由式 CLI 不会为 npm 再编译一份竞争的 .js 实现;生成的 package.json 指向产物中的可执行文件。
显式包专用 bin 与库入口是不同的输出,仍有自己的编译过程。
组合输出与 npm 输出不得重叠:包输出已使用 dist/ 时,再把产物放到那里是无效配置。
构建输出不是源码输入。应打包生成的 npm 根,而不是源码仓库或猜测的 dist/artifact/ 嵌套目录。
校验与安装流程见交付捆绑包。
可写状态不是已安装代码
请求内部使用框架提供的 plugin/context 绑定。独立代码可使用公开的 runtime resolvePluginRoot,
它区分 root 与 stateRoot;AGENT_BUNDLE_STATE_ROOT 独立于代码根覆盖值。
不要因为加载器位于已安装代码树中,就把运行时缓存、刷新后的凭据或数据库也放在那里。 应用数据保留自己的 schema、显式迁移和覆盖策略,并且不能与框架存储冲突。 框架不会自动接管或清除任意插件数据。 见配置与状态和安装生命周期。
下一步
快速开始运行一条真实约定路由。 Skills、钩子、MCP和 脚本与资源说明各表面契约。 编译器架构用于理解实现细节,不是额外的设置步骤。