games-development-ai/.agents/skills/tier2-service-generation.md
lili a207cb8d65
Some checks failed
contract-gates / contract-gates (push) Has been cancelled
docs-gate / docs-gate (push) Has been cancelled
docs(agents): skill 规范化双层收口 + 席位context skill 新增 + W-NSTAR/W-TPL/W-GENLOG 设计波落档
- .agents/skills 25 件全量 frontmatter 规范化与评审修入(含 prompt-governance 大修);.claude/skills 7 件薄壳按双层方案①落位
- 新增 skill:agentic-seat-context-design(agentic 席位与 context 工程设计基线,2026-07-05 探索蒸馏)
- 设计波三件落档:复杂游戏北极星件(W-NSTAR 终审稿待拍)/黄金模板规格件(W-TPL 定稿待批)/生成侧过程蒸馏回路(W-GENLOG 骨架)
- protocol/在飞板/作战清单/数据飞轮 SoT/契约 prompts 索引同步;breakout 九门证据刷新
- .gitignore 补 /localagents.md 真实忽略行(该文件自声明绝不提交,此前声明未被机器执行)
- 刻意不入库:nacos-data/ 与 _tier2-gen、c2v-*、amgen-* 生成产物(可重生成,忽略行格式待拍)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 05:32:56 -07:00

9.7 KiB

name, description, metadata
name description metadata
tier2-service-generation tier2 富游戏服务态生成(AgentScope create_app :8200 + 控制面有界 resume)的驱动配方与收敛诊断——含 6 个集成口径、收敛头号杠杆(play_spec driver)、九门/富游戏门读法
type
skill

tier2 服务态生成:驱动 create_app + 收敛诊断

tier2 富游戏线把"本地 CLI 直驱裸 Agent"(worker/agent_loop/studio.pyrun_studio)升级成经 AgentScope 2.0.2 create_app 的 Agent Service:多租户、多会话、REST 触发(POST /chat,fire-and-forget)、SSE 事件流,session 状态与跨会话 MessageBus 走 Redis。服务跑在 mini-desktop:8200,由一个控制面(service/control_plane.py)从消费方侧驱动一款游戏从启动到门绿落库。

这份手册记录两件在 2026-06-24 服务化实测里用真证据换来的东西:怎么正确驱动这个服务(六个集成口径,每一个都是一次 422 / 崩溃换来的),以及一个差点被误判成"模型太弱"的收敛假象的根因

收敛头号杠杆:真玩 driver,不是生成质量

服务态首批真跑(cp-smoke-006/007)都跑到 budget_exhausted 不收敛,表面看像"M3 单写产不出能过富游戏门的游戏"。这是假象。 拆开 verdict 看,九门里 A_boot / B_uncaught / C_frame / D_render / E_live 全绿——游戏能启动、能渲染、有活的状态;只有 F_wiring 挂,报 calls=0 expected=[],而富游戏三门(tripleLink / economy / latch)的子检查全是 None

关键区分:None 不是 FalseNone 意味着这些检查根本没法评估,而不是评估后判失败。富游戏门要靠 CDP harness 真玩游戏、观测它在玩的过程里有没有真调 resource.addCoins / resource.consumeIngredient、经济线能不能走到赢/破产、终态有没有 latch。没有真玩,这些观测一个都拿不到,于是全 None,门挂。

根因是控制面给 run_gates 传了 play_spec=None。play_spec 里装的是真玩驱动规格——driver(怎么玩)、expectedEngineCallPrefixes(该观测到哪些引擎调用)、assertAfterPlay(玩完该满足的状态断言)、economy 阈值。没有它,harness 把游戏渲出来就停了,从不驱动它玩。游戏永远不被玩 → 没有引擎调用 → F_wiring 挂、富游戏门 None。更糟的是,生成 agent 自己的 run_gates 工具也吃同一个 None,于是 agent 看到 decision=fix 却在"修一个根本不存在的问题",反复 thrash 直到预算耗尽。

铁证:把 007 那个"失败"的现成游戏,配上标准 business-sim driver 重跑门,直接 decision=accept,九门 + 富游戏三门全绿。游戏一直是好的。

修复(worker/run.pyrun_gates):play_spec 缺 driver 时 setdefault 一份 DEFAULT_BUSINESS_SIM_PLAY_SPEC,显式 play_spec 仍优先。这份默认规格对任何契约合规的 business-sim 游戏通用——因为 driver 是参数化的({type: "business-sim", steps, stepMs, winThreshold, bankruptSteps, streakLose}),按契约驱动而非靠逐像素坐标;bakery(feie-005)和 coffee(007)两款不同的游戏用同一份 driver 都过门。一处修复同时惠及生成 agent 自己的 run_gates 工具(thrash 根)和控制面评门。

契约:游戏要可被这份通用 driver 真玩,必须暴露 resource.addCoins / resource.consumeIngredient 这些 call-ID(经 recHook)、把终态 phase latch 成 win/lose/gameover 让宿主轮询、并在 scene 里接 bindInput 把注入的输入路由到 core 命令。M3 在设计阶段引导下已经稳定产出这套契约——所以收敛的真问题从来不是"模型写不出富游戏",而是"有没有真玩它"。

诊断口诀:九门前几道绿、F_wiring 挂、富游戏门 None → 先查 driver,别怪生成。

驱动 create_app 的六个集成口径

create_app 不收 agent 实例,只收装配零件(extra_agent_tools / extra_agent_middlewares 工厂),agent 由框架在每个 chat 回合内部装配。控制面/bootstrap 经现成 REST 端点驱动它。下面每一条都是实测撞出来的,直接照用:

  1. 凭据注册(POST /credential/):请求体是 {data: {...}},凭据载荷整体嵌在 data 下,不是扁平字段。Anthropic 凭据的 data = {type: "anthropic_credential", api_key, base_url}——没有 model 字段(模型名在 session 的 chat_model_config.model)。模型类由 get_modelCredentialFactory.from_dict(data).get_chat_model_class()data.type 决定,所以 data.type 必须对。

  2. chat 输入(POST /chat/):input 是一条 Msg,它的 content 必须是内容块列表,不能是裸字符串(裸串返 422 Input should be a valid list)。发 {name, role, content: [{type: "text", text: "..."}]}。Python 端 UserMsg(content=str) 的字符串自动包块只发生在构造器里,经 REST 传 JSON 不走那条。

  3. 九工具抠取(extra_agent_tools 工厂):2.0.2 的 Toolkit 把注册的工具按组存在 self.tool_groups,每组的 .toolslist[ToolBase];构造器传入的 tools 被包进默认 "basic" 组(不是扁平的 .tools 属性)。要把九工具交给框架,从 toolkit.tool_groups[*].tools 收集。按扁平 tools/_tools/function_tools 探测会全空,每个 chat run 起手即抛、服务态生成零产出。

  4. BYPASS 权限(建 session 后):tier2 九工具的 FunctionTool 默认 check_permissions 返回 ASK,服务态无人确认。不设 BYPASS,agent 第一次调工具就进 ToolCallState.ASKING、等一个永不来的确认事件,chat run 抛 Agent is waiting for N tool calls ... but received no event,生成零产出。修法:PATCH /sessions/{id}?agent_id=<id>{permission_mode: "bypass"}(PermissionMode.BYPASS 值是 "bypass")。注意 PATCH 与 SSE stream 一样要 query 参数 agent_id,不带返 422。等价 CLI studio.py_bypass_state()

  5. 设计阶段接进服务路径(建 agent 前):CLI 线 run_studio 先跑工作室设计阶段产出 design_text 再写,服务路径此前整段跳过、writer 拿空 design。修法:bootstrap 在建 agent 前于控制面进程内(有 agentscope + 模型)复用 studio._design_stage(工作室星形多 agent 团队 + 失败 degrade 回单 agent)产出 design_text,喂进 AgentRecord.system_prompt(roles.writer_system 第二参)。best-effort:设计失败返空串、不阻断生成。设计团队墙钟超时现为 420s(2026-07-04 由 240s 上调);240s 时代偏短、常 degrade 回单 agent,上调 420 后已缓解——即便 degrade 仍产出 design_text 可用。要调超时改 tier2/config/generation.yamldesign_team.timeout_s(配置外置已兑现)。

  6. SSE 等待必须有界(控制面消费 SSE):create_app 的 chat 是每回合一次、fire-and-forget,控制面订阅 GET /sessions/{id}/stream?agent_id=<id> 读到本回合的 REPLY_END / EXCEED_MAX_ITERS 才算这轮跑完。:超时检查不能只写在 async for line 的循环体内——SSE 流完全静默时(如服务端 Redis 超时打断了事件发布,既无 data 也无心跳)aiter_lines 永久 await,没 line 进来超时检查永不触发,控制面无限挂(实测卡死 60min)。修法:httpx Timeout(read=idle_timeout_s),静默超它即 ReadTimeout → 兜住 → 据 on-disk 评门继续。idle_timeout_s=300s 远大于 agent 内部 run_gates(chrome ~60s)的正常静默间隙,不误杀正常回合。

控制面有界 resume(B1)

service/control_plane.pydrive_generation 把 CLI run_studio:404-458 的外层有界 resume 搬到服务消费方:bootstrap.start_new_game 启动 → 外层 for attempt in range(max_resumes+1):消费 SSE 等本回合结束 → 独立run.run_gates(session_id, play_spec) 机器判门(不靠内存 session——服务态九工具每回合工厂新建 Tier2Session,内存态跨回合不保留)→ 门绿则据 on-disk 源工程重建七要素 + persist_source_project 落库 break / 否则 verdict_feedback 包成续跑指令 resume_session 续修 / 预算耗尽停。评门的 game_id 必须用框架分配的 session_id(九工具据它管工程目录 game-runtime/games/_tier2-gen/<session_id>)。门是机器判的,控制面绝不自评翻绿。

运维与诊断

  • 起服务(mini-desktop):cd /root/tier2-run/tier2/gen-worker && NEWAPI_KEY=... NO_PROXY=100.64.0.8 setsid /root/.venvs/agentscope-tier2/bin/python -m service.app >log 2>&1 </dev/null &,单独只读 ssh 轮询 /openapi.json=200 确认就绪。改了 app.py / worker/*(服务端按回合 import + 缓存)要重启服务才生效;改 control_plane.py / bootstrap.py(控制面客户端、每次新进程)不必重启,同步 tier2-run 即可。
  • 真玩门(run_gates / chrome / esbuild)只在 mini-desktop;6c6g 禁 chrome、只做 py_compile + 裸 import 静态校验。重依赖(agentscope / redis / httpx / pymysql / minio / uvicorn)一律函数体内惰性 import,顶层零重依赖,保证 6c6g 能 import。
  • C1 轻量观测:控制面把逐帧 SSE 的结构性事件(跳过 *_DELTA 逐 token 噪声)记成 per-run control-plane-trace.jsonl,零外部依赖。事件字段口径(2.0.2):TOOL_CALL_STARTtool_call_name + tool_call_id,TOOL_RESULT_ENDtool_call_id + state。要在 workdir 建好(scaffold 之后)才落盘,否则刷 FileNotFoundError
  • 端点 / 凭据 / 起服务铁律见 docs/内网凭据与端点.md 的「tier2 P4 服务化部署拓扑」段。

配套:AgentScope 2.0 架构事实见 ../knowledge/agentscope-2.0-facts.md;CLI 单写主链见 agentic-amodel-generation.md(A-model/wg1 线,与本 tier2 服务态线同源不同栈);SAA 编排见 saa-graph-orchestration.md