第 12 章 第二部分:架构原理

Runtime Server 深度解剖

FastAPI + Socket.IO 双通道、invoke 端点、Blob sideband、Worker Venv、LLM Proxy、RPCReplayGuard

Nexus Runtime Server FastAPI Socket.IO Worker LLM Proxy

Runtime Server 是什么

Runtime Server 是运行在沙箱内部的服务——一个 FastAPI + Socket.IO 应用。它接收 Host 侧的请求,在沙箱环境中执行,返回结果。

nexus/runtime/server/app.py 是最大的单文件之一(1243 行),包含了 Server 的所有端点和逻辑。

双通道架构

Host (RemoteRuntime)                  Sandbox (Runtime Server)
  │                                      │
  ├── HTTP ──────────────────────────►   │ POST /api/v1/invoke
  │   (RPC: invoke, call_tool,          │ POST /api/v1/call_executor
  │    call_executor, venv)             │ POST /api/v1/venv
  │                                      │
  ├── Socket.IO ◄────────────────────   │ emit('log', items)
  │   (Events: log, span,              │ emit('span', items)
  │    invoke:done, venv:done)          │ emit('invoke:done:{rid}', response)
  │                                      │

HTTP 是主通道——所有 RPC 调用走 HTTP。Socket.IO 是辅助通道——推送实时日志和 Span 事件。

invoke 端点的 Long-Poll 机制

POST /api/v1/invoke
  Header: Prefer: wait=30

  → 如果 30 秒内执行完毕:200 + InvokeResponse
  → 如果超过 30 秒:202 + {request_id}
    → Host 等待 SIO push event 'invoke:done:{rid}'
    → 或者 HTTP polling GET /api/v1/invoke/{rid}

这个设计平衡了延迟和资源占用:短任务直接返回,长任务异步通知。

Blob Sideband

当 payload 或 result 超过 1MB 时,不走 JSON 内联,而是通过单独的 HTTP 端点传输:

Host: POST /api/v1/blob/{blob_id}  (上传大参数)
Host: POST /api/v1/invoke {payload_ref: blob_id}  (引用)
Server: 执行...
Server: 200 {result_ref: result_blob_id}  (大结果同理)
Host: GET /api/v1/blob/{result_blob_id}  (下载)

这避免了 base64 编码大数据时的内存峰值。

Worker Venv 机制

Worker Venv 解决一个问题:如何在沙箱内运行自定义的 Python 扩展代码,同时与 Runtime Server 本身的依赖隔离。

架构

沙箱
├── Base Process (Runtime Server)
│   ├── FastAPI Server
│   ├── Executor Registry
│   └── Worker Launcher
│
├── Worker Process #1 (venv-abc)
│   ├── 独立的 Python venv
│   ├── 安装了 artifact wheel(用户的扩展代码)
│   ├── Socket.IO Client → 连接 Base
│   └── 接收 invoke 请求,执行,返回结果
│
└── Worker Process #2 (venv-xyz)
    └── ...

创建流程

  1. Host 发送 POST /api/v1/venv,包含 artifact wheel(base64 编码)和依赖列表
  2. Server 的 VenvManager 创建新的 Python venv(使用 BFS 闭包 symlink 复用已有包)
  3. 安装 artifact wheel 和额外依赖
  4. 启动 Worker 子进程
  5. Worker 通过 Socket.IO 连接 Base,注册为可用 Worker

invoke 路由

# InvokeRequest.venv_id 决定去哪里执行
if request.venv_id:
    # 路由到对应的 Worker 进程
    worker = workers[request.venv_id]
    result = await worker.invoke(request)
else:
    # 在 Base 进程执行
    result = await execute_locally(request)

LLM Proxy Services

Runtime Server 内置了 4 种 LLM API 代理:

Proxy路径用途
OpenAI Proxy/v1/chat/completions代理 OpenAI 格式的请求
Anthropic Proxy/v1/messages代理 Anthropic 格式的请求
Gemini Proxy/v1beta/models/...代理 Gemini 格式的请求
Responses Proxy/v1/responses代理 OpenAI Responses 格式

这些 Proxy 是 Installed Agent 的关键。当 Claude Code CLI 在沙箱里运行时,它的 API 请求会被路由到 Anthropic Proxy。Proxy 通过 Socket.IO 将请求转发给 Host,Host 使用配置的 OpenAI Client 完成推理,然后将结果返回。

这个机制实现了:

  • 沙箱内不需要 API Key(安全)
  • Host 侧统一做 token 计数和轨迹采集
  • 可以用不同的 LLM 替换原始 Agent 的模型

LLM/MCP Proxy 治理全景

当前 Nexus 的 LLM Proxy 专注于格式转发和 token 计数,但生产环境需要三层治理能力:安全管线、成本控制、MCP 细粒度访问。下面从三层架构重构 Proxy 治理方案。

安全管线层

CrabTrap 模式(请求内容安全审查):Brex 开源的 CrabTrap 使用 LLM-as-a-judge 两阶段评估——静态规则(URL 模式匹配,微秒级)→ LLM 判断(自然语言策略,处理长尾)。Nexus 当前不做请求内容审查,恶意 prompt 可经由 Proxy 无约束地到达 LLM API。

Traefik 组合式安全管线(2026.06 发布):Traefik Hub Triple Gate 的安全管线采用多供应商并行执行模式——Regex Guard → Microsoft Presidio(PII 脱敏)→ NVIDIA NIMs(内容安全)→ IBM Granite Guardian(策略合规),每层可独立启用/替换。这种组合式架构比单一 LLM-as-a-judge 更灵活,Nexus 可借鉴此模式在 Proxy 层构建可插拔的安全管线。

OWASP Agentic Top 10 映射:Traefik 社区已将 MCP Gateway 的四层安全管线映射到 OWASP Agentic Security Top 10 风险类别。对 Nexus Runtime Server 有直接参考价值:

这份清单的正式名称是 OWASP Top 10 for Agentic Applications for 2026,由 OWASP GenAI Security Project 下属的 Agentic Security Initiative(ASI)于 2025-12-09 发布。官方描述其为”面向自主与 agentic AI 系统的最关键安全风险清单,由 100 多位行业专家、研究者与从业者协作评审而成”,并设有 Distinguished Expert Review Board,成员来自 NIST、欧盟委员会、艾伦·图灵研究所等机构。官方十项条目全称为:

ASI01 Agent Goal Hijack|ASI02 Tool Misuse & Exploitation|ASI03 Identity & Privilege Abuse|ASI04 Agentic Supply Chain Vulnerabilities|ASI05 Unexpected Code Execution|ASI06 Memory & Context Poisoning|ASI07 Insecure Inter-Agent Communication|ASI08 Cascading Failures|ASI09 Human-Agent Trust Exploitation|ASI10 Rogue Agents

OWASP 风险(官方全称)Traefik 管线层Nexus 对应状态
ASI05 Unexpected Code Execution(非预期代码执行,官方示例为 AutoGPT RCE)TBAC 阻止工具调用需 Runtime Server 增强——沙箱层(Ch11)负责隔离,Proxy 层负责授权
ASI06 Memory & Context Poisoning(记忆与上下文投毒)Granite Guardian hallucination+RAG当前无对应机制
ASI07 Insecure Inter-Agent Communication(不安全的 Agent 间通信)MCP Gateway 认证加密审计RPCReplayGuard 覆盖重放,但缺少 Agent 间通信的认证加密
ASI08 Cascading Failures(级联失败)Failover Router 断路器链当前无断路器

安全管线是 Nexus Runtime Server 目前最薄弱的环节——CrabTrap/Traefik 都是外部方案,Runtime Server 本身不做请求内容审查。如果 Installed Agent 通过 Proxy 发送恶意 prompt,当前唯一的防护是模型自身的安全对齐。

⚠️ 核对 ASI 编号时的陷阱:网络上流传着另一套与官方错位的 ASI 编号(例如把 ASI05 写成”不充分的护栏和沙盒”、ASI06 写成”敏感信息泄露”)。本书采用 OWASP 官方发布版编号,读者核对时请以官方条目全称为准,不要只比对数字——数字相同但名称不同的,不是同一条风险。

成本治理层

TokenGuard 模式(预算保护与去重):TokenGuard 实现请求去重(相同请求缓存)、token 预计算(tiktoken)、电路断路器(超限暂停)。Nexus 的 token 计数仅用于事后统计,无实时预算保护和超限断路。

LLMCap 硬上限保险丝:开源代理层,拦截所有 LLM API 调用强制执行美元硬上限,<5ms 开销,支持 OpenAI/Anthropic/Google 多供应商。相比 TokenGuard 的 token 预算,LLMCap 用美元硬上限更直观——开发者可直接设置”$50/天”而非换算 token 数。

CostGuard 多级断路器:4 层电路断路器(session/hour/day/project)、tiktoken 预估成本、Safe Mode 暂停高价请求待人工确认、实时终端仪表板。比 TokenGuard 更完善,增加了 Safe Mode 和多时间粒度预算。

RapidClaw 三层纵深防御:Layer 1 Agent(重复检测+错误率+步骤预算+冷却)、Layer 2 Service(per-agent token/hour + per-task USD cap)、Layer 3 Infra(daily tenant USD cap + 供应商月度限额 + kill-switch)。Nexus 当前仅有 Runtime Server 侧的 token 计数,缺少 Service 层和 Infra 层的预算治理。

工具级经济权重建模(budget limiting):上述四方案均以 token 或 USD 为预算单位,2026 年 MCP Gateway 治理进一步延伸出”按工具经济权重”的细粒度建模——为每个工具标注成本权重(如 search_code=1 credit、generate_report=200 credits),使 rate limiting 升级为 budget limiting。其现实动因是:一个未治理的 agent 高频调用昂贵工具(如 800 次昂贵调用)可造成数千美元的成本事故。与 RapidClaw Layer 2 的 per-task USD cap 相比,工具级建模是更细的粒度——USD cap 是任务级上限,工具权重则刻画”单次调用的相对成本”。

治理状态的存储选择:上述成本控制方案都需要持久化状态(token 计数/预算/断路器状态)。选择分布式中间件(Redis/PostgreSQL)还是嵌入式数据库(SQLite)?

2026 年 6 月的系统性基准测试表明:SQLite WAL 模式 + synchronous=FULL 可支撑 ~1,000 durable commits/sec,而 LLM Proxy 治理层的写入频率远低于此(每次 LLM 调用 <1 次状态写入,秒级间隔)。Cloudflare Workflows V2 已在生产环境验证 SQLite-backed 工作流状态存储(4,500→50,000 并发实例)。

结论:Runtime Server 内的 Proxy 治理状态用 SQLite 存储即可,无需引入 Redis/PostgreSQL。这与 Batch Runner 用 SQLite 做任务状态的设计哲学一致——简单、单文件、天然支持 resume。

MCP 治理层

TBAC 细粒度访问控制:Traefik 的 Task-Based Access Control 不限制”哪个 agent 连哪个 MCP server”,而是限制”这个 agent 可以通过这个 MCP server 对哪些资源做什么操作”,配合速率限制+时间窗口+审计日志。这比章节原先提到的 CrabTrap 请求内容审查更全面——从”请求内容是否安全”升级为”操作是否在授权范围内”。

Traefik MCP Gateway:作为 Triple Gate 的一部分,提供 MCP 工具调用的统一治理入口。Nexus 当前缺少 MCP 调用的治理层——Installed Agent 通过 MCP 调用外部工具时,既无速率限制也无操作审计。

MCP server 自身也会出事故:前面讨论的隔离问题源自宿主应用侧,而 CVE-2026-32211(Microsoft 披露,NVD 于 2026-04-03 收录)是 Azure MCP Server 关键功能缺失认证——未授权攻击者可经网络获取信息。需注意该 CVE 的 CVSS v3.1 评分存在两个来源:9.1(CRITICAL,向量 AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N)与 7.5(HIGH,…/C:H/I:N/A:N),分歧在于是否计入完整性影响,引用时应标注这一分歧而不是二选一。

它与 Ch11 提到的 CVE-2025-59528(Flowise CustomMCP 节点 RCE,CVSS 10.0)恰好互补:后者是宿主应用解析用户提供的 MCP 配置不当、导致宿主机被 RCE;前者是 MCP server 自身压根没有认证。对本章的治理论证而言,Flowise 那条说明”不能让 MCP 工具直接在宿主上执行”,Azure 这条则说明”连认证都没有的 server 会被直接挂到互联网上”——TBAC 与审计日志要防的不只是越权调用,还包括这种默认开放。

⚠️ 两条不吃配置的硬边界(客户端实测,2026-09,均取自官方 changelog 一手):

  1. 约 5 分钟的硬超时——Streamable HTTP 的 MCP 工具调用存在一条不受 per-server timeout 控制的超时上限,即使把 per-server timeout 设得更长也会生效(Claude Code 2.1.274,2026-09-17 修复)。
  2. 2048 字符上限——MCP 工具描述与 server 指令默认有 2,048 字符上限(2.1.280,2026-09-22 起可用 CLAUDE_CODE_MAX_MCP_DESCRIPTION_LENGTH 调整)。

二者的共同点是配置写了但不生效,且没有报错。这对 Proxy 层尤其危险:工具描述被截断后,基于描述做匹配的策略(TBAC / 审计 / 预算分级)会表现为”策略没配”,而不是”描述被截断”——排查方向完全不同。因此 Proxy 若要做工具治理,必须先把这类上限显式暴露出来。

MCP 2026-07-28:协议无状态化对 Proxy 架构的影响

MCP 协议 2026-07-28 版本(2026-05-21 发布 RC,7/28 正式)是协议史上最大修订。对 Nexus Runtime Server 的 LLM/MCP Proxy 有以下直接影响:

简化 Runtime Server 的 MCP 代理逻辑:

  • 旧协议:Runtime Server 需维护 Mcp-Session-Id → worker 的映射,支持 sticky session 以保持 MCP 连接。session 断开重连需恢复状态。
  • 新协议:移除 initialize 握手和 Mcp-Session-Id。每个 tools/call 请求自包含(clientInfo 在 _meta 中传递),任意 Runtime Server 实例可处理。不再需要 sticky routing。

提升 MCP 治理层的能力边界:

  • Mcp-Method + Mcp-Name header 使 Traefik MCP Gateway 可基于 header 路由,无需解析 body。速率限制/审计可在 LB 层实现,无需应用层介入。
  • ttlMs 缓存(SEP-2549)使 tools/list 结果可被 Proxy 缓存,减少重复的 server/discover 调用。但缓存只是一半——另一半是对 list_changed 的速率限制:server 若高频发送 list_changed 通知,客户端会陷入持续的 tools/list 重取与高 CPU(客户端实测修复于 2026-09-14,Claude Code 2.1.271)。只做 TTL 缓存而不对通知做限流,缓存与通知会构成正反馈回路,Proxy 反而被动放大流量。
  • Multi Round-Trip Requests(SEP-2322)替代 SSE 流——对 tools/call、resources/read、prompts/get 三类请求(规范明确:其他请求一律不得返回该结果),服务端可返回 resultType: "input_required" 的 InputRequiredResult,且必须至少携带 inputRequests 或 requestState 之一。inputRequests 是服务端发起的请求映射(键由服务端分配、须在本次请求内唯一,值只能是 ElicitRequest / CreateMessageRequest / ListRootsRequest);requestState 是对客户端不透明的字符串。客户端收集输入后,用新的 JSON-RPC id(规范要求与首次请求不同,因为两者是独立请求)重试原方法,回传 inputResponses;收到过 requestState 就原样回显,没收到则不得凭空补一个。elicitation 因此不再需要持久连接,服务端也不再主动向客户端发请求,这消除了 Proxy 层的连接管理复杂性。

⚠️ elicitation 另有 URL 模式,且它带来一个反向破坏。 在 2026-07-28 协议上,elicitation 新增 URL 模式——服务端可以要求客户端打开一个浏览器流程(用于登录等),客户端侧实现为”服务端无法确认完成时不在屏幕上留下等待对话框”(Claude Code 2.1.281,2026-09-23)。同一能力在旧协议(2025-11-25)上的落地方式不同:客户端为支持 URL prompts 引入了新的配置要求,未声明 "bareElicitationCapability": true 的 server 会直接连不上(2.1.287,2026-10-01)。

这与上面”迁移窗口内旧实现仍可工作”的乐观预期相反:协议能力升级会以”连不上”的形式反向破坏旧 server,且报错不指向根因。Nexus 的 MCP Proxy 若要在窗口期内同时服务新旧 server,须显式枚举这类 capability 声明,而不是只做版本协商。

  • ⚠️ 但 Proxy 不能把 requestState 当透明字节:规范要求服务端把 requestState 视为攻击者可控输入——若它影响授权、资源访问或业务逻辑,服务端必须做完整性保护(HMAC 或 AEAD),并应在受保护载荷内放入防重放字段。对 Nexus Runtime Server 的 MCP Proxy 而言,这一点比”少管理几条连接”重要得多:Proxy 若只做透传,等于把一个可被篡改的授权凭据暴露在链路上,与本章 RPCReplayGuard 要防的重放属于同一类问题。

CIMD 身份模型对安全管线的影响:

  • DCR 被 CIMD 替代——Installed Agent 的 MCP 客户端身份由域名托管的元数据文档证明,而非运行时注册。这意味着 Traefik TBAC 策略中的 Agent 身份可绑定到域名而非动态 token。

迁移窗口:正式规范 2026-07-28 发布,向后兼容迁移窗口为 12 个月,至 2027-07-28 截止(Roots/Sampling/Logging/DCR 等弃用项同属此窗口)。以本书当前时间点(2026-09)计,发布至今约七周,适配工作仍处于窗口期的前 15%。现有 sticky session 逻辑在新协议下已成为死代码,移除可简化 Proxy 代码量。

Logging 弃用与 trace context 标准化对治理审计的影响:MCP 7/28 同时弃用协议级 Logging(SEP-2577,12 个月移除窗口),改由 stderr + OpenTelemetry 承担结构化可观测性,并标准化 W3C trace context(traceparent/tracestate/baggage)。对 Nexus Runtime Server 的 Proxy 治理层意味着:审计日志可直接对接 OTel Collector,而非维护私有 MCP 日志格式;trace context 的标准化也使 Proxy 层的请求追踪能与 MCP server 内部 spans 无缝关联。

无状态化的代价面:无状态消除了 sticky routing,但没有消除客户端侧的会话级状态。实测中,一个无状态远端 MCP server(典型场景:网关/代理正在重新部署)只要短暂返回一次 HTTP 404,客户端就会在本次会话剩余时间内把它判为不可用,而界面仍显示”已连接”(Claude Code 2.1.283,2026-09-25 修复)。

对 Nexus MCP Proxy 的含义:Proxy 侧必须区分”server 已连接”与”server 可用”两个状态,并对瞬时 4xx/5xx 做独立的健康判定与恢复,不能让一次抖动把整场会话钉死。这与本章 RPCReplayGuard 要防的问题属于同一族——都是”连接层看起来正常、语义层已经坏了”。

Agent-Aware 优雅错误处理

传统网关拦截返回 HTTP 403 会中断 agent 多步工作流——ReAct 循环被强制打断后,agent 无法恢复上下文继续执行。Traefik 和 RapidClaw 均采用更优雅的模式:返回 HTTP 200 + schema-compliant 拒绝消息,agent 可理解拒绝原因并调整策略继续运行。

对 Nexus 的启示:Runtime Server 的 LLM Proxy 拦截恶意请求或超限请求时,应返回结构化拒绝消息(如 {"error": "budget_exceeded", "remaining_budget": 0, "suggestion": "use_compact_model"}),而非直接 HTTP 403。这使 Installed Agent 的 ReAct 循环不被打断,可降级到更经济的模型继续运行。

与 OpenHands Action Execution Server 的对比

OpenHands 的 Action Execution Server 是 Nexus Runtime Server 的直接对标方案,核心差异:

维度Nexus Runtime ServerOpenHands Action Server
框架FastAPI + Socket.IOFastAPI(单端点)
端点设计多端点(/invoke + /call_executor + /venv)单一 /execute_action
插件系统无VSCode / Jupyter / AgentSkills
OOM 防护无内存监控 + 主动 kill
MCP 集成无内置 MCP proxyMCP proxy manager
Worker 隔离VenvManager + BFS 闭包复用无(单进程执行)
大 payloadBlob Sideband(独立端点)无特殊处理

设计权衡:

  • Nexus 的多端点设计提供了更细粒度的控制(invoke vs call_executor vs venv),但增加了 API 复杂度
  • OpenHands 的单一端点更简洁,但灵活性受限
  • OpenHands 的OOM 防护是 Nexus 缺少的重要特性——当 Agent 执行失控消耗内存时,Nexus 缺少主动检测和恢复机制

与 Traefik Hub Triple Gate 的对比

Traefik Hub Triple Gate(API Gateway + AI Gateway + MCP Gateway)是基础设施层的生产级方案,Nexus Runtime Server 则是应用层代理,两者定位不同但功能重叠:

维度Nexus Runtime ServerTraefik Hub Triple Gate
治理范围仅 LLM 代理LLM + MCP + API 统一治理
安全管线无内置多供应商并行(Presidio/NIMs/Granite Guardian)
成本控制Token 计数(事后统计)Token 配额 + USD 上限 + 多级断路器
容错路由无多供应商 failover
Agent-Aware 错误无200 + 结构化拒绝
MCP 访问控制无TBAC 细粒度 + 审计日志
部署形态沙箱内 FastAPIK8s Helm / 独立网关
Token 限速无per-user/team/endpoint

关键差异:Traefik 覆盖范围更广但定位于基础设施层,Nexus 定位于应用层但拥有更深的 Agent 运行时上下文(如 Socket.IO 事件流、Worker Venv 状态)。理想的架构是两者协同——Traefik 在基础设施层治理 LLM/MCP/API 流量,Nexus 在应用层利用运行时上下文做更精细的 Agent 行为治理。

除 Traefik 外,2026 年 MCP Gateway 生态已扩展为多方案竞争格局。下表六项的仓库归属、许可证与官方一句话定位已于 2026-09-15 直连 GitHub 核实(star 数为同期快照):

方案官方仓库许可证官方一句话定位
Docker MCP Gatewaydocker/mcp-gatewayMITdocker mcp CLI 插件 / MCP Gateway;目录中的本地 MCP server 各自跑在独立隔离容器里,npx/uvx server 只授予最小宿主权限,密钥经 Docker Desktop secrets 管理而非环境变量
IBM ContextForgeIBM/mcp-context-forgeApache-2.0位于 MCP / A2A / REST-gRPC API 之前的 AI Gateway、registry 与 proxy——即不必重写就能把既有 REST/gRPC 内部 API 暴露为 MCP 工具
Microsoft MCP Gatewaymicrosoft/mcp-gatewayMITMCP server 的反向代理与管理层,面向可扩展、安全的部署
Lasso MCP Gatewaylasso-security/mcp-gatewayMIT插件化网关,用于编排其他 MCP server
Obotobot-platform/obotMIT完整的 AI 治理平台
Kong AI GatewayKong/kongApache-2.0”The API and AI Gateway”——MCP 流量以插件形式叠加在既有成熟网关之上

⚠️ 表中”官方一句话定位”取自各仓库 GitHub 首页自述,属一手来源;但各类横评中流传的更细的能力描述(如 Microsoft 侧的 Entra ID RBAC 与会话感知路由、Lasso 侧的 prompt injection 实时检测与 server 信誉扫描、Obot 侧的 hub-and-spoke 控制平面、ContextForge 侧的多集群联邦治理)本轮未能从官方文档逐项证实,仍按待核实处理,请勿与表中已核实信息混用。

另需更正一处常见误传:Docker MCP Gateway 的许可是 MIT,不是部分资料所写的 Apache 2.0。

⏳ 复检提示(2026-10-06):本轮未重取六仓的 star 数与许可证,表中 “SNAPSHOT” 类信息请按 2026-09-15 快照理解,重印前建议重取。

其中 Docker MCP Gateway 值得单独点出:本书 Ch10/Ch11 把 Docker Sandboxes 作为重要沙箱方案讨论,而同一家厂商在网关层另有这款独立产品。做网关选型时若只对标 Traefik,就会漏掉与沙箱层同源的这一层——它的定位也确实偏开发者本地与容器原生,跨团队统一策略仍需另加工具。

这些方案与 Traefik 形成”通用网关 vs 专用安全 vs 协议桥接”的定位差异——Nexus Runtime Server 在选型对标时不必局限于 Traefik 一家,可按需借鉴 Kong 的插件化、Lasso 的安全向编排、ContextForge 的 REST/gRPC 桥接等特性。

SIOBridge

Worker 进程的 Socket.IO 是 AsyncClient,Base 进程的是 AsyncServer——两者的 API 不同。SIOBridge 提供统一接口,使 Proxy 代码可以在 Base 和 Worker 中复用。

RPCReplayGuard

防止 Socket.IO 连接断开重连后重复执行已完成的 RPC:

class RPCReplayGuard:
    _completed: dict[str, InvokeResponse]  # 已完成的 request_id → response

    def should_skip(self, request_id) -> InvokeResponse | None:
        return self._completed.get(request_id)

    def mark_done(self, request_id, response):
        self._completed[request_id] = response

⚠️ 重连不是唯一的重复执行来源。 客户端实测中另有一条完全不同的路径:远端 MCP server 的返回结果超过 16 MB 或无法解析时,工具调用会被重试一次,从而实际执行两次(Claude Code 2.1.288,2026-10-02 修复)。这条与连接状态无关,上面的 _completed 字典防不住——它防的是”重放同一 request_id”,而大结果场景下的重试可能携带新的 request_id。

对 Nexus 的含义:Blob sideband 解决的只是传输效率,不等于幂等。本章 §Blob Sideband 把超过 1 MB 的数据挪到独立端点,与该阈值问题同源;若 result_ref 指向的结果在写回前失败,重试同样会重跑一次 Executor。建议在设计层面把”已执行”标记与大结果传输分开考虑。(Nexus 侧是否已有该保护需对照源码核实 📌——此为编辑推断,非已核实事实。)

另注意与 Ch13 的分工:Ch13 §持久化的边界 讨论的是”run 级重试重复副作用”,本条是”单次调用内因响应体过大重复执行”。两处应互相引用,否则读者会以为幂等问题只出现在重试路径上。