# 豆包智能服务生命周期与开发流程

## 豆包智能服务开发概念扫盲

豆包智能服务不是单纯的前端页面，而是一组“让模型会用、让工具能执行、让结果能展示”的能力包。开发者需要准备 Skill、MCP Tool、Manifest、卡片 widget 和全页智能服务。
Skill 用来指导模型：什么时候应该调用这个智能服务的工具、需要收集哪些参数、工具返回后如何回复用户。没有 Skill，模型就不知道这个智能服务适合解决什么问题，也不知道该如何使用它。
MCP Tool 是智能服务真正提供的查询、下单、创建、更新业务能力。模型通过 Skill 决定调用工具，工具负责执行业务逻辑，并返回结构化结果。
Manifest 是智能服务的配置说明书。它告诉平台：有哪些工具、工具返回的数据代表什么、哪些结果可以展示成卡片、哪些只是执行结果、哪些是错误，以及哪些实体类型使用哪个卡片 widget。
卡片 widget 决定对话中展示给用户的样式和交互。Manifest 只声明实体到前端 `widget_id` 的引用关系；真正的卡片代码在前端工程中实现，并需要在 `src/app.config.ts` 的 `defineAppConfig({ widgets })` 中注册。开发卡片代码时，Agent 应根据业务对象和展示诉求读取 [Widget 模板库](frontend/widget-templates/overview.md)，选择一张匹配的 `@doubao-apps/template` 模板，在 widget 代码的 `defineWidget.render()` 中按模板 JSX/props 语法引用选中的模板，并补齐业务数据映射、点击动作和状态处理。选中并注册业务卡片后，还要在 Manifest 中把对应 entity 和 MCP tool 绑定到该 `widget_id`。
全页智能服务 是更完整的交互页面。用户可以先在对话中看到卡片，再通过点击卡片进入全页（不存在只有全页pages但没有卡片widgets的豆包智能服务，所以不要只开发全页而没有进入全页的卡片），完成更复杂的查看、操作或后续流程。
所以，开发一个豆包智能服务，本质上是在准备这些东西：让模型知道怎么用的说明(skill)、能完成业务动作的工具(mcp tool)、以及把工具结果展示给用户的配置(manifest)和界面(pages & widgets)。

```
用户提问
  |
  v
模型读取 Skill
  |
  |  Skill 说明：
  |  - 这个智能服务能做什么
  |  - 什么时候调用哪个 MCP Tool
  |  - 缺少参数时怎么追问
  v
调用 MCP Tool
  |
  |  MCP Tool 负责：
  |  - 执行业务逻辑
  |  - 返回结构化结果
  v
Manifest 解释工具返回
  |
  |  Manifest 说明：
  |  - 这是出卡结果？
  |  - 这是执行结果？
  |  - 这是错误？
  |  - 哪些实体类型引用哪个卡片 widget？
  v
卡片 widget 渲染
  |
  |  卡片展示：
  |  - 读取 entity 数据
  |  - 实现标题 / 摘要 / 图片 / 按钮 / 点击动作
  v
对话中展示智能服务卡片
  |
  v
用户点击卡片
  |
  v
打开全页智能服务
```

开发者需要准备

```
+----------------+
| Skill          |
| 指导模型怎么用 |
+----------------+
        |
        v
+----------------+
| MCP Tool       |
| 提供业务能力   |
+----------------+
        |
        v
+----------------+
| Manifest       |
| 解释返回和绑定 |
+----------------+
        |
        v
+----------------+
| 卡片 widget    |
| 决定卡片样式   |
+----------------+
        |
        v
+----------------+
| 全页智能服务     |
| 承接完整交互   |
+----------------+
```

## 豆包智能服务开发入口

典型链路是：

```text
用户提出需求
  -> 模型根据skill帮助用户构建MCP server、Manifest、智能服务前端
    -> MCP Tool 执行业务逻辑并返回结构化结果
    -> Manifest 帮平台理解工具、实体、输出类型和卡片 widget 引用
    -> 智能服务前端/卡片代码选择并引用合适的 Template 模板，渲染用户可见界面
    -> Manifest 记录 entity/tool 到前端 widget_id 的绑定关系
  -> 本地调试确认链路可用
  -> 上传 manifest.yaml + skill目录 + 前端源码目录
  -> 云构建生成 version_tag
  -> Agent 输出平台版本详情 URL，后续在平台操作
```

因此，Agent 的工作不是机械生成文件，而是根据用户目标判断当前缺的是哪一层能力：业务工具、模型使用说明、前端体验、平台配置、本地调试，还是最终云构建。只有理解这条链路，才能在“只修前端”“只改 Manifest”“已有 MCP 只补 Skill”“本地已调通只上传”等场景中选择正确的工作范围。

本 Skill 用于 Agent 在已经具备豆包智能服务开发基础结构的项目中接手开发。Agent 只检查当前项目是否具备必要的本地配置、Skills、前端脚手架和模板数据；如果关键初始化产物缺失，停止开发流程并提示用户先完成项目初始化。

Agent 接手后的生命周期是：

```text
setup -> mcp -> auth -> frontend -> manifest -> debug -> build
```

实际执行时不要机械跑完整链路。先理解用户目的，再选择需要的 group，自主编排满足依赖的步骤。各 group 的具体做法由本文件和 `auth.md` 展开；遇到协议、Manifest、前端或调试细节时，再按 Reference 路由读取本 skill 内的专项文件。

处理可关联到用户的数据前，先读 [data-compliance.md](data-compliance.md)，识别当前功能直接需要的数据、处理目的、接收方和保存范围，再按既有流程完成实现与验证。

这几个 group 的边界来自上面的产物关系：

- `setup`：确认项目基础结构完整，获取本地 workspace。
- `mcp`：解决“工具能执行”和“模型知道怎么用工具”，确保有公网可访问且协议合规的 MCP URL，或有符合豆包智能服务 MCP 协议的 MCP server 代码，并生成运行态 Skill。
- `auth`：解决“当前用户是谁、是否已授权、MCP Server 如何识别用户”，覆盖 `src/mcp-ui` 登录承接、智能服务后端 token 交换接口、Manifest 登录配置和 MCP 入站 header 校验。
- `frontend`：解决“用户能看到和操作什么”，包括全页页面、卡片代码和 Template 模板应用；不在本阶段打包。
- `manifest`：解决“平台如何理解这个版本”，把 MCP、entities、输出和模板引用写成平台配置。
- `debug`：在上传前验证 MCP、Skill、智能服务前端、Manifest 能协同工作。
- `build`：在用户确认并拿到真实 AppID 后，读取脚本返回的前端运行时配置文件并把 `runtimeConfig.appId` 改成该 AppID，打包前端源码快照，上传三类产物，触发云构建并拿到 `version_tag`。

注意，无论怎么编排，一定要确保在进入本地调试阶段或云端构建阶段之前具备manifest、skill、前端源码这些文件。

### Group 选择

每轮会话都先判断用户意图，再选择需要执行的 group。常见映射：

| 用户目标                                                        | groups                                         |
| --------------------------------------------------------------- | ---------------------------------------------- |
| 从 0 到 1 开发并上传构建                                        | `setup,mcp,frontend,manifest,debug,build`      |
| 从 0 到 1 开发带登录认证的智能服务并上传构建                    | `setup,mcp,auth,frontend,manifest,debug,build` |
| 只开发或修改 MCP server、tool 协议、运行态 Skill                | `setup,mcp`                                    |
| 只接入登录认证、OpenID、业务账号登录、手机号或 MCP 用户身份识别 | `setup,mcp,auth,manifest,debug`                |
| 修改 MCP 后本地调试，但暂不上传                                 | `setup,mcp,manifest,debug`                     |
| 只修改全页智能服务或卡片前端并本地调试                          | `setup,frontend,debug`                         |
| 只修改 Manifest 并本地调试                                      | `setup,manifest,debug`                         |
| 现有产物已经准备好，只本地调试                                  | `setup,debug`                                  |
| 本地调试已完成，只上传并触发云构建                              | `setup,build`                                  |

依赖关系：

- `setup` 是所有 group 的前置。
- `mcp` 产出可用 MCP URL 或合规 MCP server 代码、tools 信息和运行态 Skill 源目录。
- `auth` 依赖需要登录的 MCP tool 信息，产出登录能力等级、`src/mcp-ui` 前端承接方案、智能服务后端 token/删除接口契约、MCP Server 入站 header 处理逻辑和 Manifest 登录配置需求。
- `frontend` 产出前端源码；前端源码包由 `build` 阶段在确认 `manifest.app_key` 后通过 upload 命令临时生成。
- `manifest` 产出并校验 `workspace.py manifest path --create --json` 返回的 manifest 文件；如果 Manifest 需要描述 MCP tools/entities，应先完成相关 `mcp` 信息；如果 Manifest 需要配置 `mcp_server.user_auth`、`login_type`、`login_params`，应先完成 `auth` 设计。
- `debug` 是上传前的本地调试，依赖本轮需要调试的 MCP、frontend、manifest 已准备好。
- `build` 依赖 `workspace.py artifacts check --json` 返回的 manifest、skill、前端源码都存在，并且用户明确同意上传；skill zip 和前端源码包由 upload 命令在 `/tmp/dbx` 下临时生成并清理。

如果预设场景不能完整表达用户目标，直接组合 group，但不能违反上面的依赖关系。

### 执行原则

Agent 可以自主编排流程，不再通过状态机脚本获取下一步。

执行 `dbx` 命令时，如果命令失败，且报错信息明确表明问题来自远端服务、平台接口、网关、构建服务等服务端错误，不要根据经验猜测原因、不要擅自重试变体命令、不要继续推进后续步骤。立即终止当前流程，把原始错误信息和其中的 `logid`、`log_id` 或请求 ID 告知用户；如果错误中没有这些 ID，也要明确说明未返回可定位 ID。

在沙箱环境中执行 `dbx` 命令时，可能会因为沙箱环境无法读取真实环境的可信凭据导致出现认证失败的问题，此时尝试可以提权执行命令。

当skill、manifest、前端代码都准备完毕后，**必须明确的询问用户是要进行本地调试还是上传到云端进行构建**，不这么做会导致用户不知道下一步应该做什么。用户回答后，如当前上下文没有明确 AppID，必须向用户询问 AppID，再调用上传命令。

云构建成功后，只输出 `version_tag` 和平台版本详情 URL。后续提审、发布等操作在平台上完成，不在本 lifecycle 中继续推进。

### Reference 路由

- 初始化检查：读 [setup](#setup)。
- MCP server、tool schema、运行态 Skill：读 [mcp](#mcp)。
- 登录认证、OpenID、业务账号登录、手机号和 MCP 用户身份识别：使用 [auth](auth.md)。
- 普通支付、订单状态、回调、退款、履约完成、签约和协议支付：使用 [payment](payment.md)。
- 全页智能服务和卡片前端：读 [frontend](#frontend)。
- 卡片 Template 模板选型与代码落地：读 [template-widget](#template-widget)。
- Manifest 编写和校验：读 [manifest](#manifest)。
- 上传前本地调试：读 [debug](#debug)。
- 上传产物、轮询云构建、输出版本详情 URL：读 [build](#build)。

专项知识由本 skill 内的 reference 提供：

- 用户数据处理、数据共享和合理最小必要原则：读 [data-compliance.md](data-compliance.md)。
- Manifest 编写：读 [manifest-guide.md](manifest-guide.md)。
- MCP 协议和业务建模：读 [mcp-protocol.md](mcp-protocol.md)。
- 登录认证和 MCP 用户身份识别：读 [auth.md](auth.md)，并结合 [manifest-guide.md](manifest-guide.md) 的认证字段。
- 支付、退款、履约完成、签约和协议支付：读 [payment.md](payment.md)，再按流程读取命中的 OpenAPI 详情。
- 本地 Web 调试和 MCP 预览：读 [local-debug/overview.md](local-debug/overview.md)；Simulator Eval：读 [local-debug/simulator-eval.md](local-debug/simulator-eval.md)。
- 前端 Page / Widget / Open API：读 [frontend-dev.md](frontend-dev.md)。
- 卡片模板组件库参考：读 [frontend/widget-templates/overview.md](frontend/widget-templates/overview.md)。

### 常用脚本

`workspace.py` 只管理本地工作文件路径，不调用平台接口。涉及 manifest、skill、前端目录时，必须先调用脚本获取路径，再按返回值读写或传给 `dbx` 命令。

```bash
python3 <skill_dir>/scripts/workspace.py config-status --json
python3 <skill_dir>/scripts/workspace.py app-id --json
python3 <skill_dir>/scripts/workspace.py app-id set --value <app_id> --json
python3 <skill_dir>/scripts/platform_info.py dashboard --json
python3 <skill_dir>/scripts/workspace.py frontend path --json
python3 <skill_dir>/scripts/workspace.py workspace ensure --json
python3 <skill_dir>/scripts/workspace.py manifest path --create --json
python3 <skill_dir>/scripts/workspace.py skill path --create --json
python3 <skill_dir>/scripts/workspace.py artifacts check --json
```

### 常见问题

- `dbx` 是使用npm安装的全局可执行文件，如果在当前环境的path下找不到该目录，请查看一下npm的全局安装目录下是否有该文件。

## debug

### 目标

上传前完成本地调试，确认 MCP、运行态 Skill、前端和 Manifest 在当前用户目标下能协同工作。

本阶段使用 [本地调试总流程](local-debug/overview.md) 中的 `dbx dev` 流程；需要验证后端出卡链路时使用 [Simulator Eval 指南](local-debug/simulator-eval.md)。不要再告知用户“暂无本地调试能力”。

### 调试范围

根据本轮改动选择调试内容，不要求每次全量调试：

- MCP 改动：验证 MCP Server 可启动、`initialize` / `tools/list` 正常、关键 tools 可调用。
- 运行态 Skill 改动：检查工具选择策略、参数追问、结果解释是否符合业务目标。
- 智能服务前端改动：启动 Web 模拟器，验证页面、卡片、跳转、空态和错误态。
- Manifest 改动：确认 Manifest 能被本地模拟器加载，工具、entities、权限和 widget 引用一致。

### 执行方式

1. 先确保本轮需要调试的 Manifest、运行态 Skill、前端源码已经准备好。
2. 按 [本地调试总流程](local-debug/overview.md) 核对当前 AppID 格式，选择对应 App 配置文件；如果业务 Server 会调用平台 OpenAPI，再设置 Server 启动环境变量。
3. 再确保 `manifest.mcp_server.end_point` 指向 CLI 当前运行环境可访问的 MCP endpoint：
   - 本地 MCP Server：根据项目实际启动脚本，按 [本地调试总流程](local-debug/overview.md) 由 Agent 帮用户启动和观测服务；确认 endpoint 可访问后，核对 Manifest 和前端 URL 都已指向该实例。
   - 已有公网 MCP Server：把 Manifest 中的 endpoint 配成当前调试环境的公网 MCP endpoint。
4. 首次调试或调试边界变化时，在 dbx 项目目录下直接启动交互式调试控制台，不需要进入智能服务前端目录；启动时显式传当前 MCP endpoint：

   ```bash
   dbx dev --mcp-endpoint <mcp_endpoint>
   ```

   命令默认读取 `<project>/manifest.yaml` 和 `<project>/skill/SKILL.md`，并按项目布局和 `.dbx/config.json` 解析前端目录。`<mcp_endpoint>` 使用步骤 3 确认的 Streamable HTTP `/mcp` 地址。纯前端改动只刷新模拟器，不要重启 `dbx dev`。

5. 只有默认路径不符合项目结构时，才调用 workspace 脚本获取调试路径：

   ```bash
   python3 <skill_dir>/scripts/workspace.py frontend path --json
   python3 <skill_dir>/scripts/workspace.py manifest path --create --json
   python3 <skill_dir>/scripts/workspace.py skill path --create --json
   ```

   再把脚本返回值传给 `dbx dev`：

   ```bash
   dbx dev \
     --mcp-endpoint <mcp_endpoint> \
     --manifest <manifest_path> \
     --skill <skill_md_path>
   ```

   当前目录是整个 dbx 项目根目录，也是写入 `.dbx/localdebug` 状态、默认 Manifest、Skill 和前端目录的目录。`workspace.py skill path --json` 返回的 `path` 是 Skill 目录，`dbx dev --skill` 可以传返回 JSON 里的 `skill_md` 或 `path`。

6. `dbx dev` 已运行后，前端 Page / Widget / 样式改动只刷新 Web 模拟器或点“刷新资源并重载卡片”；不要重启工程。
7. 完成验证后，退出 `dbx dev` 控制台或按 Ctrl-C。

详细命令、App 配置分流、MCP Server 配置、Manifest/Skill 加载规则和排障方式见 [本地调试总流程](local-debug/overview.md)。

### 上传确认

本地调试完成后，不要自动上传。先向用户说明当前可上传的产物和调试结论，并询问是否上传触发云构建。用户同意后再进入 `build` group。

### 完成判据

- 本轮涉及的核心链路已经在本地验证。
- 如果使用 MCP，已确认 MCP endpoint 被 Web 调试器加载，且关键 tool 路径可用。
- 未解决问题已明确列出，并由用户决定是否继续上传。

## mcp

### 目标

确保用户要么有公网可访问且满足豆包智能服务要求的 MCP URL，要么有一份满足豆包智能服务 MCP 协议要求的 MCP server 代码；同时整理 tool 信息，并生成运行态 Skill 源目录。

MCP 阶段不强制要求一定已经有公网 URL。已有合规代码但没有公网 URL 时，可以继续本地调试；上传云构建时再要求提供公网可访问 URL。

### 场景一：用户已有公网 MCP URL

先校验这个 MCP URL 是否满足豆包智能服务要求：

- MCP endpoint 公网可访问。
- 支持 `initialize`、`notifications/initialized`、`tools/list`。
- tools 的 `name`、`description`、`inputSchema` 清晰稳定。
- tool 返回值符合豆包智能服务 MCP 协议要求，尤其是成功结果、业务错误、`structuredContent`、`output.kind`、entities / execution_result 等约定。
- 如果工具要出卡，返回结果和 Manifest entities 设计能对应起来。

校验时按 [mcp-protocol.md](mcp-protocol.md) 判断返回协议是否合规；必要时对关键 tool 做代表性调用。

如果公网 MCP URL 不满足豆包智能服务协议要求，说明具体原因并终止当前流程。不要假设平台会兼容，也不要在没有代码控制权的情况下继续写 Manifest 或上传。

如果校验通过，记录可用于 Manifest 的信息：

- MCP URL
- tool name / description / MCP `inputSchema`
- 每个 tool 的输出类型和是否出卡
- 关键返回 schema 示例

### 场景二：用户没有公网 MCP URL，但仓库已有 MCP server 代码

根据代码检查 MCP server 是否满足豆包智能服务要求：

- 能以本地方式启动。
- 支持通过 `MCP_PORT` 配置监听端口，并按 [本地调试总流程](local-debug/overview.md) 支持 OpenAPI BaseDomain 环境变量。AppSecret 不得写入前端、Manifest、运行态 Skill、日志或提交到仓库。
- MCP 协议模式明确，不能是stdio，必须是http，优先 streamable mode。
- 暴露的 tools 与用户业务目标一致。
- `tools/list` schema 与实际 tool 入参一致。
- tool 返回值符合豆包智能服务 MCP 协议要求。
- 错误返回能区分业务错误和系统异常。
- 工具调用和登录相关接口具有结构化、已脱敏且不过度冗余的日志，能够通过 request/trace ID、tool/endpoint、耗时、结果码和平台 `log_id` 定位问题。

如果代码不满足要求，直接改造代码，直到本地协议检查通过。改造后根据项目实际脚本，按 [本地调试总流程](local-debug/overview.md) 帮用户启动和观测服务；endpoint 可访问后，再调用 `initialize` / `tools/list` / 关键 `tools/call` 验证。

如果代码满足要求但没有公网 URL，不要阻塞本地调试。此时 MCP 阶段的完成状态是“有合规 MCP server 代码，但尚无公网 URL”。后续 `debug` 可以使用本地服务；`build` 上传前再要求提供公网可访问 MCP URL。

### 场景三：用户没有公网 MCP URL，也没有 MCP server 代码

先明确用户业务场景和核心业务对象，再创建一份符合业务要求和豆包智能服务 MCP 协议的 MCP server 代码。

创建代码时：

- 禁止使用stdio模式，必须使用http，优先 streamable mode。
- tools 设计要和用户真实业务动作对应。
- input schema 要能让模型稳定收集参数。
- tool 返回 schema 要符合豆包智能服务 MCP 协议，并尽量使用业务化字段名。
- 需要出卡的结果要能映射到 Manifest entities 和前端卡片。
- 必须支持通过 `MCP_PORT` 配置监听端口，并按 [本地调试总流程](local-debug/overview.md) 支持 OpenAPI BaseDomain 环境变量。
- 按 [本地调试总流程](local-debug/overview.md)，由 Agent 根据实际项目命令帮用户完成本地启动和观测。

完成后按 [本地调试总流程](local-debug/overview.md) 帮用户启动本地 Server；endpoint 可访问后再验证 `initialize`、`tools/list` 和关键 tool 调用。没有公网 URL 不阻塞本地调试；上传前再要求用户提供可公网访问的 URL 或完成部署。

### 运行态 Skill

无论 MCP 来自公网 URL、已有代码还是新建代码，都要生成运行态 Skill。运行态 Skill 必须描述智能服务能做什么、何时调用哪个 MCP tool、缺参数时如何追问、工具返回后如何回复用户和如何输出卡片；不能只复述 tool schema，也不能编造服务端不存在的能力。具体写法读取 [generate-skill.md](generate-skill.md)。

1. 获取运行态 Skill 目录和文件路径：

   ```bash
   python3 <skill_dir>/scripts/workspace.py skill path --create --json
   ```

2. 运行态 Skill 文件必须写入脚本返回的 `skill_md`，默认位置是 `skill/SKILL.md`。脚本返回的 `path` 是运行态 Skill 目录，后续示例中用 `<runtime_skill_dir>` 表示，主要用于上传。不要手写固定路径或创建项目根目录下的 `SKILL.md`。

3. 读取 [generate-skill.md](generate-skill.md)，按其中的输入材料、目标结构、工具选择、出卡、不出卡、失败和空结果规则编写运行态 Skill。至少必须覆盖：
   - 智能服务业务能力和适用/不适用场景。
   - 每个 MCP tool 的调用条件、必填参数、缺参追问方式和用户可理解的参数名称。
   - tool 成功返回后的回复策略；如果 `tools.output.kind=entities` 且命中 `tool_card_binding`，说明会展示对应卡片。
   - tool 业务错误、系统错误、空结果和权限不足时的用户回复。
   - 多轮对话中如何复用上轮参数，何时重新确认用户选择。

4. 不要在 MCP 阶段打包 `skill.zip`。`build` 阶段调用 `dbx app artifacts upload --skill <runtime_skill_dir>`，由 CLI 在 `/tmp/dbx` 下临时打包并在上传后清理。

### 完成判据

满足以下任一 MCP 条件：

- 已有公网可访问 MCP URL，且协议校验通过。
- 没有公网 URL，但仓库内已有合规 MCP server 代码。
- 没有公网 URL，也没有旧代码，但已新建合规 MCP server 代码。

同时满足：

- 已整理 tool name、description、MCP `inputSchema`、输出形态。
- `workspace.py skill path --create --json` 返回的 `skill_md` 存在。
- MCP Server 已为关键 tool、登录接口和下游 OpenAPI 调用实现可关联、已脱敏的结构化日志。

## frontend

### 目标

基于项目初始化时创建的前端脚手架，完成全页智能服务和卡片相关前端源码。

### 关键原则

前端源码不放在 `.dbx/workspace` 下。`.dbx/workspace` 只保存打包产物和中间工作文件。

本阶段不打包前端源码快照。前端必须将非敏感运行时配置集中在 `src/config/runtime.ts`（或脚本返回的等价路径）：`appId` 和 `apiBaseUrl` 是必需字段。`src/app.config.ts` 从该模块读取 `appId`，所有普通 HTTP 请求通过统一 client 使用 `apiBaseUrl`。不要在 Page/Widget 中硬编码 AppID 或服务端 URL；AppSecret 绝不属于前端配置。

前端打包必须放到 `build` 阶段。在拿到用户确认的真实 AppID 后，确认运行时配置的 `appId`、Manifest `app_key` 与该 AppID 一致，并确认 `apiBaseUrl` 和 `mcp_server.end_point` 是正式版本应使用的地址；如果本地调试曾临时切换身份或地址，必须将整组配置恢复为正式值。随后再由 `dbx app artifacts upload` 在命令内部临时生成前端源码包，避免把沙箱身份、业务 URL 或本地 `/mcp` 地址上传到正式版本。

如果前端脚手架不存在，不要直接新建一套平行工程；提示用户先完成或修复项目初始化。

### 执行方式

1. 确认前端目录。
   - 优先读取 `.dbx/config.json` 中 `frontend.directory`。
   - 若配置缺失，再根据项目结构判断，常见目录为项目根目录下的 `doubao-agentic-service`。

2. 根据用户需求开发前端。
   - 补齐页面、组件、路由、状态管理、接口调用、空态、错误态和基础样式。
   - 全页智能服务中的运行时交互可以发起普通 HTTP 请求，不要求把页面内接口调用都设计成 MCP tool。
   - 豆包智能服务前端开发相关知识读取 [frontend-dev.md](frontend-dev.md)；内置组件 props 和事件读取 [frontend/components/overview.md](frontend/components/overview.md)；模板卡片读取 [frontend/widget-templates/overview.md](frontend/widget-templates/overview.md)。
   - 如涉及对话卡片，必须使用卡片模板的方式进行开发，必须先读 [frontend/widget-templates/overview.md](frontend/widget-templates/overview.md)，选择合适的 `@doubao-apps/template` 模板，并在业务 widget 代码中引用模板组件，绝对不允许不引用模板自行开发卡片，这种方式可能会导致云端构建失败。
   - 对话卡片实现完成后，确认它已在 `src/app.config.ts` 的 `defineAppConfig({ widgets })` 中注册，并记录对应 `widget_id`，供 Manifest 的 entity/tool 绑定使用。
   - `widgets` 显式对象写法使用对象里的 `id` 作为 `widget_id`；`widgets: ['widgets/weather/index']` 这类简写使用 `widgets` 目录下的目录名 `weather` 作为 `widget_id`。
   - 若卡片或全页需要读取 MCP 返回数据，确保字段与 Manifest/实体设计一致。

### 完成判据

- 前端目录存在，并包含本轮需求所需页面、组件和交互。
- 本轮可运行的项目校验已通过，或已说明项目没有可用校验命令。
- 不要求 `.dbx/workspace/doubao-agentic-service.zip` 存在；前端源码包由 `build` 阶段的 upload 命令临时生成并清理。

## setup

### 目标

确认当前项目基础结构完整，恢复本地开发状态，获得本地 workspace 路径。

### 关键原则

Agent 只检查初始化产物是否存在，不负责创建或补齐这些产物。关键产物缺失时停止当前开发流程，提示用户先完成项目初始化。

### 检查项

1. 检查 `.dbx/config.json` 是否存在：

   ```bash
   python3 <skill_dir>/scripts/workspace.py config-status --json
   ```

   如果 `config_exists=false`，停止当前流程并提示用户先完成项目初始化。不要继续创建 workspace。

2. 确认 `.dbx/config.json` 存在后，获取本地 workspace 目录：

   ```bash
   python3 <skill_dir>/scripts/workspace.py workspace ensure --json
   ```

3. 检查基础产物：
   - `.dbx/config.json` 存在。
   - 项目中存在前端脚手架目录；优先读取 `.dbx/config.json` 中的 `frontend.directory` 配置，其次再按项目结构判断。

如果关键产物缺失，不要自行补一个平行结构；提示用户先完成或修复项目初始化。

## template-widget

### 目标

在开发对话卡片 widget 时，使用 [frontend/widget-templates/overview.md](frontend/widget-templates/overview.md) 选择合适的 `@doubao-apps/template` 模板，并在业务 widget 代码中引用该模板组件，补齐业务数据、交互和状态处理。

### 何时使用

只要本轮开发涉及对话卡片代码，就先读取 [frontend/widget-templates/overview.md](frontend/widget-templates/overview.md)，并按其中的模板选型和 props 约束实现。

典型场景：

- `entities.<entity_type>.tool_card_binding` 指向的业务卡片还没有实现。
- MCP tool 返回了适合在对话卡片中展示或操作的业务实体。
- 已有卡片代码需要从手写布局迁移为 Template 模板组件。

### 执行流程

1. 明确业务卡片要表达什么。
   - 先判断这张卡片承载的是单个对象、候选集合、确认动作、状态反馈，还是其他业务表达。
   - 明确卡片需要展示的核心字段、用户可执行动作、空态/异常态，以及这些信息来自哪个 MCP entity 或页面状态。

2. 读取 [frontend/widget-templates/overview.md](frontend/widget-templates/overview.md) 和 [frontend/widget-templates/props.md](frontend/widget-templates/props.md)。
   - 模板名称、选型表、props、item 类型和行为约束都以该专项 Skill 为准。
   - lifecycle 不复制模板清单；如果专项 Skill 更新，按专项 Skill 的最新说明选择模板。

3. 在前端工程中实现业务 widget。
   - `defineWidget` 从 `@doubao-apps/framework` 导入。
   - 按 [frontend/widget-templates/overview.md](frontend/widget-templates/overview.md) 的说明，从 `@doubao-apps/template` 导入选中的模板组件和类型。
   - 在 `defineWidget({ render() { ... } })` 的 `render()` 中直接返回选中的模板组件。
   - 不要在模板外再包 `view`、`scroll-view` 或额外卡片壳。

4. 补齐业务代码。
   - 将 MCP entity 或页面状态映射为模板 props。
   - 列表 item 使用稳定 `key`，优先使用业务 ID。
   - 按业务需要补齐点击事件、跳转、按钮 loading/disabled、空态和异常态。
   - 若模板结构不能完全覆盖业务展示，优先使用模板提供的 `children` 自定义内容区，不要直接重写整张卡片。

5. 回填 Manifest 绑定关系。
   - 选定并实现业务卡片后，确认该卡片已在 `src/app.config.ts` 的 `defineAppConfig({ widgets })` 中注册，并拿到对应 `widget_id`。
   - 显式对象写法使用 `widgets[].id` 作为 `widget_id`；字符串简写 `widgets: ['widgets/weather/index']` 使用 `widgets` 目录下的目录名 `weather` 作为 `widget_id`。
   - 在 Manifest 中为会出卡的 entity 配置 `entities.<entity_type>.tool_card_binding.<tool_name>: <widget_id>`。
   - `tool_name` 必须是实际 MCP tool 名；`entity_type` 必须是该 tool 输出中声明的 entity 类型。
   - 同一个 entity 在不同 tool 返回时可以绑定到不同 `widget_id`，以 Manifest 中的业务绑定为准。

### 最小代码形态示意

以下只是代码形态示意，`SelectedTemplate`、`SelectedTemplateProps` 应替换为 [frontend/widget-templates/overview.md](frontend/widget-templates/overview.md) 选型结果中的真实模板组件和类型。

```tsx
import { defineWidget } from "@doubao-apps/framework";
import {
  SelectedTemplate,
  type SelectedTemplateProps,
} from "@doubao-apps/template";

export default defineWidget({
  render() {
    const props: SelectedTemplateProps = buildPropsFromBusinessData();

    return <SelectedTemplate {...props} />;
  },
});
```

### 与 Manifest 的关系

- 前端代码选择的是 `@doubao-apps/template` 的模板组件；Manifest 绑定的是前端 `widget_id`。
- Manifest 需要通过 `entities.<entity_type>.tool_card_binding.<tool_name>` 把“某个工具返回的某类实体”绑定到对应卡片 `widget_id`。
- `@doubao-apps/template` 的组件名、props、字段映射和点击事件只存在于前端 widget 代码中。
- 前端卡片代码要读取的业务字段，应和 MCP 返回 entity 以及 Manifest `entities.<entity_type>.schema` 保持一致。

### 完成判据

- 已根据业务展示诉求，按 [frontend/widget-templates/overview.md](frontend/widget-templates/overview.md) 选择了一个合适的 Template 模板。
- widget 代码中通过 `@doubao-apps/template` 引用了选中的模板组件。
- `defineWidget.render()` 直接返回模板组件。
- 模板 props 已接入真实业务字段或清晰 TODO，关键点击动作和状态处理已补齐。
- Manifest 中需要出卡的 entity 已通过 `tool_card_binding` 绑定到对应前端 `widget_id`。

## manifest

### 目标

编写、修改并校验当前项目的 Manifest 工作文件。

### 输入依赖

- 如果 Manifest 需要描述 MCP tools、entities 或工具输出，应先完成对应 MCP/tool/schema 信息。
- 如果 Manifest 需要引用卡片 widget，应先明确前端工程中注册的 `widget_id`；卡片代码内部使用的 `@doubao-apps/template` 组件由前端实现决定，不写入 Manifest。
- 如果本轮新增或修改了对话卡片，应把对应 entity 和 MCP tool 通过 `entities.<entity_type>.tool_card_binding.<tool_name>: <widget_id>` 绑定到该前端 `widget_id`。

### 执行方式

1. 获取 manifest 工作文件路径：

   ```bash
   python3 <skill_dir>/scripts/workspace.py manifest path --create --json
   ```

   后续所有 Manifest 读写都使用返回的 `path`；命令示例中用 `<manifest_path>` 表示。

2. 编写或修改 Manifest。
   - 使用 [manifest-guide.md](manifest-guide.md)。
   - 涉及业务建模、entities、工具输出类型时，结合 [mcp-protocol.md](mcp-protocol.md) 的设计结果。
   - 涉及对话卡片时，结合 [frontend/widget-templates/overview.md](frontend/widget-templates/overview.md) 的结果更新 `tool_card_binding`。
   - 只修改本轮目标相关配置；不要顺手重写无关配置。

3. 一旦修改了 Manifest，**一定要进行校验**。
   ```bash
   dbx app artifacts validate \
     --file <manifest_path> \
     --json
   ```

如果校验失败，根据 validator 返回的 errors/warnings 修改；如果失败明确来自远端服务端错误，按主 Skill 的远端错误中断规则处理。

### 完成判据

- `workspace.py manifest path --create --json` 返回的 `path` 存在。
- Manifest 覆盖本轮要提交的工具、实体、输出和权限配置。
- `dbx app artifacts validate` 校验通过。

## auth

登录认证、OpenID、业务账号登录、手机号和 MCP 用户身份识别流程见 [auth.md](auth.md)。进入 `auth` group 时先读该文件，再回到本文件继续 `manifest`、`debug` 或 `build` 阶段。

## build

### 目标

在用户确认后，上传本地三类产物并触发云构建，轮询构建结果，最终输出 `version_tag` 和平台版本详情 URL。

如果用户是因为“想看真机效果”“测试手机里的渲染”“真机验证页面/卡片”进入本阶段，但尚未明确选择预览方式，先询问并等待回答：

> 你想通过哪种方式验证真机效果：使用 UGC Bot 扫码预览已上传并云构建的版本，还是使用 `dbx dev` 连接手机并直接推送页面/卡片？

用户选择 UGC Bot 后才继续本阶段。用户选择 `dbx dev` 后，改读 [dev-debug.md](dev-debug.md)，不要上传或触发云构建。等待选择期间不执行任一路径的专属操作，也不要把“想看真机效果”本身当作上传确认。

### 前置条件

build 前必须具备：

- `workspace.py manifest path --json` 返回的 manifest 文件
- `workspace.py skill path --json` 返回的运行态 Skill 目录，且其中存在 `SKILL.md`
- 前端源码目录存在，且包含 `src/app.config*` 和 `src/config/runtime.ts`（或脚本识别的 `.js` / `.json` 等价文件）
- Manifest 中用于云构建的 MCP endpoint 必须是公网可访问 URL。只有本地 MCP server 代码但没有公网 URL 时，不能上传；此时向用户说明需要先部署 MCP server 或提供公网 URL。

先检查本地待上传源文件和源目录：

```bash
python3 <skill_dir>/scripts/workspace.py artifacts check --json
```

必须确认：

- 缺 `manifest.yaml`：回到 `manifest`
- 缺运行态 Skill：检查 `skill/SKILL.md`，回到 `mcp`
- 前端目录不存在、没有 `src/app.config*` 或没有 `src/config/runtime.*`：回到 `frontend`

同时记录 `required` 中实际解析出的 Manifest 和 Skill 路径作为 `<manifest_path>` 与 `<runtime_skill_dir>`。不要手写固定路径。

### 用户确认

上传前必须询问用户是否上传并触发云构建。用户确认后，如果上下文没有明确 AppID，先通过平台信息脚本读取平台 Dashboard 地址；该脚本从 `dbx auth` 写入的本地 token metadata 中获取平台 base URL：

```bash
python3 <skill_dir>/scripts/platform_info.py dashboard --json
```

如果脚本返回 `dashboard_url`，向用户询问 AppID 时顺带告知用户可以在该页面创建应用。如果没有返回 `dashboard_url`，提示用户先完成 `dbx auth:login`，或在登录后重新执行当前流程。

如果本轮是向用户询问得到的 AppID，写入项目根目录的 `manifest.yaml`；这是项目中 AppID 的唯一手工维护入口：

```bash
python3 <skill_dir>/scripts/workspace.py app-id set --value <app_id> --json
```

### 打包前端源码快照

拿到真实 AppID 后，先获取前端目录：

```bash
python3 <skill_dir>/scripts/workspace.py frontend path --json
```

脚本返回 `frontend_dir`、`app_config`、`runtime_config` 及其 candidates。`runtime_config` 是实际命中的前端运行时配置文件；Agent 必须读取它，并根据文件实际语法确认 `runtimeConfig.appId` 与正式 AppID 一致、`runtimeConfig.apiBaseUrl` 指向正式业务 Server。随后读取 Manifest，将 `app_key` 与正式 AppID 对齐，并确认 `mcp_server.end_point` 是正式公网 endpoint。`app.config.ts` 应只引用该值，不再重复维护 AppID。只有当前值与本次要构建的目标应用不一致时才更新。

检查要求：

- 只修改构建目标确实需要调整的身份与地址：`runtimeConfig.appId`、`runtimeConfig.apiBaseUrl`、`manifest.app_key`、`manifest.mcp_server.end_point`；不要顺手修改其它业务配置。
- 保持原文件格式、缩进、引号风格和导出方式。
- 如果 `runtime_config_exists=false`，回到 `frontend` 阶段补齐集中配置和 `app.config.ts` 的引用；不要退回到各组件或 `app.config.ts` 中硬编码。
- 如果文件中找不到 `runtimeConfig.appId`，停止 build，向用户说明无法确定写入位置。

确认 Manifest AppID 后再上传。不要在 Agent 侧手动生成 `skill.zip` 或 `doubao-agentic-service.zip`；`dbx app artifacts upload` 会把 AppID 传给 Kit，先执行前端构建检查，再在命令内部完成临时打包和上传。构建检查失败时停止上传。

### 上传并触发云构建

```bash
dbx app artifacts upload \
  --manifest <manifest_path> \
  --skill <runtime_skill_dir> \
  --frontend-code <frontend_dir> \
  --json
```

该命令会校验 manifest、把 skill 目录临时打成 zip、调用前端打包命令生成源码包、上传三类产物并触发云构建。临时产物会放在 `/tmp/dbx/artifacts-upload/upload-*`，上传完成或失败后由 CLI 清理。从输出中记录 `version_tag` 和 `log_id`。

上传云构建前确认 `manifest.mcp_server.end_point` 是公网可访问 URL。若当前配置仍是本地或内网 endpoint，停止真实上传并要求用户提供可用于云构建的公网 MCP URL。

### 轮询构建状态

如果 upload 输出表示构建仍在进行，或需要确认最终状态，执行：

```bash
dbx app artifacts status \
  --version-tag <version_tag> \
  --poll \
  --json
```

构建失败时，把失败原因、`artifact_build_error_info` 和 `log_id` 告知用户，不要继续假设成功。

### 输出平台版本详情 URL

构建成功后输出：

- `app_id`
- `version_tag`
- 平台版本详情 URL
- 后续使用 UGC Bot 进行真机预览的指南：
  1. 打开平台版本详情 URL。
  2. 如果该应用没有添加用户的豆包UID进入白名单则需要先添加。
  3. 打开豆包app扫描二维码。
  4. 在移动端设备的浏览器中打开此链接 https://inhouse.doubao.com/bot/2xgttdEs，会自动跳转到豆包中的调试对话中。

该版本详情页扫码并进入 UGC Bot 调试对话的流程统一称为“真机预览”；“真机调试”只用于 `dbx dev` 的设备连接与 Page / Widget 推送。即使命令输出仍使用旧名称，回复用户时也要按此术语纠正。

如果命令输出已经包含版本详情 URL，优先使用命令输出。否则按当前 dbx 平台 base URL 拼接：

```text
<platform_base>/agentic_service/<app_id>/versions/<version_tag>
```

`platform_base` 使用当前 dbx 连接的平台地址；无法确定时，至少输出相对路径：

```text
/agentic_service/<app_id>/versions/<version_tag>
```

后续提审、发布等操作在平台上完成。
