# AgentHub 基座接入引导 —— 一条产品线从决策到上线的总纲

> **读者**：要把一条 SaaS 产品线接入 AgentHub 基座的团队——业务拍板人、租户管理员（人类工程师）、开发 agent（AI coding agent）、基座平台 owner。四种角色各取所需：本文告诉你**全局长什么样、每一步谁做、做到什么程度算过关**。
> **定位**：接入总纲（入口文档）——阶段划分、人机分工、步骤清单、坑清单；每一步的机制细节下沉到专题文档，本文不重复。先读 [`platform-status.md`](./platform-status.md) 确认「现在能承诺什么」，再回本文走流程。
> **状态基准**：2026-09-08。底稿：英语陪练 SaaS 接入评估（2026-09-07~08，含生产重部署验证与七步人工清单三方对齐）；关键端点 / 字段已对 `ai_develop` 代码逐一核验。
> **机器读者**：本文在 [`llms.txt`](./llms.txt) 索引内；AI 开发 agent 另读 [`ai-agent-integration-guide.md`](./ai-agent-integration-guide.md)。
> **配套 Skill**：本引导有可下载的 agent skill 版——装进你的开发 agent（Claude Code / ZCode / Trae）即可人机协同跑流程，下载与安装见 §9。

---

## 0. 一页纸心智：三个阶段、四类角色、两条不变式

**接入 = 三个阶段**：

```
① 拍板（§1）──► ② 演练期 S0：平台 realm 走通最小闭环（§2~§4）──► ③ 正式期：品牌 realm 上线重跑（§5）
```

- **① 拍板**：定业务值（slug、单价、积分、护栏、模型选型）——没人能替你定，但定错了代价最大的只有 slug（不可逆）。
- **② 演练期 S0**：在基座生产环境的**平台 realm** 上，把「注册 → 租户 → 项目 → 模型 → 积分 → 发布 → 实测」最小闭环走通。目的：验证选型与流程，产出可复用的配置记录。
- **③ 正式期**：品牌域名 + 品牌 realm 就绪后，**全部步骤在新 realm 重跑一遍**（数据不迁移，见不变式 1），产品线以自有域名上线。

**四类角色**（分工原理与边界见 §3）：

| 角色 | 凭据 | 干什么 |
|---|---|---|
| 业务拍板人 | — | 定 §1 全表：slug、单价、积分、护栏数值、模型选型、产品线形态 |
| 租户管理员（人） | Builder UI / tenant_admin JWT | §2 步 1~7 的自助操作：租户升级、项目、模型注册 + 路由、M2M 签发、发积分 |
| 开发 agent（AI） | M2M client_credentials | Agent 建 / 改 / 删 / 发全生命周期、dry-run、SOP / KB / skill / tool（§3 白名单；运营期可全量代跑，边界见 §3.5；边缘机机器面初始化见 §5.1） |
| 基座 owner（平台运维） | 部署面 | 重部署生产、建品牌 realm、Google IdP / SMTP 开闸、网关接线（§5） |

> **术语约定**：文中「你」＝接入方团队（SaaS 产品线一方，人类工程师视角，即本文读者）——通常身兼「业务拍板人」与「租户管理员」两角；表格「谁」列中的「人」＝租户管理员；「基座 owner」＝平台运维方，与接入方是**两方**（单人身兼两角时也按角色区分理解）。AI 一律写作「开发 agent」。

**两条不变式（违反必返工）**：

1. **租户与 realm 绑死**：token 的 realm ≠ 租户归属 realm → 403（ADR-0063 R1）。品牌 realm 上线后，S0 在平台 realm 建的租户 / 项目 / 模型 / Agent **不会迁移**——这正是「演练 → 重跑」两阶段的由来。
2. **租户 slug 全局唯一且永不可改**（`uk_tenant_slug`，PATCH 只能改 name；格式 `^[a-z0-9][a-z0-9-]{1,62}$`；换租户 = 全部用户钱包迁移）。演练期用 `<slug>-s0`，把正式 slug 留给品牌 realm。

---

## 1. 阶段①：拍板清单

接入动工前定完这张表。全部是**业务值**，平台侧不代定；标 ⚠ 的项定错代价高或需要在演练期收口。

| 决策项 | 要点 | 参考 |
|---|---|---|
| 通道 | 自营 / 孵化 → **模式 B**（浏览器 JWT 直连，ADR-0058 唯一仲裁路线）；自带存量用户体系的外部二开方 → 模式 A | [总索引 30 秒分流](./README.md) |
| ⚠ 租户 slug / name | slug 永不可改；演练 `<slug>-s0`、正式 slug 预留 | §0 不变式 2 |
| 项目 name / slug | 项目 = 计费归因维度；一可多产品各一项目 | §2 步 3 |
| 模型选型 | chat 主模型（必须自注册，见 §4.1）；vision（`capabilities:["vision"]`）；stt / tts / image_gen 按需；embedding（KB 用，`embedding_dim: 1536` 硬约束） | §4.4 |
| 全部单价 | llm / embedding 双价（per-1M token + 按次）；stt / tts / image_gen 按次配对价；轮次价 `points_per_turn` | §4.2 |
| 护栏五项 | `max_input_tokens` / `max_attachments` / `max_tool_calls` / `max_sop_invocations` / `turn_timeout_seconds` 全必填（建议 `turn_timeout_seconds ≥ 180`）；多模态另开 `max_images_per_turn` / `max_attachments > 0` | — |
| 内容护栏 | `off` / `shadow` 二选一（enforce 未上线）；演练期建议 `shadow` 只审计不拦截 | [platform-status](./platform-status.md) |
| 语音人声 | speech 组价 + `voice`（如 `longanyang`，已实证可用） | — |
| 种子积分数额 | 演练期小额即可；按**用户**发不是租户池（§2 步 5） | — |
| ⚠ 产品线入口形态 | **路径**（`<品牌域>/english/`，平台默认、一张证书、零 CORS）vs **子域**（`english.<品牌域>`，需通配证书 / DNS-01、每子域一个 server 块、KC 手工补 Redirect URI）。共享 / 隔离行为两形态完全一致，差异只在边缘工程量。**必须在建品牌 realm 之前定**——建完再改动 KC 和信任注册表 | §5.1 |
| 部署形态 | 品牌自托管边缘为默认（ADR-0063 D10）：一品牌域 = 一 realm = 一运营域租户 + 一台自己的服务器 | [品牌自托管接入标准](./brand-self-hosted-deployment-guide.md) |

---

## 2. 阶段②：S0 演练七步（平台 realm 最小闭环）

### 2.0 前置：确认基座生产是最新版

自助表单的关键能力（模型注册收单价、发布 preflight、`routes:effective`）依赖平台近期修复。**动手前确认**：让基座 owner 从 `ai_develop` 重部署生产（或先在 testbed 演练）。线上是旧版的信号：

- 模型注册表单**没有单价字段**（旧版不收价 → 非 LLM 模态首调 500）；
- 发布**没有 preflight 409**（缺项不报中文明细）；
- `GET /api/v1/builder/routes:effective` 返回 404 而非 401（401 = 端点在、待鉴权；404 = 旧版无此端点）。

### 2.1 七步清单

| # | 谁 | 操作 | 完成判据 | 关键事实 |
|---|---|---|---|---|
| 1 | 人 | 打开 `https://<基座域>/builder/` 注册：KC 托管页，**邮箱即用户名**（`registrationEmailAsUsername` + verifyEmail），必须真实可控邮箱；首登 JIT 自动建平台用户 + 个人租户，自动获 tenant_admin 级自助 scope，**无需任何人审批** | 能登录 Builder，`GET /api/v1/me` 200 | Google 登录非硬依赖，邮箱注册即可走完全部自助步骤 |
| 2 | 人 | 租户升级 formal：Builder 引导页（或 `POST /api/v1/tenants` `{name, slug}`），slug 用 `<slug>-s0` | 租户 kind=formal | **硬顺序：必须先于步 5/6**（发积分与 M2M 签发都要求 formal 租户）；slug 永不可改 |
| 3 | 人 | 建项目（Builder Projects 页或 `POST /api/v1/builder/projects` `{name, slug}`），**记下返回的 `project_id`** | 拿到 project_id | 它就是前端 `VITE_PROJECT_ID` / `AGENTHUB_PROJECT_ID` 的值（**不是 slug**），也是计费归因维度 |
| 4 | 人 | 模型四步：vendor → 模型组 → 注册模型 → 路由（展开见 §4） | `GET /api/v1/builder/routes:effective` 生效、无未计价红标 | 模型 / 路由是**租户级**资源；模态无平台兜底，不建路由的模态发布即被拦 |
| 5 | 人 | 发起始积分：Builder 发放入口（自动生成幂等 `operation_id`）或 `POST /api/v1/billing/points:tenant-grant` | 测试账号余额 > 0、流水可见 | **积分发给用户，不是租户池**（钱包 = (租户, 用户) 唯一）；用哪个账号测试就给谁发，第二个测试账号也要发一份；`expires_at` 必填、`operation_id` 幂等 |
| 6 | 人 | M2M 签发：Builder「设置 → 租户控制台 → M2M 接入凭据」或 `POST /api/v1/tenants/current/m2m-clients` | secret 落位 env_file（600 + gitignore） | **secret 只回显一次**，当场亲手写 env_file，**绝不让 agent 经手**；每租户上限 3 枚；S0 纯浏览器测试（JWT 通道）用不到 M2M，可随时补、不阻塞步 7 |
| 7 | 人建 + agent 可接手 | 建 conversation Agent → Builder「预览」（dry-run，零计费）→ 发布 → Starter 实测 | 见 §6 验收判据 | 发布 preflight 409 的中文 `issues[]` 列出全部缺项；发布产生不可变 `agent_version`，**会话钉死打开时版本** |

执行顺序备忘：1→2→3→4→5→7→6（M2M 随时补）。

### 2.2 演练期可裁剪面

纯文本最小闭环**可跳过**：知识库、stt / tts / image_gen 模态注册、speech 组价、SOP——都是增量能力不是前置，后补不影响已发布 Agent（改版重发即可）。

### 2.3 随手记录（正式期重跑时直接复用）

`project_id` · 各模型 id · 路由组 id · 积分 `operation_id` · M2M `client_id`（secret 只记落位处，不记值）· 全部拍板值（单价 / 护栏 / persona）。

---

## 3. 人机分工：什么必须人手，什么交给开发 agent

### 3.1 分工切面

| 操作面 | 租户管理员（人手） | 开发 agent（M2M） | 基座 owner |
|---|---|---|---|
| 租户升级 / M2M 签发 | ✅ 唯一入口（tenant_admin JWT） | ❌ scope 排除 | — |
| vendor + 模型注册 / 路由 | ✅ **唯一入口**（贴 key、定价） | ❌ `builder:model:write` 刻意排除（只读 `builder:model:read`） | OpenBao 平台兜底 key 注入（可选） |
| 项目 | ✅ 建议（面板一步） | 可（`builder:project:read/write` 在白名单） | — |
| Agent 建 / 改 / 删 / 发 / dry-run | ✅ 可 | ✅ **主力**（`agent:*` 全量；含 versions / agent-teams / bench-agents；单项目 Agent 数量无限制） | — |
| SOP / KB / skill / tool | ✅ 可 | ✅（对应读写 scope） | — |
| 种子积分 | ✅ Builder 发放入口 | ✅（`billing:points:tenant_grant` 在白名单） | ops 级 `points:grant`（跨租户） |
| API-Key 交付 | — | ✅（`delivery:api_key:*`） | — |
| 品牌 realm / DNS / TLS / SMTP / Google IdP | — | — | ✅（§5） |
| 品牌资料（首行造册 / 日常录入） | 录入 ✅（运营租户管理员 · builder 品牌设置页或 `PATCH /api/v1/brand/profile`） | ❌ `brand:profile:write` 挂 tenant_admin 族 | 造册 ✅（建租户时勾选「设为品牌运营租户」或 seed；hello-agent §14） |

切分原理：**碰密钥的操作不进机器凭据**——这是密钥安全边界，不是能力缺陷。

### 3.2 M2M scope 白名单（代码事实源 `M2M_PERMISSIONS`）

**含**：`agent:read/create/update/delete/publish` · `sop:read/create/update/publish/debug` · `builder:project:read/write` · `builder:model:read` · `builder:knowledge:read/write` · `builder:skill:read/write` · `builder:tool:read/write` · `builder:policy:read` · `builder:budget:read` · `builder:billing:read` · `delivery:api_key:read/write` · `billing:points:tenant_grant/read` · `billing:ledger:read` · `billing:membership:read/write` · `task:read/submit`。

**刻意排除**（及原因）：

- `builder:model:write`——模型 / 路由 / key 留给人手（SaaS 孵化分工）；
- `billing:points:grant`——ops-only 跨租户入账；
- `tenant:*` / `identity:*` / `ops:*`——管理面；
- `conversation:*`——headless 会话通道走 API-Key（`X-AgentHub-Api-Key`），不走 JWT。

### 3.3 M2M 使用纪律

- 每租户上限 **3 枚** active client；建议 runtime 后端与开发自动化**各一枚**、剩一枚备用，泄露即 rotate（`POST .../m2m-clients/{id}/rotate`，新 secret 只回显一次、旧 secret 即时失效）。
- 第一枚 label 建议 `dev-automation`。
- mint 机制：KC 建 confidential client + service account，`tenant_id` / `user_id` / `permissions` 写入 service account 属性（与 SPA client 同一套 mapper），client_credentials 换 JWT 后过同一条 AuthMiddleware + 租户 RLS。
- **影响面警示**：M2M 凭据能发积分、能发布面向用户的 Agent——泄露影响面大，分离持证。

### 3.4 迭代模型（为什么「先演练后正式」不耽误开发）

每次 publish 产生**不可变 `agent_version`**；会话钉死打开时版本，re-publish 只影响新会话。所以正确姿势：SaaS 开发到哪，开发 agent 经 M2M 改到哪、发到哪——persona、skill 绑定、`points_per_turn`、护栏、speech 价**均为每次发布可变参数**。发布 preflight 409 的 `issues[]` 是结构化缺项清单，开发 agent 可程序化消化补齐后自动重试。会话通道的 API 细节见 [会话运行时协议](./conversation-runtime-protocol.md)。

### 3.5 时间维度：什么时点起可以整体交给开发 agent

| 时段 | 开发 agent 的边界 | 原因 |
|---|---|---|
| S0 建立期（步 6 签发 M2M 之前） | **陪跑不代跑**：生成 curl、核对 `routes:effective` / preflight 输出、维护 §2.3 记录清单；执行凭据（浏览器登录态）留在人手 | M2M 凭据尚不存在，浏览器 JWT 通道不属于机器凭据 |
| M2M 就绪后（步 6 起，直至正式期长期运营） | **运营面全量代跑**（下清单），人手零介入 | §3.2 白名单 |

M2M 就绪后**可整体交给开发 agent 经 API 自动执行**的清单：

- **会话 Agent 全生命周期**：创建（persona、模型组绑定、`points_per_turn`、护栏五项、speech 组价、`content_guardrail`）、PATCH 迭代、dry-run 冒烟、发布（preflight 409 `issues[]` 程序化消化重试）、删除、版本查询；
- **SOP**：创建 / 更新 / 发布 / 调试（`sop:*` 全套）；
- **KB / skill / tool**：创建、配置、绑定到 Agent（`builder:knowledge/skill/tool:write`）；
- **积分与流水**：tenant_grant 发放、余额 / ledger 只读（SaaS 后台代发奖励积分等场景）；
- **API-Key 交付与项目读写**（`delivery:api_key:*` / `builder:project:*`）。

**永远留在人手**（§3.1 的密钥面，长期不变）：模型注册 / API key / 路由（`builder:model:write` 刻意不在 M2M）、租户与身份面、M2M 自身的 mint / rotate、业务拍板值变更。

> SaaS 自有后端以服务身份调基座（代用户扣点、后台跑 Agent）用**同一枚 M2M 凭据**经 VPC 内网调用——见 [品牌自托管指南 §3.6](./brand-self-hosted-deployment-guide.md)。

---

## 4. 模型与路由配置要点（步 4 展开）

### 4.1 两把 DashScope key 不可混用

| 用途 | key | 端点 |
|---|---|---|
| chat（含 vision）/ embedding | **Token Plan 网关 key**（`sk-sp-` 前缀） | compatible-mode（`token-plan.*.maas.aliyuncs.com/compatible-mode/v1`） |
| stt / tts / image_gen | **经典按量 key** | `dashscope.aliyuncs.com` |

`sk-sp-` key 打经典端点会 `InvalidApiKey`；反向同理。**生产平台的 fallback chat key 是占位——chat 主模型必须自己注册，不能指望兜底**（testbed 环境有平台兜底 key 可空组起步，生产行为不同，勿混淆）。模型 API key 在注册表单直接贴（`api_key: SecretStr` → 平台代存 OpenBao，只回 opaque `vault_secret_ref_id`，永不回显 / 不落 DB / 不进日志），**不需要运维注入**；租户级 vendor 解析优先于服务器 env。

### 4.2 计价配对（漏了发布即被拦）

| 模型类型 | 必填价 | 字段 |
|---|---|---|
| llm / embedding | **per-1M token 价**（人民币分 / 百万 token，ADR-0022 SSOT） | `pricing_input_per_1m_cents` / `pricing_output_per_1m_cents` |
| stt / tts / image_gen | **按次价配对** | `unit_price` + `price_unit`（stt / tts = `second`，image_gen = `image`） |

半配对（只填一半）被 422 拒。存量模型改价走窄通道 `PATCH /api/v1/builder/models/{id}`——恰好四字段：`unit_price` / `price_unit`（仍须成对）/ `capabilities` / `status`；per-1M token 价与身份字段不可经此修改。

### 4.3 模型四步与路由

1. **vendor**：DashScope 已内置可直接选（否则 `POST /api/v1/builder/model-vendors` `{code, api_base, protocol_family}`）。
2. **模型组**：注册模型时 `group_id` 必填；**同组唯一路由**约束下，语音 / 画图等模态要独立分组；注册后界面有「一键填入」路由引导。
3. **注册模型**：`POST /api/v1/builder/models`（`ModelRegisterIn`：`group_id` / `vendor` / `name` / `model_type`（`llm|embedding|tts|stt|reranker|image_gen|video_gen`）/ `context_max_tokens` / `api_key` / 两类价 / `capabilities`；可选 `Idempotency-Key`）。连通性 probe 在事务提交后执行。
4. **路由**：`POST /api/v1/builder/routes` `{group_id, primary_model_id, fallback_model_id}`。chat 组 **primary = chat 主模型、fallback = vision 模型**（带图轮次独占 vision 端点，纯文本走主模型）。

**模态无平台兜底**：每个要用的模态都要有自己的路由；缺路由该模态发布被 preflight 409 拦（issues[] 中文明细）、运行期调用 503。**发布表单里的「模型组绑定」不参与运行时路由**——运行时只认租户级 Model Routes。配置后用 `GET /api/v1/builder/routes:effective` 核对：实际生效路由、inert 原因（如 vendor 网关不可解析）、主模型计价 / 能力一屏可见。

### 4.4 实证选型参考（DashScope，本平台真栈验证过）

| 模态 | 型号 | 计价 | 备注 |
|---|---|---|---|
| chat 主模型 | 自选（compatible-mode 系） | llm 双价 | 生产 fallback 是占位，必须自注册 |
| vision | `qwen3-vl-plus` / `qwen-vl-max` | llm 双价 + `capabilities:["vision"]` | 作 chat 路由 fallback；缺 vision 路由时图片轮次出「降级占位」黄条（警告非错误） |
| stt | `qwen3-asr-flash` | `unit_price` + `second` | — |
| tts | `cosyvoice-v3-flash` | `unit_price` + `second` | voice `longanyang` 实证可用 |
| image_gen | `qwen-image-3.0-pro` | `unit_price` + `image` | — |
| embedding | 自选 | 双价 | `embedding_dim: 1536` 硬约束（KB 创建参数） |

---

## 5. 阶段③：正式期迁移（品牌 realm 上线）

### 5.1 前置（品牌侧 + 基座侧）

| 项 | 谁 | 要点 |
|---|---|---|
| 品牌域名 + DNS | 品牌方（你）· 人工 | `@` / `www` A 记录指向品牌边缘服务器（www 301 → @）；不需要 api. / auth. 子域。域名商 / 云控制台凭据操作，**不交 agent** |
| 边缘服务器（控制面） | 品牌方（你）· 人工 | 购置（与基座同区域同 VPC 建议，如 SGP）、该机安全组放通 80/443、在操作机 `~/.ssh/config` 建 ssh 别名——云控制台与新机引导期操作，**不交 agent** |
| 边缘服务器（机器面初始化） | 品牌方（你）· **可交开发 agent** | ssh 通道建立后：装 nginx、渲染 `deploy/brand-edge/nginx.brand-edge.example.conf` 六占位符（`/` 本机直出前端 + `/api/` `/auth/` 同源反代基座 VPC 内网，零 CORS）、放置前端构建产物、`nginx -t` + reload、验收探针。**先例 = 生产部署同款**：agent 经 ssh **别名**执行命令，私钥留在操作机 `~/.ssh/config`、凭据不进 agent 会话；可直接粘贴给 agent 的初始化提示词见 [brand-server-initialization.md](./how-to/brand-server-initialization.md)（含人类侧前提清单与验收断言） |
| TLS | 品牌方（你）· 部分可交 agent | HTTP-01 单证书在边缘机上自动签发续期（机器面，agent 可执行）；子域形态的通配证书 DNS-01 需域名商 DNS API 凭据——凭据纪律同 M2M secret，不进 agent 会话 |
| SMTP | 品牌方（你）· 人工 | 品牌域 SPF / DKIM / DMARC（注册邮箱验证依赖）；DNS 面板操作——展开步骤见 [email-auth-spf-dkim-dmarc.md](./how-to/email-auth-spf-dkim-dmarc.md) |
| Google OAuth client（可选） | 品牌方（你）+ 基座 owner | 非硬依赖，邮箱注册即可；凭据到位后 owner 在 KC 管理台 enable |
| 建品牌 realm | 基座 owner | 见 5.2 |
| 安全组 | 基座 owner | 基座实例放通品牌边缘内网 IP → 443 |

### 5.2 建 realm（一条命令 + 一个陷阱）

```bash
# 单 client（推荐默认）
new-realm.sh <realm> <品牌域> --client-id <realm>-web
# 多前端 client 时必须一次传全 audiences，漏了第二个 client token 403
new-realm.sh <realm> <品牌域> --client-id learner-web --audiences learner-web,admin-web
```

- **单 / 双 client 裁定参考**：线内共享登录 / 钱包由 realm（SSO 锚 `<品牌域>/auth`）+ 租户（`UNIQUE(tenant_id, user_id)`，流水按项目归因）机制保证，**与 client 数量无关**——单 client 够用就不要多建；仅当需要管理端 / 学员端会话与 audience 隔离时才加 client，**加时必须同步补全注册表 audiences**。
- **陷阱**：脚本只建**一个** SPA client（5 mapper + PKCE S256）；平台验签按信任注册表 `audiences` 校验（禁合并），第二个 client 不在 audiences 里 → 403。其本体（5 mapper + Redirect URI + PKCE）随后 KC 管理台手工补建（`kc-spa-clients-reconcile.sh` 收敛器只管平台 realm，不管品牌 realm）。
- `frontendUrl` 平台强制写入勿删（没有它 issuer 会取请求 Host，PE3-5 实证）；品牌 realm 的 issuer = `https://<品牌域>/auth/realms/<realm>`——**域名 / DNS / 边缘不存在之前这个 realm 建不了**。
- 生效时点：registry 在 api 启动时为空的首个 realm 需 restart api；已登记过 realm 的部署（生产现状）后续 realm 约 300s（`KEYCLOAK_REALM_REGISTRY_TTL`）自动生效。

### 5.3 重跑与上线

在品牌 realm 用**正式 slug** 重跑 §2 全部七步（除模型 key 需重贴外都是表单活；§2.3 的记录直接复用）。用户侧前端按 [模式 B 指南](./saas-mode-b-integration-guide.md) 派生部署到品牌边缘；八步上线细则见 [品牌自托管接入标准](./brand-self-hosted-deployment-guide.md)。

**品牌资料**（可选增强，当前「可录不可见」）：建租户时由基座 ops 勾选「设为品牌运营租户」完成首行造册（或运维 seed），随后运营租户管理员在 builder 品牌设置页录入品牌名 / slogan / 简介 / 明暗 logo / 明暗条幅（API 形态见 [Hello Agent §14](./tutorial/hello-agent.md)）。渲染接线（博客品牌呈现 BA2 / KC 登录主题 F7）未完成前，录入内容不出现在任何对外页面——不阻塞上线。

---

## 6. S0 验收判据（走通即通过）

- [ ] dry-run 200 且**零扣点**（Builder 预览正常回复）；
- [ ] 发布成功，版本状态 published；
- [ ] Starter（或薄壳前端）选 Agent 开会话、发一轮：SSE 帧完整（`turn_started → turn_delta* → turn_completed`）；
- [ ] `turn_completed` 携带 `points_charged` = `points_per_turn`；余额按价减少；
- [ ] ledger 可对账：同轮 `freeze` / `deduct` 共享 `turn:*` operation_id（worked example 见 [first-saas 教程 §5](./tutorial/first-saas.md)）；
- [ ] `POST /api/v1/app/conversations/{id}:end` 200，会话闭合；
- [ ] （可选）清零积分后发一轮 → 402 `POINTS_INSUFFICIENT`（零副作用，失败轮次全额退）。

---

## 7. 坑清单（按首次踩到的阶段排序）

| # | 阶段 | 坑 | 症状 | 规避 / 处置 |
|---|---|---|---|---|
| 1 | 拍板 | slug 永不可改 | 想改 slug 无 API | 演练 `<slug>-s0`，正式 slug 预留（§0 不变式 2） |
| 2 | S0 前置 | 线上是旧版 | 表单没单价字段 / 无 preflight / `routes:effective` 404 | §2.0：让基座 owner 重部署；外部快照文档（含本仓历史版本）可能滞后，**以代码 + 本文档树 curl 形状为准** |
| 3 | 步 4 | 两把 DashScope key 混用 | `InvalidApiKey` | §4.1 分 key 分端点注册 |
| 4 | 步 4 | 以为有平台兜底 | chat 503 | 生产 fallback key 是占位，chat 必须自注册 |
| 5 | 步 4 | 模态缺路由 / 缺价 | 发布 409（issues[] 中文明细）或调用 503 | 这是护栏不是故障；按 §4 配齐再发 |
| 6 | 步 4 | 混淆模型组绑定与运行时路由 | 改了绑定「没生效」 | 运行时只认租户级 Model Routes；用 `routes:effective` 核对 |
| 7 | 步 5 | 积分发错对象 | 测试账号 402 | tenant-grant 按**用户**发；每个测试账号都发 |
| 8 | 步 6 | M2M secret 丢失 | 无法再取 | 只能 rotate（旧 secret 即时失效）；纪律见 §3.3 |
| 9 | 步 7 | 旧会话跑旧版 | 改版后「没生效」 | 会话钉打开时版本；验证新版开新会话 |
| 10 | 步 7 | dry-run 路径写错 | 404 | 实际 `POST /api/v1/builder/agents/{id}/dry-run`（历史文档的 `/chat-dry-run` 已滞后） |
| 11 | 步 7 | 新用户看不到 Agent | 目录空 | `GET /api/v1/app/agents` 租户 RLS 隔离；新注册用户 JIT 进个人租户——需 membership 邀请入域 + 发积分，或全程用自己账号测 |
| 12 | 步 7 | 新用户首调 tenant 端点 404 | `Local user not found` | 首次登录先过一次 `GET /api/v1/me`（JIT 建本地用户行） |
| 13 | 正式期 | 多 client 漏 audiences | 第二个 client token 403 | §5.2 建 realm 时 `--audiences` 一次传全 |
| 14 | 正式期 | token issuer 不匹配 | 401 | token 经品牌边缘 / 网关的 `/auth/` 取，勿直连 KC 内部端口；`frontendUrl` 勿删 |
| 15 | 正式期 | 子域 Redirect URI 未配 | 登录回跳失败 | 子域形态建 realm 后在 KC 管理台手工补各子域 Redirect URI + Web Origin |
| 16 | 通用 | vision 无路由 | 图片轮次「降级占位」黄条 | 警告非错误；要原生图片理解就配 vision 路由 |

---

## 8. 文档地图（按任务取用）

| 你要做什么 | 文档 |
|---|---|
| 确认现在能对用户承诺什么 | [platform-status.md](./platform-status.md) |
| 前端薄壳派生 + OIDC 接线 + 15 步 checklist | [saas-mode-b-integration-guide.md](./saas-mode-b-integration-guide.md) |
| 品牌域 / realm / 边缘八步上线 | [brand-self-hosted-deployment-guide.md](./brand-self-hosted-deployment-guide.md) |
| 给品牌服务器做机器面初始化（可粘贴 agent 提示词） | [how-to/brand-server-initialization.md](./how-to/brand-server-initialization.md) |
| 配品牌域邮件防伪（SPF/DKIM/DMARC）+ realm SMTP | [how-to/email-auth-spf-dkim-dmarc.md](./how-to/email-auth-spf-dkim-dmarc.md) |
| 搞懂品牌·realm·用户·租户·项目·URL 的绑定关系（心智模型） | [brand-line-binding-model.md](./brand-line-binding-model.md) |
| 外部二开方（模式 A）逐条 curl | [saas-integration-cookbook.md](./saas-integration-cookbook.md) |
| 会话 SSE 帧与轮次状态机 | [conversation-runtime-protocol.md](./conversation-runtime-protocol.md) |
| 积分 / 充值 / 对账 | [payment-and-recharge.md](./payment-and-recharge.md) |
| 知识库检索（演练期可跳过） | [knowledge-base-retrieval.md](./knowledge-base-retrieval.md) |
| 全链 worked example（口语搭子） | [tutorial/first-saas.md](./tutorial/first-saas.md) |
| 平台全貌 + 首个 Agent curl 教程 | [tutorial/hello-agent.md](./tutorial/hello-agent.md) |
| AI coding agent 心智与已知坑 | [ai-agent-integration-guide.md](./ai-agent-integration-guide.md) |
| ops 侧开通（M2M 人工通道 / API-Key / Webhook） | tenant-onboarding-runbook |

---

## 9. 配套 Skill：把本引导装进你的开发 agent

本引导提供**可下载的 agent skill**（单文件自包含，含分工铁律、断点续跑 state 文件、七步「人做 / agent 做 / 判据」协同流程、M2M 就绪后的代跑清单、验收 checklist 与坑速查）。开发人员下载后装进自己的 AI 开发 agent，即可按 §3 的分工纪律协同作业、一步步完成接入。

**下载**（raw markdown 直出，单文件即完整 skill；测试环境替换为实际文档站地址）：

```bash
curl -o SKILL.md https://docs.bhsl.cc/guides/skills/agenthub-onboarding/SKILL.md
```

安装位置（SKILL.md 约定通用；项目级 = 只在当前仓库生效，个人级 = 本机全部会话生效）：

| agent | 项目级 | 个人级 |
|---|---|---|
| Claude Code | `.claude/skills/agenthub-onboarding/SKILL.md` | `~/.claude/skills/agenthub-onboarding/SKILL.md` |
| ZCode | `.zcode/skills/agenthub-onboarding/SKILL.md` | `~/.zcode/skills/agenthub-onboarding/SKILL.md` |
| Trae | `.trae/skills/agenthub-onboarding/SKILL.md` | — |
| 其他 / 免安装 | 下载后直接对 agent 说「读 SKILL.md 并按它执行」 | — |

一键安装示例（Claude Code 项目级）：

```bash
mkdir -p .claude/skills/agenthub-onboarding \
  && curl -o .claude/skills/agenthub-onboarding/SKILL.md \
     https://docs.bhsl.cc/guides/skills/agenthub-onboarding/SKILL.md
```

装好后对 agent 说「接入 AgentHub」或「开始 S0 接入」即可触发；skill 会先探测阶段（识别 `agenthub-onboarding.state.md` 断点续跑），再按七步协同推进。
