238 lines
31 KiB
Markdown
238 lines
31 KiB
Markdown
---
|
|
date: 2026-06-30
|
|
topic: 配置控制面
|
|
status: 草稿 · 生态原生架构重写(经多轮源码核查)· Opus 复评已过(承重墙 W1/W2/W3 + 第3处 SoT 偏离 + 次要 S1-S6 已在文内修掉)· 生产基建 build-vs-buy 尽调采纳(§3.7:Nacos/RocketMQ/Sentinel,AGENTS.md §3.1 同步反转)· 待创始人评审 → writing-plans
|
|
sot-impact: 修订 生成引擎运行时(SoT §5.2/§5.8/ADR-4 按本设计修正,已回写(2026-07-03,W-DSGN doc-sync 回写图说 §5.2/§5.8/ADR-4/A13/§二补④))
|
|
上级: docs/plans/2026-06-25-生成引擎统一执行计划-AgentScope三档-plan.md
|
|
关联:
|
|
- agentscope==2.0.2:app/_service/_chat.py(每 POST 从存储现装配 agent+model=per-POST 热重载)· app/_router/_agent.py(/agent CRUD:name/system_prompt/ContextConfig/ReActConfig)· app/_router/_session.py(/session:ChatModelConfig=model/type/credential/parameters)· agent/_agent.py(reply 循环 :595-620 finish 点)· types/_hook.py + middleware(reply/reasoning/acting/model-call 钩点,可 intercept+modify)· observability/studio_sink.py(Studio 桥)
|
|
- tier2/gen-worker/service/control_plane.py(现有外层 resume,将改为 middleware)· worker/middleware.py(CircuitBreakerMiddleware 软/硬预算)· worker/run.py:811(run_gates 纯函数,将包 MCP)· worker/store.py(自建 MySQL+MinIO 成品归档,保留)· worker/toolkit.py(九工具)
|
|
- cheap-worker/cheap_studio.py · _bootstrap.py(便宜档进程内路,将归并 Service)
|
|
- game-cloud huijing-module-infra / huijing-module-bpm(yudao:配置中心宿主 + 审批)· game-admin/src/views/wanxiang/(配置编辑面 + genMonitor)
|
|
- .claude/skills/agentscope-skill · .agents/knowledge/agentscope-2.0-facts.md(AgentScope 事实源)
|
|
- 设计 SoT:docs/architecture/架构/生成引擎/agentic运行时架构图说.md §5.2 / §5.8 / ADR-4 / A13 / §二补④(GitOps 口径 + /agent-CRUD-管配置 假设 + resume=外层循环叙述,三处均须据本设计修正,见 §6)
|
|
- commit hash:待收口填
|
|
图清单: [图0 一图看懂, 图1 四层归属, 图2 配置热配数据流, 图3 构建序]
|
|
---
|
|
|
|
# 配置控制面 · 功能设计
|
|
|
|
## 0 一图看懂
|
|
|
|
(图0 概览 SVG 待补)
|
|
|
|
- **核心思想**:生成统一走 AgentScope Service(`/chat`),配置(prompt / 模型 / 参数 / max_iters)经 `/agent`+`/session` 由框架**原生 per-POST 热重载**——改完下一次生成即生效、零重启(每 POST 从存储现装配 agent 与 model,无进程缓存,已读源码验证)。**配置中心是它之上的版本化治理层**:game-cloud 的 **yudao 管治理(鉴权/creator/BPM/编辑 UI)与版本账本(版本行落 MySQL、含 prompt 正文)**,改→定版→激活时**双路下发**——prompt/模型这一路 PATCH 进 `/agent`+`/sessions`(写 AgentScope Redis),预算/阈值那一路 publish 进 Nacos 生效 dataId、由 worker 经 genconfig 门面(NacosHotConfig 作热源)热读。Nacos 在此只承预算/阈值那一路的生效下发,不再是版本账本(创始人 2026-07-02 拍方向 B:prompt 正文放不进 Nacos 100KB 上限、定版要原子,账本挪回 MySQL,详见阶段二设计)。生产基建采 **Spring Cloud Alibaba 原生三件套**——Nacos(配置+服务发现)、RocketMQ(异步 gen 队列)、Sentinel(Java 准入侧流控 ≤15):**Java 管准入+队列,Python 只服务 `/chat`**(见 §3.7)。护城河(九门 / 预算 / 续修)不另起框架外的编排,而是**做成 AgentScope 洋葱里的 middleware 与 MCP 工具**、留自建(无现货品类)。成品源工程归档保留自建 `store.py`(MySQL+MinIO)。
|
|
- **边界**:管热配置策略类(模型路由 / 预算 / max_tokens / thinking / prompt / skills / 可热阈值)。**SAA 11 roles 不接**(非 MVP runtime);硬代码机制、版本化安全件、phase-3 拖拽建图不进;受治理发版审批 + 运营 DB 审计归放量后。
|
|
- **成功**:本会话手改过的每个旋钮(模型 M3↔glm-5.2、预算 ¥10↔¥49、max_tokens、prompt)都能在配置中心改一版、激活、下一次生成即生效、可回滚、可查谁何时改;一组协同旋钮作一个配置集成组激活(静默期语义)。
|
|
|
|
## 1 意图与目标
|
|
|
|
### 1.1 意图
|
|
|
|
设计早承诺"改 prompt、换模型、调 skill 不发版"(SoT §5.2),但执行计划把这条基建写成"按需生长",结果只有 prompt 一块以文件热取落地,模型路由 / 预算 / 阈值全停在硬编码。本会话调一款便宜档游戏,四个旋钮里三个是改代码重启:
|
|
|
|
| 本会话改的旋钮 | 改代码还是配置 | 代价 |
|
|
|---|---|---|
|
|
| prompt | 配置(C2a 文件热取) | scp,零重启 |
|
|
| 模型 M3→glm-5.2 | 代码(`_bootstrap.py`) | 改码 + 重启 |
|
|
| 预算 ¥10→¥49 | 代码(`cheap_studio.py`) | 改码 + 重启 |
|
|
| max_tokens | 代码(`run_studio` 默认参) | 改码 + 重启 |
|
|
|
|
而且是在 live worktree 上 SSH 手敲改的。这条基建不再按需生长,在恢复质量与 tier2 go 之前一次性建成。
|
|
|
|
架构方向经多轮源码核查收敛到**生态原生**,而非在项目自建的进程内配置上再糊一层:护城河(九门 / 预算 / 续修)可解耦成框架的扩展点(MCP + middleware),所以生成不必焊在进程内、能统一走 AgentScope Service;而 Service 对 `/agent`+`/session` 的配置**每次生成从存储现装配**,天然就是热重载。据此,配置控制面 = 采框架原生热配 + 在其上加一个版本化管理层,自建面压到最小。
|
|
|
|
### 1.2 目标
|
|
|
|
- **配置即数据、版本可管**:热配置策略类每个旋钮进配置中心,改一版、可激活 / 回滚 / diff,激活即 PATCH 进 Service、下一次生成生效——覆盖本会话手改过的全部硬编码点。
|
|
- **改动可审计、归因到人**:配置中心建在 yudao,登录用户即 `creator`,权限门管写,审计随版本原生。
|
|
- **协同旋钮成组激活**:一组相关旋钮作一个配置集一次激活;取静默期语义(激活时确保无在跑局、或只对下一批新生成生效),不强求机制级原子——两次独立 PATCH 给不了真原子(见 §3.3)。
|
|
- **护城河用框架扩展点实现**:九门做 MCP 工具、预算与续修做 middleware,在 AgentScope 洋葱里,不另起框架外编排。
|
|
- **观测绑 agent 运行**:每局生成的推理 / 工具调用 / 门裁决 / 成本可回放,在跑 gens / 门 / 预算实时可见。
|
|
|
|
## 2 边界
|
|
|
|
(图1 四层归属 SVG 待补)
|
|
|
|
进控制面的判据采 SoT §5.8 配置三类。
|
|
|
|
| | 进控制面 | 不进 |
|
|
|---|---|---|
|
|
| **热配置策略类** | 模型路由、预算 / 熔断阈值、max_tokens、thinking、prompt、few-shot、skills、max_iters、新增门 observe/enforce 档、压缩比例、RAG 源、记忆模式 | — |
|
|
| **版本化安全构建类** | — | 依赖锁、引擎版本、构建 profile、沙箱类型、权限上限 |
|
|
| **硬代码机制类** | — | 门断言逻辑、熔断机制本体、基线硬门强制、铁律 |
|
|
|
|
**SAA 11 roles 不接**(非 MVP runtime,远期复活再补 Java 客户端)。**管理面只做 phase-1**(配置编辑 + 运行观测);phase-2/3 图编辑属远期。**受治理发版审批(复用 yudao BPM)+ 运营 DB 审计 = 放量后**——放量前创作页置灰、影响面为零,配置改动者是创始人本人、属非关键即时改。**成品源工程归档不进本设计**(保留自建 `store.py`,见 §3.5)。
|
|
|
|
## 3 方案
|
|
|
|
### 3.1 生成统一走 AgentScope Service
|
|
|
|
生成从"进程内直接构造 model + 跑 ReAct"改为统一走 AgentScope Service 的 `/chat`。tier2 已有这条路(`control_plane`);**cheap-worker 从进程内 `cheap_studio` 归并上来**,两档同构。这样配置才能吃上框架的原生热重载(§3.2)。归并是本设计主要迁移工作量;运行开销可忽略(LLM 与门判占大头)。
|
|
|
|
归并范围比"搬个入口"大:cheap-worker 现在是裸 `ThreadingHTTPServer` + 直构 `agentscope.agent.Agent`、**没走 create_app/Service `/chat`**,九门是**生成后 Python pipeline**(非工具/非 MCP)、预算 `rmb_hard_limit=10.0` 硬编码(`cheap_studio.py:156`)——归并 = 上 Service `/chat` + 九门改 workspace MCP + 预算改读配置源(才真热)。另有两处易漏 plumbing:
|
|
- **代理旁路必须保留**:cheap-worker 现走 tier2 `build_model_openai`(带内网代理旁路 + `/v1` 补全 + 从凭据文档取 key);归并后改走框架 `get_model` + 注册 credential,这条新路**必须仍绕过系统 fake-ip 代理**,否则内网 M3 调用直接 502(栽过的确切坑)。
|
|
- **write_whitelist 特化要有落点**:reskin 模式锁 `game-logic.js` 只换皮,是工具权限面、不在 `/agent`+`/session`+middleware 的旋钮表里;归并后它落进 agent 的 permission_context 或写工具的过滤层,迁移时明确指定,否则 reskin 降本主线落不了地。
|
|
|
|
### 3.2 配置热配 = AgentScope 原生 per-POST 热重载
|
|
|
|
已读源码验证:Service 每次 POST `/chat` 都**从存储现装配 agent 与 model**(`_service/_chat.py` 现读 agent_record / session_record,`get_model` 每次新建、无进程缓存),所以改配置下一次生成即生效、零重启。生效粒度 = 每回合;不插进正在跑的回合。
|
|
|
|
| 旋钮 | 存哪 | 改哪个 API | 热 |
|
|
|---|---|---|---|
|
|
| prompt(system_prompt)、压缩比例、tool_result 截断、max_iters | AgentData / ContextConfig / ReActConfig | `/agent` PATCH | ✓ per-POST |
|
|
| 模型、协议(type)、credential、max_tokens、thinking、reasoning_effort、temp | ChatModelConfig | `/session` PATCH | ✓ per-POST |
|
|
| context_size / max_retries | model 构造参数,App 透不进 | 无需热配 | context_size 默认 20 万够、max_retries 小默认够 |
|
|
| stream | model 构造参数,App 透不进 | 无需热配、但要按档定 | **不是"默认就行"**:tier2 现故意 `stream=False`(治 M3 thinking 内联截断);与协议/模型有真实交互 → 作 per-tier Service 启动默认显式定,既非热旋钮也非无关项 |
|
|
|
|
协议 anthropic/openai 由 `ChatModelConfig.type`(凭据类型)选、不按模型名自动——同一 M3 两协议都能走。
|
|
|
|
**配置面有三个,不止 /agent+/session**:工具 / MCP / skill 不在 AgentData 或 ChatModelConfig 里(两个数据模型无此字段),它们挂在 **workspace** 上(`workspace.list_tools/list_mcps/list_skills` 每 POST 现取;REST `/workspace/mcp`、`/workspace/skill` 热管,或 manager `default_mcps`/`skill_paths` 给新 workspace 缺省 seed)。故配置中心热配聚焦 **/agent+/session + middleware 薄读参数**;workspace 上的 MCP/skill **wiring** 属稳定基建、随 Service 部署,不做每局热旋钮。skill 的**内容**(`.agents/skills/*.md`)仍热——agent 运行时 read_file 现读(cheap-worker 每次 fresh、无缓存),改文件下次生成即生效。
|
|
|
|
### 3.3 配置中心 = yudao 治理与版本账本 ⊕ Nacos 生效下发
|
|
|
|
AgentScope 的存储只有"当前配置"(Redis),没有版本历史。配置中心补这一层,职责劈成两半:**yudao 管治理与版本账本**(鉴权 + `creator` 归因、放量后 BPM 审批复用 `huijing-module-bpm`、配置编辑 UI,连同每次定版落下的版本行——版本历史 / 一键回滚 / diff 全借 yudao CRUD/审计原生能力就地做),**Nacos 管生效下发**(长轮询推送 / 客户端磁盘快照兜底 / namespace 隔离,预算/门阈值那一路的热推全靠它)。版本账本早稿曾放 Nacos,创始人 2026-07-02 拍方向 B 挪回 yudao MySQL 版本行——Nacos 单配置默认 100KB 上限扛不住会随 few-shot 长大的 prompt 正文,且定版须同库同事务原子落一行(prompt 正文随行存 `MEDIUMTEXT`),内容出库即成跨系统写;详见阶段二设计 §3.1。这不推翻 build-vs-buy 的"下发机制全买"结论:推送/快照/回滚灰度仍全靠 Nacos,挪回 MySQL 的只是版本行这张普通 yudao 业务表。流向:创始人在 yudao UI 改 → yudao 校验鉴权/走 BPM → 定版落 MySQL 版本行(`creator`/时间随行)→ 激活时把 active 版双路下发。**prompt/模型/参数这一路**:激活编排 PATCH 进 `/agent`+`/sessions`、写进 AgentScope 自己的 Redis,下一次 POST 现装配——MySQL 版本行是账本、AgentScope Redis 是生效投影。SAA 不接 → Python 侧消费方经 Service 或 SDK,无跨栈倒置。
|
|
|
|
**成组激活(静默期语义,非机制级原子)**:激活一个配置集时,配置中心把涉及的 `/agent`+`/session` 作一批 PATCH。但两次独立 PATCH = 两次独立 Redis 写,读侧 `/chat` 又是两次独立 GET(且在 `session_run` 锁之前),机制上给不了真原子——并发一局理论上能读到"新 agent prompt + 旧 session model"的撕裂组合。故激活取**静默期语义**:激活时确保无在跑生成、或新配置只对下一批新生成生效(MVP 单操作者 + 创作页置灰,blast radius 小、够用)。配置中心记"当前激活版"为权威、Service 为投影;一批 PATCH 须幂等,失败即整批判未生效、可重试,不留半生效态。真机制级原子(给 `/agent`+`/session` 盖 epoch 戳、读到版本不一致就重读或拒绝)留放量后。
|
|
|
|
**middleware 热参经 genconfig 门面读、NacosHotConfig 作热源(消灭原自建薄读接口)**:预算目标、门阈值这类不在 `/agent`+`/sessions` 的 middleware 参数,激活时 publish 进按档隔离的 Nacos 生效 dataId;worker 侧不让 middleware 直连 Nacos,而是把 NacosHotConfig(v1 `add_config_watcher` 长轮询推送)接成既有 genconfig 门面的热源,middleware 仍照旧 `genconfig.get(area, key)` 取值、调用面一行不改。fail-safe 由 NacosHotConfig 本地磁盘快照兜底,再回落 env / 本地 YAML / 内置默认(Nacos 挂了不连累生成),正好兑现"强缓存 + 安全默认 + 抖动回落"。除此之外的配置走框架原生 per-POST 热配。接线细节见阶段二设计 §3.4。
|
|
|
|
### 3.4 护城河 = middleware + MCP(框架洋葱内,不另起外层)
|
|
|
|
已验证 AgentScope middleware 能在 reply/reasoning/acting/model-call 钩点 intercept + modify 行为(项目现已用 middleware 做熔断 / trace)。这三件是护城河、无对应现货品类(build-vs-buy R5(a) 豁免),留自建、不在 §3.7 采购面——Nacos/RocketMQ/Sentinel 是围着护城河的基建管道,不是护城河本身。护城河据此全落进洋葱:
|
|
|
|
- **软预算 = on_model_call middleware**:每次裸调用前按"已花 + 本次预估"判,超目标**优雅收尾、不 fail-closed 断链**。因续修移进洋葱内(下条)= **整局生成变成一个 POST `/chat`、一个 middleware 实例贯穿全程**,`spent_rmb` 在同一实例内存里自然累计、**无需持久化**(AgentState 也没有自由 KV 槽可塞,别 fork 它)。若将来真出现跨 POST 的场景(如某门/工具 park 住 agent),再用外部计数器(Redis 按 session 存、经 `extra_agent_middlewares(user_id, agent_id, session_id)` 工厂 seed 进新实例)或直接对 new-api key 级 quota 对账。new-api key 余额本就只能做 key 级粗粒度全局兜底、做不了每局。
|
|
- **续修(resume)= on_reasoning middleware**:reply 循环在 `_reasoning()` 产出纯文本 Msg 时 finish(`_agent.py:614-620`);middleware 在此拦截 → 调 `run_gates`(零 LLM 机器判)→ 没绿且有预算 → 吞掉 finish、注入"这些门没过,修" → 循环 `while cur_iter < max_iters` 继续。bounded by max_iters + 软预算。**取代现有框架外的 `control_plane` 外层循环**:整局在**一个 POST 内**跑完、不再每轮 resume 重开 POST——这正是上条 `spent_rmb` 能内存累计的前提。(finish 点吞 Msg 前 `_save_to_context` 已把助手文本落进 context,注入的"修"消息追加其后、下一轮 model 输入读得到;评审已核到源码。)
|
|
- **九门 = MCP 工具,但放行权威在 middleware 独立重跑**:`run_gates` 已是纯函数(`run.py:811`)、薄封装成 MCP server(跑 mini-desktop、需 chrome/esbuild),给 agent 自查用。**但 finish 是否放行,唯一权威是续修 middleware 在 finish 点自己独立重跑的 `run_gates`,绝不采信 agent 上报的门工具结果**——否则便宜档 M3 可漏调门工具、或谎报门绿再 finish,链路假绿静默破掉(栽过)。代价是每次 finish 尝试都真跑一遍 esbuild+chrome 门、慢,但正确性 > 成本。门要读 agent 刚写进 workspace 的 `src/`,故 Service 与门 MCP 必须**同驻 mini-desktop 或共享工作区**(跨机 FS 门读不到文件,见 §6)。MCP 挂在 **workspace** 上(`workspace.list_mcps()` 每 POST 现取——故经 REST `POST/DELETE /workspace/mcp` 加/摘即下一 POST 生效、零重启;作 `default_mcp` seed 进每个新生成 workspace 让每局都带上);**换哪个 MCP 属稳定机制(改=重部署)、门阈值才是热的一层**(§3.2 / 薄读)。服务态现有 `_extract_function_tools` 丢弃 mcps 的 gap(`service/app.py:119`)须先补,MCP 才能在服务态到达 agent。门判仍机器判、零 LLM。
|
|
|
|
### 3.5 成品源工程归档 = 保留自建 store.py
|
|
|
|
已验证 AgentScope Workspace 只是运行期草稿工作区(本地/容器/沙箱 FS + 上下文 offload),**不支持 minio/s3、无版本、无导出快照**,替不掉项目自建的 `store.py`(MySQL manifest + MinIO 源文件、内容哈希幂等、版本历史、id+version 寻址)。两者职责正交、项目已刻意解耦。归档保持现状,不进本设计改动面。
|
|
|
|
### 3.6 观测 = Studio + genMonitor(采现货 + 扩)
|
|
|
|
部署 AgentScope Studio(桥 `studio_sink` 已建、翻开即用)做深度 trace / 事件回放;扩 game-admin 的 genMonitor(trace 回放 / 成本对账 / agent 拓扑从 `/agent` list / 在跑 gens 与门与预算实时监控)。全部从 agent 运行时事件流→OTel 来。
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
UI["配置编辑 UI<br/>game-admin(yudao)"] -- 带身份:改→定版 --> CC[(yudao 治理<br/>鉴权/creator/BPM<br/>MySQL 版本账本)]
|
|
CC -- 激活·prompt/模型:PATCH /agent+/sessions(静默期成组) --> SVC["AgentScope Service<br/>Redis 当前配置"]
|
|
CC -- 激活·预算/阈值:publish 生效 dataId --> NACOS[(Nacos<br/>路B 生效下发)]
|
|
NACOS -. 长轮询推送 .-> HC["NacosHotConfig<br/>→ genconfig 门面"]
|
|
HC --> MW[middleware]
|
|
SVC -- 每 POST 现装配(热) --> GEN["/chat 生成回合"]
|
|
GEN -- on_model_call --> MW2["软预算 middleware"]
|
|
GEN -- on_reasoning 拦 finish --> MW3["续修 middleware → run_gates(MCP)"]
|
|
GEN -- 事件流→OTel --> OBS["Studio + genMonitor"]
|
|
GEN -- finish --> STORE["store.py 归档<br/>MySQL+MinIO"]
|
|
```
|
|
|
|
### 3.7 基建选型 = 采 Spring Cloud Alibaba 原生三件套(build-vs-buy 现货尽调)
|
|
|
|
栈已经是 Spring Cloud Alibaba,而 Nacos / Sentinel / RocketMQ 正是这条栈的原生三件套——同一套设计哲学、同一套运维面、清一色 Apache-2.0、都能自托管在 mini-infra。现稿里的三处自建(§3.3 薄读配置接口、生产异步队列、并发 ≤15 限流)12 个月后会分别长成 Nacos / RocketMQ / Sentinel 的形状;现在自建等于替这三个系统重写它们早已解决的可靠性问题——配置版本回滚、消息死信重试、集群级全局限流(R2 形态终点测试逐项命中,默认裁决 = 采购)。
|
|
|
|
四需求落点(R1 尽调,每项 ≥3 候选、排除理由落枚举):
|
|
|
|
| 需求 | 采纳 | 排除的候选(一句话理由) |
|
|
|---|---|---|
|
|
| 配置版本化存储 + 下发 | **Nacos** | Apollo(不带服务发现、Python 客户端是社区实现)· Consul(**BSL 1.1 非开源许可**、合规雷)· Spring Cloud Config(Java-only 无灰度、服务不了 Python 热读) |
|
|
| 异步 gen 队列 | **RocketMQ** | RabbitMQ(非 SCA、无事务半消息;RAM 吃紧时的首选回退)· Kafka(流平台、当任务队列是错形状 + RAM 重)· Redis Stream(死信/延迟/幂等全手写 = 自建可靠性红线) |
|
|
| 流控 ≤15 | **Sentinel(Java 侧)** | Resilience4j(单机、无集群全局限流)· Redis 令牌桶(规则手写、无熔断/自适应)· 自建计数器(扩到两实例即双双放行到 30) |
|
|
| 服务发现 | **Nacos(同实例)** | Consul(BSL)· Eureka(**停更/维护态**、归档倾向不得作首选)· 硬编码 @8200(一扩容即断) |
|
|
|
|
采购 / 互补 / 自建:
|
|
|
|
- **采购**:Nacos(配置版本化存储 + 下发 + 服务发现,一套供两需求)· RocketMQ(gen 队列,Java 生产+消费)· Sentinel(Java 准入侧流控 ≤15,规则源 Nacos)。全 Apache-2.0、SCA 原生、自托管 mini-infra,增量成本趋 ¥0(约束是 RAM 余量 ~4-5GB JVM、非现金)。
|
|
- **互补**:yudao(鉴权/creator/BPM/编辑 UI + MySQL 版本账本)⊕ Nacos(生效下发:长轮询推送/快照兜底/namespace 隔离),前者治理并持账本、后者只承预算/门阈值那一路的热推;AgentScope 原生 per-POST 热重载不动,MySQL 版本行作账本、AgentScope Redis 作 prompt/模型那一路的生效投影。
|
|
- **自建(护城河,R5(a) 豁免)**:九门 MCP / 续修 middleware / 门判定逻辑——没有对应现货品类,是域特定的生成验收链,买不到也不该买。
|
|
|
|
生产形态 = Java 管准入+队列,Python 只服务。这个分工不是偏好,是被两个事实逼出来的:Sentinel 无 Python 端口、RocketMQ 的 Python 客户端(Boost.Python over C++)长期低维护。于是限流与队列都落 Java 侧,Python worker 只负责服务 `/chat` 与经 genconfig 门面读热参(NacosHotConfig 作热源)——RocketMQ Python 客户端的成熟度问题因此变成非问题:
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
U[用户请求] --> SENT["game-cloud · Sentinel 准入<br/>并发≤15 + 用户配额<br/>规则热推自 Nacos"]
|
|
SENT -->|过闸| MQ[(RocketMQ<br/>gen 队列)]
|
|
MQ --> CONS["Java 消费者<br/>有界并发结构性≤15"]
|
|
CONS -->|调| CHAT["AgentScope Service /chat<br/>(Nacos discovery 定位)"]
|
|
CHAT --> MW["Python middleware<br/>经 genconfig 门面读预算/阈值<br/>(NacosHotConfig 热源)"]
|
|
```
|
|
|
|
热参不由 middleware 直连 Nacos,而是经 NacosHotConfig 投影进 genconfig 门面:NacosHotConfig 用 nacos-sdk v1 `add_config_watcher` 走长轮询推送、客户端本地磁盘快照兜底(Nacos 不可达不连累生成),middleware 照旧从 genconfig 取值。实现里写死三条:watcher 回调 try/except 兜住别掀翻 worker、语义非法值(负预算/超小超时)保旧值 + 告警不覆盖热参、Nacos 不可达回落快照 → env → 本地 YAML → 内置默认。
|
|
|
|
## 4 步骤计划(全 foundation 先行 · 有序)
|
|
|
|
(图3 构建序 SVG 待补)
|
|
|
|
四阶段按依赖串行,恢复质量与 tier2 go 之前一次性建成。每阶段自带交付 / 验证 / 依赖 / 风险。
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
S0[阶段〇<br/>生产基建 SCA 三件套<br/>Nacos/RocketMQ/Sentinel] --> S1[阶段一<br/>生成归并 Service + 护城河 middleware/MCP]
|
|
S1 --> S2[阶段二<br/>配置中心 yudao⊕Nacos + 服务发现]
|
|
S2 --> S3[阶段三<br/>配置编辑·版本 UI]
|
|
S3 --> S4[阶段四<br/>观测 Studio+genMonitor]
|
|
S4 --> DONE[全齐 → 质量/go 骑上来]
|
|
```
|
|
|
|
**阶段〇 · 生产基建 = SCA 三件套自托管(前置)**
|
|
- 交付:mini-infra 起 Nacos(standalone,配置中心 + 服务发现)+ RocketMQ(NameServer + 单 Broker,gen 队列);game-cloud 接 Sentinel(Java 准入侧流控 ≤15 + 按用户配额,规则源 Nacos 热推)+ RocketMQ 生产/消费(有界并发结构性保证 ≤15);AgentScope Service 注册进 Nacos discovery(替硬编码 @8200);建好 NacosHotConfig(v1 `add_config_watcher` 长轮询热源、本地快照兜底,单测绿),接进 genconfig 作预算/阈值热源留阶段二。
|
|
- 验证:NacosHotConfig 能连 Nacos 收到配置变更(接进 genconfig 由阶段二验);请求过 Sentinel 准入(击穿 ≤15 被拦)→入 RocketMQ→Java 有界消费→调 `/chat`;三件自托管、mini-infra RAM 余量够;数据不出内网。
|
|
- 依赖:mini-infra(已有 Docker/MySQL/Redis)。
|
|
- 风险:mini-infra RAM 余量(新增 ~4-5GB JVM)——吃紧则压 `-Xmx` / 不部 Sentinel 面板(规则直存 Nacos);RocketMQ Python 客户端弱 → 队列生产消费全在 Java 侧、Python 不碰(见 §3.7)。
|
|
|
|
**阶段一 · 生成归并 Service + 护城河做 middleware/MCP**
|
|
- 交付:cheap-worker 从 `cheap_studio` 归并到 Service `/chat` 路(与 tier2 同构、保留代理旁路);软预算 middleware(软停 + 单 POST 内累计,无需持久化);续修 on_reasoning middleware(拦 finish + **独立重跑 run_gates** + 续跑,取代 `control_plane` 外层);九门包成 MCP server(与 Service 同驻、共享 workspace)。
|
|
- 验证:两档都经 Service 生成、真玩门九门仍全绿;续修 middleware 拦住早退、门没绿不放行(放行权威 = middleware 独立重跑、不采信 agent 上报的门工具结果);软预算超目标优雅收尾不断链、单局内累计正确;九门 MCP 在 mini-desktop 真跑;归并后内网 M3 调用仍绕过代理不 502。
|
|
- 依赖:AgentScope Service(tier2 已部署 @8200)、`run_gates`(已存在)。
|
|
- 风险:**middleware 拦 finish + 注入续跑的确切机制没在项目里验过**——先做一个小 spike 坐实(§6);cheap-worker 归并是主要工作量。
|
|
|
|
**阶段二 · 配置中心 = yudao 治理与版本账本 ⊕ Nacos 生效下发**
|
|
- 交付:game-cloud 落一个 yudao 治理子域(编辑 UI + 鉴权 + `creator` + BPM 挂点 + 版本行 + 生命周期状态机 + 当前激活版指针 + 激活编排);版本行落 MySQL、承版本历史/回滚/diff(借 yudao 原生);激活时双路下发——prompt/模型/参数 PATCH 进 `/agent`+`/sessions`,预算/门阈值 publish 进按档隔离的 Nacos 生效 dataId;把阶段〇建好未接线的 NacosHotConfig 接进 genconfig 作热源(middleware 调用面不改)。Nacos 收窄为预算/阈值那一路的生效下发通道,不再承版本账本。
|
|
- 验证:改任一旋钮→定版→激活→下一次生成生效;配置集成组激活(静默期)、并发两局不读撕裂组合;回滚旧版本即恢复;改动随版本可查 creator/时间/diff;NacosHotConfig 接线后 cheap 与 tier2 经 genconfig 数秒热读到新预算/阈值、不重启。详见阶段二设计 §4/§5。
|
|
- 依赖:阶段一(生成走 Service,配置才有 PATCH 落点);阶段〇 NacosHotConfig 已建未接线。
|
|
- 风险:激活一致性是本阶段最重风险——一批 PATCH+publish 跨系统非原子、投影写即被读,靠值域校验前置 + 幂等 + 失败即整批判未生效并立即补偿重推已成功路回上一激活版收敛;详见阶段二设计 §6。
|
|
|
|
**阶段三 · 配置编辑·版本 UI**
|
|
- 交付:game-admin(标准 admin-api,不用独立 axios)配置面:浏览 / 改→版本 / 单条或配置集激活 / 回滚 / 历史 / diff;agent 配置表单消费 `/agent/schema`。
|
|
- 验证:创始人在 UI 改旋钮、激活、下一次生成生效;历史/回滚/diff 可用。
|
|
- 依赖:阶段二。
|
|
- 风险:UI 不另持配置模型,一切以配置中心为真相。
|
|
|
|
**阶段四 · 观测**
|
|
- 交付:部署 Studio + 翻开 `studio_sink`;扩 genMonitor(trace 回放 / 成本 / agent 拓扑 / 在跑监控)。
|
|
- 验证:任一局 trace 在 Studio 与 genMonitor 可回放;在跑 gens/门/预算实时可见;成本按 new-api quota 对出。
|
|
- 依赖:trace 事件流(已落)、`/agent` list。
|
|
- 风险:Studio 单独部署、default-off,不可达即 no-op、不影响生成。
|
|
|
|
**全齐 → 质量与 tier2 go 骑上来**:此后调模型/预算/prompt/阈值都在 UI 改一版激活、下一次生成生效,trace 可回放。放量后再接 BPM 审批 + 运营 DB 审计。
|
|
|
|
## 5 验证方式
|
|
|
|
1. **配置即数据、版本可管**:改 model/budget/max_tokens/thinking/prompt 任一→新版本→激活→PATCH→下一次生成生效;回滚即恢复;逐项覆盖本会话手改过的硬编码点。
|
|
2. **成组激活(静默期)无撕裂**:一组旋钮作一个配置集激活,取静默期语义(无在跑局时切 / 只对下批新生成生效);并发两局不读到跨 `/agent`+`/session` 的撕裂组合。
|
|
3. **审计归因**:yudao 登录用户即 creator,每次改动随版本可查谁/何时/diff。
|
|
4. **护城河在洋葱内**:续修 middleware 拦早退、门没绿不放行(放行权威 = middleware 独立重跑 `run_gates`、不采信 agent 上报;九门 MCP 真跑);软预算超目标优雅收尾不断链、单局内累计正确。
|
|
5. **观测绑运行**:任一局 trace 在 Studio+genMonitor 可回放;在跑 gens/门/预算实时可见。
|
|
6. **两档同构**:cheap-worker 与 tier2 都经 Service 生成、配置同一套热配。
|
|
|
|
## 6 风险与回滚
|
|
|
|
- **middleware 续修机制未在项目验过**(最需先坐实):源码支持 middleware intercept+modify(评审已核到 finish 点 `_save_to_context` 次序 + `_check_next_action` 语义、钩子选型正确),但拦 finish + 注入续跑的确切写法仍要一个小 spike 坐实;spike 不成则回落现有 `control_plane` 外层循环(已存在),架构其余不受影响。
|
|
- **cheap-worker 归并 Service**:是主要迁移;回滚 = 保留进程内路作 fallback,分档灰度归并。
|
|
- **配置中心↔Service PATCH 一致性 + 并发撕裂**:激活是一批独立 PATCH,机制上非原子;须幂等 + 失败即整批判未生效可重试 + 记"当前激活版"为权威(Service 为投影)、不留半生效态。并发一局读到跨 `/agent`+`/session` 撕裂组合的风险,MVP 由**静默期激活**规避(见 §3.3);真机制级原子(epoch 戳 + 读到不一致重读/拒绝)留放量后。
|
|
- **门 MCP 必须与生成 Service 同驻 / 共享 workspace**:门要读 agent 刚写进 workspace 的 `src/`,而 chrome/esbuild 只在 mini-desktop;若跨机、跨 FS 则门读不到文件。钉:Service + 门 MCP 同驻 mini-desktop 或共享工作区。
|
|
- **SoT 收口必须扩全**(否则触 canonical-uniqueness 红线门):须同步修 SoT 的**三处**偏离——① GitOps 口径(§5.2 表行+正文 / ADR-4 / A13 / §二补④ / §5.8)改为配置中心版本化;② §5.2"管理面用 /agent CRUD 做配置管理"的假设不完整(源码证:/agent 不含 model、context_size/stream 透不进、生成原走进程内),据本设计的"配置中心版本层 + 原生 per-POST 热配 + 护城河 middleware"修正;③ **resume 机制叙述**:现有 SoT 与代码注释(`bootstrap.py`、`app.py`、`control_plane.py:19`、tier2 架构图说 + close-out)把 resume 讲成"消费方决定是否再 POST"的**框架外层**机制;本设计改成 `on_reasoning` 洋葱内 resume,那些叙述须降级标注为 fallback,否则两份自称 canonical 触门。
|
|
- **阶段二方向 B 涟漪已收口(2026-07-04)**:创始人 2026-07-02 拍方向 B——版本账本从 Nacos 挪回 yudao MySQL 版本行、Nacos 收窄为预算/阈值那一路的生效下发、middleware 经 genconfig 门面读(NacosHotConfig 作热源)。本设计 §0 / §3.3 / §3.6 图 / §3.7 / §4(阶段〇 listener 口径、阶段二节)已随之回调,与阶段二设计 §7 挂账表逐条对齐;运行时 SoT(架构图说 §5.2/§5.8/ADR-4/A13)已同步(2026-07-03)。`/session` 路径按 22444fd5 修复口径应为 `/sessions`,本次仅在已回调段落更正,其余机制描述段(§1.1/§3.1/§3.2)未一并统一,待后续 doc-sync。
|
|
- **预算网关侧做不了每局硬顶**:每局预算是 agent 侧软限(网关只 key 级兜底);这是事实约束、非本设计缺陷。
|
|
|
|
## 附 图清单与状态
|
|
|
|
| 图 | 角色 | 状态 |
|
|
|---|---|---|
|
|
| 图0 一图看懂 | §0 门面 SVG | 待 opus 子代理出图 |
|
|
| 图1 四层归属 | §2 边界 SVG | 待出图 |
|
|
| 图2 配置热配数据流 | §3 SVG(内联 Mermaid 事实源已在文) | 待出图 |
|
|
| 图3 构建序 | §4 SVG(内联 Mermaid 事实源已在文) | 待出图 |
|
|
|
|
文字 + Mermaid 为事实源,SVG 为派生视觉。
|