Skip to content

从零发布你的第一个 SaaS(worked example:口语搭子) ​

状态基准:2026-09-03(试点叙事仍是 2026-08-30 ECS-B 真栈;其后 PE 已补齐知识库 Tier B / 支付双通道代码 / 多 realm。真收款与 Google 登录仍未开闸,见 platform-status.md)。 读者:要孵化第一个自营 SaaS 的建设者(人类工程师或 AI coding agent)。 性质:本文是真实跑通的完整叙事——下面每一步都在 2026-08-30 的 ECS-B 真栈上实际发生过,数字、事件、回复摘录全部来自验收证据,不是示例假数据。机制的完整参数表在 saas-mode-b-integration-guide.md(§7 有同源 15 步 checklist),本文负责把它讲成一个故事。 契约事实源:openapi.yaml。


0. 你要造什么 ​

「口语搭子」——一个职场英语口语 SaaS,两个会话 Agent:

Agent人设单价
日常口语陪练咖啡馆场景日常对话陪练10 分/轮
面试模拟官产品经理行为面试英文模拟15 分/轮

用户注册登录、钱包扣点、租户后台——一行代码都不用写。你写的只有:从模板派生的前端(品牌与页面定制)。

1. 平台侧准备(运营动作,15 步 checklist 的 1~7) ​

  1. Keycloak SPA client(public + PKCE,试点 client id agenthub-oral-buddy,当时落在平台 realm agenthub)+ 四个 protocol mapper(aud-… / tenant_id / user_id / permissions)——形状参照 mode-b 指南 §1。新品牌线不要照抄 realm=agenthub:生产默认是每线一个 realm,见 品牌自托管。验收实测:试发 token 的 aud 同时含 oral-buddy 与 console,四 claim 齐。
  2. 建正式租户:运营首登 JIT 自动建个人租户后,POST /tenants 升级正式租户(slug oral-buddy,kind=formal,name=口语搭子)。
  3. 建项目「口语搭子 Web」挂该租户——这是计费归因维度,ID 填进前端 VITE_PROJECT_ID。建项目的 curl 见 hello-agent 教程 §2.1(POST /api/v1/builder/projects;或经 web-builder 界面 Projects 页创建。该端点契约收录登记为跟进项)。
  4. 建模型组(LLM-chat,空组走平台 fallback 即可起步)。
  5. 建双 Agent 并发布(人设 / 模型组 / 单价 10 与 15 / 护栏齐全——单价与护栏强制配对,缺一发布被拒)。

判据:GET /api/v1/app/agents?agent_type=conversation 返回的 items 数组长度 = 2(响应无 count 字段)、points_per_turn 10/15(响应键为 snake_case)。

2. 派生你的前端(checklist 8~11) ​

bash
cd frontend
node scripts/new-saas-app.mjs --name oral-buddy --target ../oral-buddy
  • workspace 依赖二选一(源码内联或私有 registry),填 env(VITE_KEYCLOAK_CLIENT_ID / VITE_KEYCLOAK_URL / VITE_PROJECT_ID…),VITE_USE_MOCKS=true 先离线冒烟。
  • 部署:把 deploy/compose-snippet.yml 的 service 块加进编排(服务名 web-oral-buddy)。验收实测:GET https://<网关>/oral-buddy/ → HTTP 200,登录页标题即你的品牌「口语搭子 · 职场英语口语陪练」。

3. 用户进来(checklist 12~13) ​

  1. 终端用户在你的站点注册 → 平台 JIT 自动建域内用户行;被邀请入域(redeem + active-tenant 切换)后,活跃域 = 口语搭子。
  2. 运营给首批种子积分:tenant_grant 手动入账(现在仍然是对用户的标准形态——PayPal / 微信真收款未开闸,见 payment-and-recharge.md)。验收实测:+200 分,source=tenant_grant,流水 operation_id 可对账(请求体 expires_at 必填)。

4. 见到钱动起来:双轮对话(checklist 14) ​

用户从目录选 Agent 开会话、各发一轮。验收实测(SSE 事件序列 turn_started → turn_delta → turn_completed):

  • 日常口语陪练(扣 10 分),真实上游英文回复开场:

    "Hey there! Welcome to the café. What can I get for you today? We've got a great latte special on right now."

  • 面试模拟官(扣 15 分):

    "Welcome! For a product manager behavioral round, let's kick off with a 1-minute English self-introduction. …"

每轮 turn_completed 携带 points_charged(10 / 15)——前端展示即扣点回显。

5. 对账(checklist 15):每分钱都能回答「花在哪、买了什么」 ​

以运营身份读 GET /api/v1/billing/points/ledger?user_id=<终端>&project_id=<项目>,验收实测五行流水:

时间线typeamountoperation_id含义
t0manual_adjust+200sm41-grant-…种子入账
t1freeze10turn:25d4ddf8-…陪练轮冻结
t2deduct10turn:25d4ddf8-…陪练轮划扣
t3freeze15turn:1b1cc78a-…面试轮冻结
t4deduct15turn:1b1cc78a-…面试轮划扣

同一 turn 的 freeze/deduct 共享 operation_id;cost_records 另有两行 call_kind=llm 且 project_id 指向「口语搭子 Web」——模型成本也按项目归因。这就是「强治理执行」在你 SaaS 上的样子。

6. 常见卡点(真栈踩过的坑) ​

症状原因与处置
终端用户积分页 403旧环境:种子角色未含 billing 只读 scope。2026-08-30 之后的 saas_user 已含 billing:points:read / billing:ledger:read,新环境应 200。仍 403 则重跑角色种子或查 token permissions
发布被拒(409)单价与五项护栏强制配对,缺一不可(cookbook 计费章)
SSE 一次性整段到达检查网关 proxy_buffering off(模板 nginx 已配,勿删)
切换租户后行为怪active-tenant 响应恒 token_refresh_required: true,客户端必须强制 refresh token(mode-b 指南 §3)

7. 你学到了什么 ​