52 KiB
SIP Go Agent 重写方案 v0.3
本版按本次讨论收敛为稳定、快速单节点内测上线:1个Agent/1套Asterisk/1个单活Dispatcher、单 Cell、单租户、静态发布、ASR-only与ASR+LLM+TTS双模式。至少3家SIP供应商保留为 trunk 配置与协议 fixture 覆盖;双节点、第二 Cell、双租户、真实 SaaS/MQ 联调和生产 ECS 延期第二阶段。保留Cobra双命令、Dispatcher SQLite、Agent文件、Unary gRPC及关键可靠性;动态治理和规模化另立项。文件名保留,当前仍只有文档,不代表实现或验收通过。
1. 状态、范围与决策
状态:设计草案,不代表实现、切换或生产验收完成。
用户已确认:
-
使用 Go 1.27.1,完整重写 Agent,但分阶段替换。
-
范围包含调度、Cell 执行、ARI/RTP/录音、AI 流式适配、Cell 配置接收;不是只做一层 Go 代理。
-
go-sip/是独立 Git 仓库,自己的文档也全部放在其docs/中。 -
不重写 Asterisk,不合并独立管理平台,不改变 SaaS 的 MQ 业务边界。
-
SIP 和其它组件有适配需求的现成开源库/官方 SDK 时必须复用,绝不从零手写替代协议栈或客户端;库不满足时先证明缺口、选择替代或向上游修复,不能自行转为手写实现。
-
同一Go module、同一版本/二进制,使用Cobra的
agent、dispatcher两个业务子命令,分进程部署,方便统一更新而不混用权限。 -
不接入PostgreSQL;独立Dispatcher统一全局任务/配额,使用本地持久SQLite。Agent不设SQLite业务库,文字/录音及必要执行/上传恢复信息流式落文件。
-
内部采用 Unary gRPC;Dispatcher预配置Agent Endpoint列表,Agent业务启动参数尽量只有Dispatcher Endpoint,不增加内部MQ或双向流。
-
所有Agent共用一套mTLS证书;这只认证Agent群组,单节点授权另由受控Endpoint/自动会话绑定落实。Dispatcher身份独立,不能伪称具备独立节点证书隔离。
-
OSS配置来源于SaaS,Dispatcher向Agent提供受限上传信息并统一回传SaaS。文本保留实时MQ事件,OSS用于归档;录音按OSS ID查看。
-
Dispatcher感知Agent健康、必要资源、软件/协议能力、获授权SIP供应商和已加载配置版本;在静态授权候选内按固定、可解释策略分配新任务,不做智能负载评分或自动跨供应商重拨。
-
管理平台仍为SIP配置唯一编辑面;P1以批准的静态快照经受控部署入口加载,Dispatcher控制准入并核验Agent加载事实,暂不建设在线动态发布/回滚编排。
-
本次固定1个Agent、1套Asterisk、1个单活Dispatcher、单 Cell、单租户;至少3家独立SIP供应商保留为 trunk 配置/路由/协议 fixture 覆盖。双节点、第二 Cell、双租户不在本轮开发或验收范围。
-
ASR-only与ASR+LLM+TTS均为本次必需能力,按本地/隔离协议和状态机验收;真实供应商/ECS 联调延期第二阶段,不以 Mock 冒充真实供应商通过。
-
upload-session/complete/verified、RabbitMQ ACL/TLS 和 application receipt 本阶段按版本化契约、Schema、正反例 fixture 和本地隔离状态机验收;真实 SaaS/MQ 联调延期第二阶段。
以上范围不再列为待定。G0只冻结P1实际使用的Proto、事件payload、双AI模式及SaaS配置/调参、静态配置交接、录音授权、共享证书授权和运行阈值;后续功能有明确阶段,不再要求所有未来缺口同时关闭。本轮不创建Go骨架、数据库、broker或真实呼叫。G0开发准备与契约冻结方案 D01–D10的方向、模式/许可/恢复机制及内部PoC初始profile已获用户确认;权威源发布、正式Proto及验证仍未完成,不能视为G0通过。本轮只同步文档,不修改上游Schema或创建代码。
OSS数据面已明确为Agent→OSS直连上传:Agent从Dispatcher获取本录音的受限目标/凭证/headers等配置后自行上传文件;Dispatcher不接收或转发录音字节,负责SaaS上传会话/complete协调及verified后的MQ结果回传。每次下发token有效15分钟;过期或失败时保留源文件,由调用方显式重新申请,不自动续期或重试。此直传不改变Agent不直连SaaS的边界。
1.1 本次P1目标与完成标准
| 目标 | 完成判定 |
|---|---|
| 单节点/单 Cell/单租户 | 1个Agent/1套Asterisk/1个单活Dispatcher;单 Cell 静态制品、单租户准入和本地持久恢复闭环;不要求第二节点或第二 Cell |
| 至少3家SIP供应商 | 每家独立trunk/主叫/前缀/codec/额度的契约、路由和协议 fixture 校验;真实供应商成功外呼延期第二阶段 |
| 双AI模式 | 两种模式均在本地/隔离环境从命令到通话模拟、实时文字、录音和结果闭环;ASR-only不调用/占用LLM/TTS,真实新供应商联调延期 |
| 单租户、静态配置 | 只启用一个可信租户;使用管理批准的不可变单 Cell 快照,初装及维护变更均核验实际加载,错版本/哈希不接单 |
| 可靠性基础 | 同执行不重复拨号、未知不重拨、控制屏障/持久恢复/录音交接安全;租户独立队列、复合幂等键和单 Cell 调度边界留在本轮 |
| 契约与独立交付 | SaaS/MQ 交互按版本化契约、Schema、fixture 和本地状态机验收;可独立检出、构建、测试、打包,无父仓库/Python运行依赖 |
验收按验收方案§1.1–§1.2执行。P1通过只表示当前单节点/单 Cell/单租户本地范围通过;不代表真实 SaaS/MQ receipt、真实供应商/ECS、双节点、第二 Cell、双租户、1000路/N+1或生产切换通过。
1.2 明确不做
- 不自研 SIP 协议栈,不逐通电话重写
pjsip.conf或重载 Asterisk。 - 不建设第二套 SIP 管理后台,不共享管理平台或 SaaS 的业务数据库。
- 不引入自研调度框架、插件系统、服务网格、事件溯源平台或默认 Kubernetes。
- 不复用
voice_test的 LLM/TTS;验证前仍明确Mock/未启用,但真实双模式是P1退出门禁,不是可删减项。 - P1不做在线动态配置编排、自动跨供应商FALLBACK、活动通话迁移、多Dispatcher HA、权重借用、AI插件/多供应商编排、文本OSS归档、1000路/N+1验收。
- 本轮不开发或验收双租户、公平调度和第二 Cell 汇总配额;保留 tenant_key、独立队列、复合幂等、单租户配额和控制屏障。多租户/跨 Cell 能力作为后续阶段,不能在本轮状态中标为已通过。
- 不把整份 Python 源码机械翻译为 Go,也不为使用新语言特性而增加抽象。
2. 已有实现与迁移依据
以下路径仅记录现有实现的来源,不是新项目的运行依赖:
| 现有模块 | 已观察到的职责 | 新项目处理方式 |
|---|---|---|
agent_call/core.py |
持久状态、租约、租户轮询、控制、MQ inbox/outbox、上传与补传恢复 | 拆出调度控制面,重建自有持久化边界 |
agent_call/real_cell.py |
ARI、RTP、通话资源、路由验证、执行账本、未知执行对账 | 迁移语义到Agent文件恢复与Dispatcher权威账本;不照搬Agent SQLite,不确定不重拨 |
agent_call/cell_agent.py |
配置版本/哈希校验、落盘、Asterisk 应用和状态回执 | 迁移为 Cell 的受控配置接收能力 |
agent_call/ai_runtime.py |
ASR/LLM/TTS 流式编排及取消 | 按新项目的音频与供应商契约重新划界 |
services/asr-web |
已有 Go ASR 协议实现 | 复用其已验证行为/测试;先选匹配供应商协议的现成 SDK,不照搬或重写二进制协议,不依赖原服务目录 |
management/ |
独立 Go 管理 API 和前端 | 保持外部系统,只通过批准的版本化接口集成 |
当前 Python 调度每轮涉及租约、指令接收、控制、调度、outbox 等多个职责;真实 Cell 已有本地执行账本。行为和测试可以复用,进程内锁、线程组织以及调用方/执行方混在一个服务中的边界不能照搬。 尤其不得让生产 Agent 同时扮演 SaaS 事件消费者或写 SaaS 数据库;这些能力只能存在于独立测试端。
3. 独立项目与契约管理
3.1 目录规划
下面是逐阶段建立的目标布局,不是本轮已经生成的文件列表:
go-sip/
├── AGENTS.md
├── README.md
├── go.mod / go.sum # 独立模块;P1 再创建
├── cmd/sip-go-agent/ # 唯一main,Cobra根命令
├── internal/
│ ├── cli/ # agent / dispatcher 两个子命令
│ ├── contract/ # 从批准契约生成的类型/校验入口
│ ├── rpc/ # 生成的Unary gRPC桩与薄适配
│ ├── dispatcher/ # MQ、租户感知调度/配额、SQLite/outbox;P2补公平
│ ├── agent/ # 通话执行、文件恢复、配置加载、状态采集
│ ├── media/ # 现成RTP/音频能力、录音与打断
│ ├── ai/ # 现成供应商SDK薄适配
│ └── store/ # 仅Dispatcher的SQLite事务/迁移
├── migrations/ # 仅Dispatcher业务数据库迁移
├── config/ # 无密钥的配置样例
├── contracts/ # 带来源与校验和的只读契约发布包
├── tests/ # 项目内夹具、协议 Mock、集成与故障注入
├── deploy/ # 独立镜像、Compose/systemd 与运维入口
└── docs/ # 本项目方案、运行、验收和发布文档
采用单Go module、同一发布版本/镜像、少量具体类型。使用github.com/spf13/cobra,不手写命令解析或引入第二个业务main。显式业务子命令只有agent、dispatcher;help/version是框架能力,不再提供scheduler/cell两套别名以免运维混淆。只在真实边界建立小接口,不建通用调度/插件框架。
规划用法(当前本地制品已提供 agent/dispatcher;生产参数仍须受控注入):
sip-go-agent dispatcher --config <受控配置文件>
sip-go-agent agent --dispatcher-endpoint <Dispatcher管理网地址>
Dispatcher配置包含MQ/SaaS受控引用、SQLite路径、两个Agent Endpoint→agent_id/cell_id绑定及准入策略;Agent证书/信任根、监听地址、ARI访问、持久目录及批准的静态快照由部署提供。只需Endpoint指业务启动不再手填SIP/OSS配置,不代表无需凭据、持久盘、Asterisk或静态制品。 静态制品不是允许运维另写业务Schema;不在CLI传密钥,不让agent初始化MQ/业务DB或dispatcher打开RTP端口。
两角色同一制品便于更新,不等于必须同时重启;P1采用受控维护窗口,不承诺混合版本无损滚动更新,见§5.7。
3.2 权威来源与独立拆仓
现有上游权威是《SaaS交互_OpenAPI与MQ契约规划_v0.1.md》(正文 v1.0)及经核验的发布产物。现有产物包括 mq.schema.json、executor.openapi.yaml、cell-agent.openapi.yaml、AI 配置及 SIP 管理相关契约。文件存在不代表完整覆盖:P0 必须逐条核对正文、Schema、状态语义和实现差异。
- 将经批准的协议作为版本化、只读发布包导入本项目
contracts/,记录源仓库、源版本/提交、文件 SHA-256 和生成器版本;工作区未提交修改不能冒充某个提交的发布产物。 - 类型和校验代码从该发布包生成;禁止手写另一套字段、枚举或业务 Schema。
- 同步工具在开发阶段获取发布包;普通构建、测试和发行包运行不得读取父目录。
- 新增调度器—Cell 的消息、fencing、回执或对账字段,先形成契约变更提案并获批;本方案不擅自定字段或 MQ 路由。
- 本项目自己的设计、运行、验收文档只在此处维护;上游共享契约仍只有一个编辑源。
- 本项目已独立初始化 Git,并按
git.ipao.vip/rogee/go-sip维护;不创建 submodule 或改变父仓库跟踪关系。项目许可证和第三方 NOTICE 在对外发布前确认。 - 通信与事件数据交互覆盖1类外部执行命令、8类业务事件、现有HTTP归属及13个内部Unary职责草案;字段索引完整提取42个HTTP操作/115个命名组件。
- 已逐字段/哈希确认MQ信封command_type/command_id、event_type/aggregate_*及task_revision与正文一致;但事件payload目前仅通用object,专属约束仍需上游补齐(GAP-01)。不能以旧测试或通用object校验冒充完整验收。文字事件准确名称为transcript.updated。
- 42操作/115组件是上游目录,不是本项目首发工作量。P1保留既有7条SaaS交互路径/8种事件,并消费实际所需AI配置和静态制品;不实现管理平台30个API或复制其业务后端。生成/校验仅覆盖使用入口及其引用闭包,来源包与只读字段索引保持完整。
- 当前AI Schema强制要求llm/prompt/tts/asr/conversation,缺少明确的ASR-only表达。GAP-08须先在上游批准模式/缺省/文字与错误语义;不在MQ添加临时mode字段或绕过required校验。
4. Go 1.27.1 的采用策略
已用本机 GOTOOLCHAIN=local go version 核验 go1.27.1 linux/amd64,并核对官方 Go 1.27 发布说明与本地 go doc。以下区分“新版本能力”和“已有成熟能力”,不把所有 API 都说成 1.27 新增。
| 能力 | 使用位置与收益 | 边界 |
|---|---|---|
Go 1.27 encoding/json/v2 |
新 JSON 协议边界的候选实现,减少兼容包依赖 | 先过黄金报文与哈希兼容测试;不直接替换全部旧编码行为 |
Go 1.27 uuid |
新项目自生成且契约允许的 UUID | 不改既有命令/事件/执行标识格式,更不改原值 tenant_key |
| Go 1.27 goroutine leak profile | 长时间通话、取消/断线循环后的泄漏诊断 | 仅管理网/本地诊断,不公开 pprof |
Go 1.27 testing/synctest.Sleep、httptest.NewTestServer |
测试定时、取消、重试与 HTTP 协作 | 真实 socket、broker、DB 的故障仍用真实集成测试,不能只靠虚拟时钟 |
已有 context、sync.WaitGroup.Go、log/slog、net/http、pprof |
生命周期、结构化日志、内部 HTTP 和诊断 | WaitGroup.Go 不负责错误传播;任务必须返回/上报错误并正确退出,不把它当 panic 隔离 |
| 泛型与语言新能力 | 简单类型复用 | 没有实际重复就不用,不建立通用调度 DSL |
| Go 1.27 实验性 SIMD | 不采用 | 当前重点是 I/O 编排,不增加实验开关或平台约束 |
特别注意:JSON 新版本在重复键、大小写、空集合、数字、字段省略和对象输出顺序等方面可能与旧行为不同。content_sha256、签名或配置摘要必须遵守上游的确切规范化规则,不能把某次 Marshal 输出或“排序一下”当成通用 canonical JSON;Python/Go 黄金样本不一致就阻塞发布。非法/歧义 JSON 应按获批契约拒绝,不为兼容而接受歧义。
P1 建模块时拟使用 go 1.27.1 并锁定 CI/构建镜像及 digest;go 指令是最低工具链要求,不是精确锁定。CI 校验实际版本并使用 GOTOOLCHAIN=local,不靠运行时自动下载工具链。未来补丁升级走独立验证,不连带修改管理平台或其它服务的版本基线。
4.1 开源库优先是实施硬约束
标准库/现有服务原生能力能覆盖的先用它们;其余使用经评估的现成开源库。自有代码只承担契约绑定、状态机、权限、配额、事务和必要的薄适配,不能以“薄适配”为名重写 SIP/ARI、RTP 编解包、G.711、WebSocket、AMQP、数据库驱动、OSS 签名、供应商 SDK 或 Schema 解析器。
候选、许可证、上游证据与风险集中维护在 开源组件清单。使用Cobra、官方grpc-go/protobuf、gopsutil、Asterisk/ARI、Pion、amqp091-go;modernc SQLite用于Dispatcher,pgx退出本项目选型,Agent不引数据库驱动业务能力。ASR/LLM/TTS按批准供应商选SDK。不将所有候选一并引入,不用sipgo/diago另起SIP栈。
P0 必须以锁定 tag/commit 的 PoC 验证 Go 1.27.1、Asterisk 镜像、API/音频格式和现有契约,检查许可证全文、传递依赖、安全通告及 SDK 自动重试;失败则阻塞该组件,不默许改为手写协议。只有业务接口确有必要才抽象,不额外引入 Web 框架、ORM、Redis 锁或认证服务。
当前契约为 OpenAPI 3.1 / JSON Schema 2020-12。生成/校验库必须实测支持这一方言及原契约;不能把开发分支能力当已发布能力,不能为了生成器方便手工降级或复制 Schema。依赖锁版、许可清单、漏洞处置与复用审查是 P1/发布门禁,验收见 L01–L08。
5. 目标运行架构
SaaS ── RabbitMQ命令 ──> dispatcher(单活SQLite)
SaaS <── RabbitMQ事件 ── dispatcher outbox
SaaS <── 既有HTTP控制/查询/录音握手 ──> dispatcher
管理平台 ── 批准静态快照 ──> 受控部署入口(维护窗口)
│
dispatcher ── Unary gRPC ──────┼─ agent-1 ↔ Asterisk-1 ↔ 获授权的SIP trunk
(mTLS) └─ agent-2 ↔ Asterisk-2 ↔ 获授权的SIP trunk
├─ 两种AI模式、文字/录音/恢复文件
└─ Dispatcher授权 → OSS直传
内部不再增加MQ或双向流。Agent不拿broker/SaaS管理凭据,业务事件统一由Dispatcher发布;内部RPC不是新的SaaS拨号HTTP入口。两个Cell分别使用获授权固定出口,多EIP直连;至少3家供应商按矩阵预配置独立trunk,不承诺每家已同时授权两个出口。Dispatcher可与一个Cell同机但权限/目录/资源隔离,该节点故障会同时影响中央调度,不能宣传两节点即自动HA。
5.1 Dispatcher:唯一业务状态与调度权威
持久化命令、执行归属、租户/供应商/Cell/按模式AI全局配额、控制CAS、许可、静态目标版本/加载事实、事实去重、资产交接和outbox。单个活动Dispatcher负责决策;同机竞争实例可做所有权/恢复测试,但不以两台各有SQLite的Dispatcher各自发额度。
SQLite业务状态留在Dispatcher,管理平台数据库保持独立。首版不承诺跨机自动热备:备份/恢复时必须停止旧所有者、对账,再开放新准入,禁止NFS共享DB、双活复制或把MQ当数据库。Dispatcher故障暂停新拨,已授权通话在Agent继续,结果落文件待补。
每天2万次:24小时平均约0.23次/s、8小时约0.69次/s;假设每通100条业务写入,8小时平均约69条/s,只是量级估算不是基准测试。若是每Agent2万,中央总量按Agent数汇总;验收要测峰值CPS、并发、写放大、保留和故障恢复,不据日均承诺1000路容量。
5.2 Agent:无业务数据库的执行端
不自行分配全局额度、不消费SaaS MQ、不承担另一份任务主库。通过Unary执行授权、控制和配置,在本Cell维护ARI/RTP/AI会话,流式落文字/录音及必要manifest,回报真实事实/上传结果。
每通话固定在同一Cell/出口;不因Dispatcher短暂不可达自动挂断,也不把Agent重启说成通话无损续接。每通话一个生命周期所有者,媒体/AI工作有界可取消,不创建每包goroutine;共享ARI事件按通话分派,控制不能静默丢失。
5.3 持久化与恢复(SQLite/文件方向已确认)
| 数据 | 落点 | 边界 |
|---|---|---|
| 全局任务/配额/归属/控制、事件/静态配置事实/资产、inbox/outbox | Dispatcher独立SQLite | WAL、可靠Sync策略、短事务/有界写队列、唯一约束与条件更新;提交后MQ ACK,不跨网络持事务 |
| 活跃通话上下文 | Agent内存+Asterisk真实通道 | 不是任意实例可替换的无状态HTTP请求;未知执行须对账 |
| 执行关联/配置加载/待回报事实/上传进度 | Agent受控文件/manifest | 原子替换、关键事实同步落盘、单写者与尾部截断识别;不用Agent SQLite,也不自造通用数据库 |
| 文字/录音 | Agent持久spool;P1录音→OSS,文字OSS归档后续 | 实时文字先回报;文件封口、摘要校验、恢复与保留条件完整 |
推荐SQLite WAL+synchronous=FULL作为关键事实持久性基线,具体驱动/文件系统/锁/忙等待在P0验证;记录不能按RTP包或每token逐条写中央库。单文件仍只有一个writer,长期读事务/checkpoint/磁盘空间必须监控。备份用SQLite一致性备份能力,不在运行中只拷db忽略WAL。
恢复旧备份可能丢失已ACK的事实/许可/版本;先关准入,对比Agent文件、Asterisk、MQ与资产水位,不恢复过期许可或盲重拨。去重/stop墓碑不套普通日志TTL。持久卷完好崩溃、旧备份、满盘/只读、永久丢盘分开验收;永久丢失未上传资产不能承诺RPO=0。
5.4 Unary通信与最小启动
Dispatcher受控配置列出Agent Endpoint及agent_id/cell_id绑定,监听地址必须管理网可达;不信任Agent提交的任意回拨地址。Agent先加载受控证书、本地监听/ARI及部署交付的静态制品,以Dispatcher Endpoint请求引导;不由用户再手填SIP/OSS/AI业务配置。
初次调用若未绑定只返回pending/非敏感能力;Dispatcher主动探测预配置Endpoint,核对boot/协议,再向该端点激活受限节点会话。Agent得到会话后获取自身运行策略、SIP/AI版本索引和OSS策略引用,加载并报告ready。任何身份/版本/凭据缺失都只允许诊断,不接真实任务。
普通Unary复用HTTP/2连接;Execute只返回accepted/rejected,不等待整通话;状态/最终文字/上传结果独立回报。SDK重连不证明业务未执行,回应丢失只按原标识查询/重报,不盲目再originate。Proto方法/字段号、截止与大小见交互草案,P0冻结后生成。
5.5 共享mTLS的权限边界
用户选择所有Agent共用证书,便于扩展;证书/私钥通过Secret/受控文件挂载,不写进镜像/仓库/参数。Dispatcher使用独立受信身份,Agent管理RPC不能接受仅有Agent群组身份的对端。
共享证书只认证群组:禁止凭自报agent_id/源IP直接领取另一节点的配置或执行。采用预配置Endpoint主动激活和自动签发的受限节点会话,将agent/cell/boot/代次/操作范围绑定;无需用户逐节点填写运行token,但具体认证中间件、期限、重放/撤销机制须PoC,不能自创密码算法。
必须验证SAN/SNI/信任链,不设InsecureSkipVerify;共享证书要覆盖合法管理域名/受控SAN,扩容不能靠关闭主机名校验。管理网隔离/DNS控制/最小端口仍必要。任何Agent私钥泄露影响整组,需全组轮换/撤销;会话授权只能减少误绑定,不等价独立证书的节点隔离。把这一已知风险留在发布签收中。
5.6 健康准入与静态候选选择
Dispatcher定期调用GetAgentStatus,复用既有2s心跳/10s失联基线;以本机接收时间判新鲜,保留Agent采样窗口/序列/boot,过期/缺失为unknown而非0。gRPC SERVING只说明能应答,不说明可拨号。
P1状态包括软件/构建/Proto/Asterisk版本,准入必需的CPU/内存/FD/磁盘/spool、媒体端口、ARI及已知/未知占用,本模式AI健康,静态授权trunk的codec/注册适用性/desired与applied版本/哈希。完整load/IO历史、staged发布态和高级评分后续再做。用gopsutil/ARI SDK采集,区分host/container/process,不自写/proc解析。
P1选择顺序为:可信绑定与协议兼容→静态route_policy/caller_profile及授权矩阵匹配→版本/出口/新鲜健康/未排空→租户/供应商/Cell/本模式AI配额→在可行Agent内按固定轮询分配新执行。已建立执行意图后固定归属,不因健康变化改投另一Cell;未发起的新执行可选同策略下其它获授权健康Cell。CPU低不能越额度,新boot/0活动不能清中央未知占用。不做价格/权重优化、自动跨供应商FALLBACK或活动通话迁移。
CPU/内存/FD等首发必要保护阈值和恢复条件在profile登记;spool沿用70/80/60%规则。供应商“支持能力”“已配置”“已加载”“真实验证”分别展示,未验证线路不报ready。P1只传有界静态清单及必要状态,不先建全量遥测/供应商分页平台。
5.7 一个制品、维护窗口更新
Cobra两命令共用release版本、依赖锁、镜像和协议包;每个进程只能启动所选角色,凭据/目录/监听权限分离。更新前检查Dispatcher/Agent协议兼容范围与配置Schema,不兼容的节点拒绝新准入,不尝试猜测字段。
P1允许维护窗口暂停新任务:关闭受影响资源准入、排空/对账、备份、更新、重新激活、核验实际配置和资源后恢复。当前只验收单 Cell;第二 Cell、多节点并行和在线滚动编排属于后续阶段。Dispatcher保持唯一所有者,迁移/恢复先验证;Agent不执行远程任意shell或自下载二进制。
6. 核心可靠性设计
6.1 消息接入与 ACK
以下MQ消费/发布和业务数据库事务仅由Dispatcher承担;Agent事实经gRPC进入中央事务。沿用 agent-call 资源命名空间,不因项目名变化而重命名协议资源:命令 exchange 为 direct,routing key 为 agent-call.tenant.{tenant_key}.call.execute,事件 routing key 为 agent-call.{event_type};不把 SaaS 业务结果队列改成每租户一条。
- 以可信队列绑定校验
tenant_key、正文身份和版本;原值一对一,不清洗、编码或截断。超过 224 个 UTF-8 字节的既有路由预算时保留原任务并停发,不能换一个 key。 - 先验证认证、租户归属和基本 Schema,再识别已持久化的历史幂等事实,最后才对新执行检查当前控制状态、不可变 agent 版本和资源准入。重投不能因当前配置/任务状态变化而改写原决定;权限检查不能因命中历史而绕过。外部命令不能注入 SIP 地址、主叫、密钥或任意 AI URL。
- inbox 与可恢复待执行状态在同一事务持久化后,才 ACK broker;无效消息按既有拒绝/死信契约可靠处理,不能先 ACK 后记原因。临时额度不足进入受限持久等待,不丢弃合法任务。
- 传输消息 ID 与业务标识的映射遵守契约;命令、执行、事件的唯一键分别为
(tenant_id, command_id)、(tenant_id, execution_id)、(tenant_id, event_id),禁止只按 execution ID 跨租户去重。同键异载荷按契约冲突处理;换 command ID 不能绕过同一执行去重。 - 业务 outbox 与产生它的状态变更同事务提交;MQ confirm 后只标记运输层发布成功。confirm 丢失允许以原
event_id重发,不创造第二个业务结果。 - broker 持久化、publisher confirm、mandatory/不可路由处理、手动 ACK 和重试退避均必须真实验证。事件 confirm 不是 SaaS 业务应用收讫,不增加应用 ACK。
启动须核验 broker 的 exchange 类型、精确绑定、持久化、ACL、队列上限和拒绝发布策略;配置漂移即不 ready。处理 mandatory return、confirm 丢失、blocked 和全局水位;满队列拒绝新发布,不丢队头,SaaS 保留原任务。死信/重试恢复回原租户配额,租户停用和清理先完成未决任务/消息/资产对账。现成 AMQP 库不等于已实现这些业务保证;连接恢复封装也需过 S04/S05/S20–S22。
MQ 的 exactly-once 拨号不是可承诺特性。采取持久幂等、授权屏障和不确定就不重拨的策略,并把未知执行放入可对账状态。
6.2 多租户分期与资源预留
P1现在做骨架和安全,不开放多租户运营:
- tenant_key原值贯穿租户独立队列、持久记录、事件与受控诊断;保留tenant_id复合幂等键,不用default tenant或共享总FIFO。
- 调度按可信的活跃租户集合组织,当前启用列表只含一个租户;其它租户不能因发来消息就自动启用。每租户/全局prefetch、未ACK、持久待执行及内存窗口有界,额度不足时不绕过限制。
- 一次预留原子校验当前租户并发/CPS、供应商并发/CPS、单 Cell/媒体端口、出口及本模式AI额度:ASR-only只需ASR;完整模式必须同时具备ASR/LLM/TTS,不以缺少LLM/TTS阻断合法ASR-only,也不静默降级完整模式。
- 单 Cell 额度在单活Dispatcher SQLite短事务中校验/更新,唯一约束/CAS防竞争;并发覆盖预留/拨号/振铃/接通/未知,未知是否发起不错误退还CPS或释放并发占用。
- 所有权代次/fencing、时效和最后发起许可在本轮实现并故障注入;Cell每次originate前必须核验,pause/stop/维护屏障覆盖已发许可。
- 本轮只验证一个可信租户;不开发双租户公平、第二 Cell 汇总或多 Dispatcher 协调。未来阶段再增加多活跃租户轮询、背压、轮转恢复和跨 Cell 汇总配额。
P2/后续多租户能力不作为本轮退出门禁。未来若启用获批FALLBACK,仍计原执行attempt/CPS,不能获得免费额度。
6.3 执行、结果与不确定窗口
Dispatcher事务:控制/归属校验 → 预留资源 → 持久执行意图
→ Unary Execute → Agent保存原执行/通道关联文件并返回accepted
→ Unary最后许可(含 Asia/Shanghai 09:00–20:00 时间门禁) → ARI originate → 跟踪实际通话事实
→ Agent文件持久待回报 → Unary Report → Dispatcher事务状态/outbox
→ SaaS MQ事件 + 全局对账/资源释放
SIP 外呼时间窗口为 Asia/Shanghai 每日 [09:00, 20:00);窗口外在最后许可和 Agent 执行入口均 fail-closed,不等待、自动延迟、重试或换线。上图是内部处理顺序,不新增对外状态枚举。对外状态必须从批准契约生成。
- 中央幂等/固定归属、Agent恢复文件和Asterisk关联共同防重;任何SQLite/文件提交都无法与外部originate做原子事务,Agent无SQLite不等于可跳过对账。
- 在 originate 超时、进程退出或网络中断时,利用稳定执行/通道标识、ARI 状态和账本对账;无法证明未拨或已结束则保持未知占用,不自动另起一通。
- Caller/callee 由 Cell 受信配置映射;切换线路必须从原始被叫重新构造,禁止串用上一线路前缀。
- 用户业务重试仍由SaaS决定。P1静态策略不启用自动跨供应商FALLBACK;新执行的选路从原始号码开始,失败如实返回。若输入要求未支持策略,按批准的能力/拒绝语义处理,不能静默改写;未来扩展仍不得重拨已接通或未知执行。
- 控制、记录、录音、结果分别持久化重试;OSS 或 MQ 故障不能导致已完成通话再次执行。
6.4 控制屏障
沿用主契约的租户作用域 command_id 幂等、expected_task_revision CAS;区分 requested_task_revision 与 applied_task_revision,同 command 重试不能再次递增版本。
- HTTP 202 仅表示 accepted;相关 Cell、在途许可和要求的挂断均确认后,才能通过 MQ 报 applied。失联/结果未知继续 applying/reconciling 并告警,不伪造成功。
pause停止新发起,已拨出(包括拨号/振铃)和已接通电话继续原生命周期;收敛的是尚可发起的在途许可,不以暂停为由取消已拨出通道。stop必须显式指定active_call_policy=drain|hangup:drain 让已有电话自然结束;hangup 还需outbound.hangup权限并等待挂断确认。- 撤销号码先由 SaaS 禁发并对相关旧任务建立整体 pause 屏障,不能用临时删 broker 消息代替。SaaS 过滤撤销对象、对账旧执行后,paused 任务可以按当前已生效 revision 恢复;剩余对象用新 command/execution 授权,旧命令重投不能复活。
- 只有 stopped 任务不可 resume。是否改用新任务由 SaaS 决定,Agent 不能强制把 pause 改成不可恢复的 stop。
6.5 整体补传
HTTP 仅按一个 call_id 或 source_command_id 发起整体补传,不增加 task/execution 范围或事件/turn/资产筛选。受理时固定截止点,使用原 event ID/内容/版本,分批、限速并优先实时结果;source command 尚无 call 也应能恢复其结果。区分不存在与保留过期(404/410),补传自身 command.result 不得循环纳入;completed 只表示该固定集合发布完成,不代表 SaaS 已应用。
6.6 最终文字、事件与 DNC
Dispatcher对Agent稳定事实去重后,按 command/call/transcript_segment/recording 的实体与状态域事务持久化聚合版本,payload 是该域的快照;测试中的独立 SaaS 按同域合并。不能用全局最大版本丢掉低版本但独立的录音/attempt,也不能用 call.finished 覆盖 recording.ready。最终文字不会被迟到中间稿覆盖;当前基线同段 final 同内容幂等、异内容冲突,未来允许修订须经 G0 更新契约。文字失败必须出 transcript.failed,通话结束不等待所有后处理。
客户实际说话与 AI 生成/发送/播放证据严格区分,旧轮次片段取消后不能冒充已播放。contact.opt_out 按获批业务判定及时发布,不等挂断;SaaS 持久禁发并枚举相关任务完成屏障。Agent 不能用未经确认的关键词替代业务判定。
7. 媒体、录音与 AI
7.1 ARI/RTP
- Asterisk 继续实现 SIP、注册和编解码协商;Go 使用现成 ARI SDK 管理通话/桥/ExternalMedia/录音/事件,不手写 ARI 客户端。SDK 缺口优先用已有 API 组合或修复上游,不另起 SIP 栈。
- 固定通话到 Cell/出口,验证受信路由和配置版本。白名单原始号码仅为
15003164745、15830461047;写入配置不代表授权发起测试。 - 已知供应商 PCMA 作为待真机复验的基线,不把一个供应商的前缀/主叫或媒体源带到其它线路。
- RTP/RTCP 编解包使用 Pion 等现成库;在 SDK 边界校验长度、扩展、padding、SSRC、序号/时间戳回绕、源地址及负载类型。抖动/乱序/节拍也先评估现成组件,不复制协议解析器。
- 转码/重采样优先使用 Asterisk 现有能力;确需 Go 侧 G.711 时评估
zaf/g711,不手写 A-law/μ-law 算法或线性插值重采样。明确 PCM 端序、采样率、声道、帧时长和缓冲策略,不能硬编码“所有链路都是 20ms”。 - 每 Cell 独立分配媒体端口;端口池、FD、包率与带宽均计入容量,不能用现有
10000–10800范围宣称保证 1000 路。 - early media 与接通分开统计;按最终计划从接通开始记录双向音频,不能把 183 媒体到达当成 answered。
- 固化既有问题的等价回归:ExternalMedia 就绪/本地端口、桥成员未齐、RTP 源/SSRC、双向标识音、末帧与录音封口。沿用 MixMonitor 时停止并确认封口后才读文件;替代实现须证明相同行为,不接受空 WAV 或合成音冒充录音。
7.2 AI 流与打断
本次必须支持两种模式,均由批准的不可变 agent_version_id 配置选择,任务不携带供应商密钥或临时模式字段:
| 模式(概念名,非新协议枚举) | 执行与准入 | 验收边界 |
|---|---|---|
| ASR-only | 采集来电音频、识别、实时文字、录音及结果;不建立LLM/TTS会话、不预留其额度、不生成虚假播放事实 | 即使LLM/TTS未配置或不可用也可独立运行;仍受ASR/媒体/控制/录音约束 |
| ASR + LLM + TTS | 完整对话、生成与播放、取消/打断;三类AI配额同时满足 | 使用新批准SDK/模型,真实闭环;依赖不足拒新任务,不静默退成ASR-only |
当前AI Schema强制要求llm/prompt/tts/asr/conversation,没有明确的ASR-only模式/禁用规则。GAP-08须由上游唯一源补齐模式选择、缺省与模式相关的字段/超时/事件语义,包含ASR-only无agent播放片段时的合法表示;禁止伪造LLM/TTS配置或放宽源Schema。本轮用户已确认百炼/火山两种ASR、OpenAI兼容LLM、火山TTS;模型/voice/API协议仍按SaaS配置和能力PoC冻结。每个适配只选必要的一套SDK,不建插件、自动AI切换或多供应商编排。
- ASR 先用真实匹配的现成 SDK:DashScope 的 Paraformer/FunASR 与阿里 NLS 不能混同,火山 SAUC 与经典接口须分别核对。现有 Go ASR 的协议行为/测试是兼容性基线,不因已有手写代码就跳过 SDK 调研。选库、访问控制、生命周期与重连验收归本项目。
- LLM/TTS新规范、供应商、模型、音频、取消/打断、限额及费用核验属于P0/P1必需门禁。使用官方/适用开源SDK薄适配,禁止自写已有客户端或复用旧实现;此前仅Mock/未启用且P1保持blocked,不能将完整模式移到未来。SDK重试不得重复收费生成、播放或拨号。
- 通话 context 管全生命周期,每轮回答使用子 context 和代次;用户打断时取消生成并清理待播音频,过期分片不能继续播放。
- 区分生成、排队、发送和实际播放,不能把 TTS 已产生字节当作用户已听到。
- 媒体/识别/生成队列按音频时长和字节数限额,溢出策略显式验收;不得无限积压或静默丢弃关键控制。
- 持续采集 ASR 首包/最终结果、LLM 首 token、TTS 首音频、端到端响应和打断清空延迟;换 Go 不会消除供应商网络与推理延迟。
7.2.1 AI配置来源与调参边界(本次必需)
- 配置流固定为:MQ任务引用agent_version_id → Dispatcher调用SaaS已有AI版本GET → 校验租户/源Schema/摘要及供应商能力 → R07的执行快照/获批缓存引用 → Agent会话局部SDK请求与控制器。Agent不直接查询SaaS,不从CLI/env另填业务参数,不新增HTTP拨号或结果回调。
- 初选组件为百炼devinyf/dashscopego、火山ASR/TTS共用GizClaw/doubao-speech-go、LLM官方openai-go;均需实际协议与参数PoC,尤其火山TTS不能忽略语速/音量等字段。基础库及未完成的锁版门禁见 组件清单§1.3/§4.3。
- 模型、提示词/变量、语言/中间稿、音色/语速、音频格式、temperature/Token上限、超时、开场白、打断、静音/轮数/时长、分句/缓存等已有参数必须从SaaS贯穿到执行;热词/VAD/top_p/音量/阶段超时等实际所需扩展先由上游补GAP-09。精确字段及缺省/单位/能力规则仅在源契约维护,需求索引见 交互§6.1–§6.3。
- 在已支持并获授权的能力范围内,SaaS发布新不可变版本,新任务显式引用即可调参,无需改代码/重建/重启;在途与原排队任务固定原快照,未知执行不因版本变化重拨。SIP静态发布不限制这条AI配置读取链路,也不需要建设R04通用热更新平台。
- 无有效授权缓存、版本冲突、未支持参数、模式/SDK能力不匹配均在准入前明确失败;不改用SDK默认值或伪造配置。显式0/false/未提供必须区分,并发两Agent不能共享可变参数。凭据/端点来自受控引用,业务参数不能突破安全硬限额或启用不安全SDK重试。
- 本轮确认配置来源/需求,不代表SaaS已有全部参数或SDK已暴露全部控制。GAP-08/09批准前不手改只读字段索引、不添加MQ临时字段/metadata后门;首发参数必须以SDK请求/本地控制器实测证明有效。
7.3 录音交接
OSS配置来源于SaaS,不在Agent启动参数中维护bucket/AK/SaaS地址。Dispatcher统一解析获授权的配置/版本,承接现有上传申请和complete;Agent通过gRPC获取仅本执行/对象所需的HTTPS目标、headers和有效期,直传OSS并回报元信息。verified后由Dispatcher写outbox发布recording.ready,不把PUT200/ETag当验证成功。SaaS全局配置拉取接口未在现有OpenAPI定义,列为GAP-02而非虚构已可调用路径。
spool 按继承的测试 profile 在 70% 告警、80% 停止新接单,降至 60% 且依赖恢复后才恢复;为活动通话预留剩余录音空间。已 verified、ready 持久并确认发布、无已知恢复任务的本地已交接录音,测试至少保留 24h;未确认/失败文件不自动删。生产保留另行批准,不能在 confirm 后无条件删原始资产。
CALL_NOT_REGISTERED 保留文件并等待;签名失效续用原 recording/upload 会话,不制造新资产。仅接受受控 HTTPS 目标与约定 headers,禁止任意重定向/跨对象写入;verified 对象须防止旧签名覆盖。SaaS/对象侧独立读真实字节验证,不能信自报摘要或把 ETag 当 SHA-256。
Agent对已签名PUT使用标准库HTTP/约定headers,需要OSS API才用官方SDK,不自写签名或拿不必要长期凭据。文字也流式落文件,但实时transcript.updated/contact.opt_out仍经gRPC→Dispatcher→MQ及时回SaaS。文本OSS归档的授权/完成/引用尚缺契约,未冻结前明确未启用,不伪装录音;保留文字MQ链路不受此影响。补传按§6.5整体call/command范围。
8. 静态配置发布与授权
P1不实现在线动态发布平台。管理平台仍是唯一编辑/审批面,输出带来源/版本/哈希、目标Cell/trunk和credential_ref的不可变快照;由项目自有受控部署入口交付。GAP-03先批准最小静态交接合同,不另建CRUD后台、不手写第二套Schema、不依赖管理源码运行。Dispatcher记录期望版本/准入,Agent验证并报告Asterisk实际加载;旧直写通道不得并行。
- 维护流程:关闭受影响资源新准入→收敛最后许可与预留→排空/对账拨号、振铃、已接通及未知占用→备份/原子替换批准制品→加载或受控重启→核验实际版本/哈希/线路能力→恢复准入。初装同样必须先验证才ready。
- 固定两个Cell及供应商授权矩阵;同版本同哈希幂等、异哈希/旧版本冲突按合同拒绝。失败保持not-ready/待对账;人工恢复旧制品也须完成加载确认,不靠切active指针假成功。
- 部分节点加载成功时只允许已满足完整准入条件的资源接新执行;存在共享冲突则一并阻塞。不能以“静态配置”为由跳过租户/供应商总额度或旧许可屏障。
- 只接受获批快照和凭据引用,不执行任意脚本/路径,不从MQ覆写SIP地址、主叫或供应商凭据;不逐呼reload,不虚构备用地址。
- 运行态验证Endpoint/boot/授权代次及采样新鲜度;实时结果保留实际attempt、线路/Cell/出口历史事实。管理聚合统计与在线发布回滚属于后续集成,不影响事实留存。
未来需要在线发布时,再冻结完整目标集合/发布意图/CAS/回执及R04/R06,验收新增/移除节点、在线停用和回滚编排。P1不为这些功能建立空框架;安全排空与人工恢复纳入本次交付,当前尚未实现。
9. 运行、监控与安全
9.1 生命周期
SIGTERM 先撤销 ready/停止新预留和新拨号,再有界排空、提交状态并关闭连接。长通话的维护排空与截止行为需配置并验收;到时仍有通话不得默默丢状态或由新实例重拨。
调度器失去租约即停止新决策;Cell 失去授权/心跳时停止接新任务,已有通话按本地策略继续并保留结果。就绪、存活与外部依赖状态分开:数据库不可用不能报告可调度,第三方缺失可以启动诊断/草稿能力,但不能宣称真实可用。
9.2 可观测性
- 使用
slog;允许记录受控的 trace/command/execution 关联信息,但不输出密钥、ARI 密码、完整音频、完整对话或用户号码。 - P1指标覆盖等待/额度不足、inbox/outbox年龄、confirm延迟、未知执行、两个Cell心跳/配置、媒体/AI延迟、spool/OSS积压与恢复告警;公平份额/租户饥饿指标在P2补齐,不先建复杂监控平台。
- 不把任意
tenant_key、execution ID、手机号作为无限基数指标标签;租户详细诊断通过受控查询提供。 - pprof/泄漏诊断只在受控管理网暴露。先 profile,再考虑调 GC、PGO、对象池或零拷贝;不用未经测量的“高性能优化”。
9.3 部署边界
独立构建非 root 镜像和部署入口,初期用 Compose/受控 systemd 即可。是否采用 CGO/SQLite 驱动会影响静态链接和交叉编译,必须按实际构建验证,不能因为用了 Go 就承诺完全静态二进制。
镜像/依赖锁定版本及digest;Dispatcher才持MQ/SaaS/中央库权限,Agent才持本地ARI/必要供应商运行权限。两角色不共享工作目录或全部Secret,共用二进制不等于共用运行权限。mock/mixed/real 可识别:Mock 默认限制真实外网,real 拒绝 Mock 端点、测试凭据和未授权路由,不静默回退。
独立开发与 CI 不依赖云资源、真实电话或其它业务测试栈。外部 Mock 服务按需使用固定镜像与版本化协议,不读取父目录源码。生产仍使用多机器、多 EIP 直连;不引入单 EIP+NAT 方案。沿用阿里云北京、指定 IP、竞价与清理授权约束,方案不产生任何云消费权限。
10. 分阶段目标与交付顺序
本节替代旧P0–P5全量重写计划;P1现在表示本次单节点/单 Cell/单租户本地首发,第二阶段再做真实 SaaS/MQ 联调及多节点/多租户扩展,不是完整生产控制面。旧12–22人周估算不再用于本次排期;不承诺未经SDK/契约核验的缩减百分比或工期。
| 阶段 | 交付范围 | 退出门禁 |
|---|---|---|
| P0 首发契约/PoC | 8种事件、双AI模式与SaaS配置/参数GAP-08/09、首发Unary/最后许可、单 Cell 静态交接、录音授权、共享证书、至少3家trunk的契约/协议 fixture | 契约正反例、模式/参数/权限和本地隔离 PoC 通过;不以宽松Schema、假配置或手写协议绕过 |
| P1a 独立基础与调度骨架 | Cobra/单module、SQLite/文件、MQ inbox/outbox、单租户独立队列/有界窗口、单 Cell 原子配额、Unary身份/健康 | 独立构建、契约/权限/存储/恢复和单租户隔离通过 |
| P1b 单 Cell 执行 | 1 Agent+1 Asterisk、至少3独立trunk配置、静态快照、原始号码选路、最后许可/控制/未知对账 | 协议 Mock/mixed、重复拨号防护、维护时停止新准入通过;真实供应商/ECS 延期 |
| P1c 双AI与资产闭环 | 百炼/火山ASR、OpenAI兼容LLM、火山TTS,双模式/取消/实时文字/录音;D读取契约 fixture 配置并逐执行传参 | 两ASR适配及两模式通过本地/协议 Mock,调参无需重启且参数实际生效;真实供应商联调延期 |
| P1d 本地内测 | 受限隔离负载、故障注入、短期稳定性、维护恢复、告警与运维步骤 | 当前单节点门禁通过;不要求真实 ECS、双节点、第二 Cell、双租户或1000路/N+1 |
| 第二阶段 | 真实 SaaS/MQ、真实供应商/ECS、双节点/第二 Cell、第二租户公平及生产切换 | 另行授权、另行验收,不阻塞本轮本地 P1 |
| 后续按需立项 | 动态发布/回滚、自动SIP FALLBACK、AI多供应商编排、文本OSS归档、多D协调/HA、权重借用、1000路/N+1 | 各自批准契约、资源/预算与专项验收;不阻塞已满足范围的P1/P2 |
P1a–P1d为同一首发的有序工作包,不是各自可替代完整首发的产品。可并行协调供应商/契约,但真实双模式未通过就不能宣布P1完成。P1只要求登记负载内的稳定性和性能,无须先完成Python/Go性能对照项目;规模化收益对比留待后续相同环境专项测试。
11. 迁移与切换原则
- 先做离线黄金样本和非执行影子调度;影子输入来自显式复制/回放,不能竞争消费旧生产队列、预留生产额度或真正拨号。
- P1不以旧Python Cell作首发运行依赖;若迁移验证确需临时对接,必须有批准协议并完整支持新许可/控制/幂等,否则停留在Mock,不写HTTP拨号代理凑过渡。
- 优先使用空闲/专用 Cell 做小范围验证。只有能证明全局共享额度和控制屏障协调正确时,才允许 Python/Go 在互斥资源分区中同时运行;否则采用维护窗口完整排空后切换。
- 切换单元包含租户调度归属、Cell/路由、共享配额及未决任务,不是改一个进程地址。任何相同资源不得由两套 Agent 同时写入/发放许可。
- 排空旧端、处理 broker 未 ACK、保存控制版本/幂等 ID/待执行/未知执行/outbox/录音进度,再切换所有权。数据库迁移显式、可审计,不长期双写同一业务库。
- Go 接手新执行后,不能让 Python 忘记这些执行直接恢复消费。回滚先停止新准入、排空并对账;状态无法兼容回迁就暂停并前向修复,不能靠退镜像冒险重拨。
详细演练、量化profile及新增架构门禁见 验证与切换验收。
12. G0 待冻结清单
| 项目 | 本方案建议 | 未确认时的边界 |
|---|---|---|
| 持久化/恢复细则 | 已确定Dispatcher SQLite、Agent文件;冻结驱动/Sync/checkpoint/备份、保留和RPO/RTO | 不引PG/Agent DB/NFS共享,不拿普通文件复制冒充一致性备份 |
| 调度可用性 | 首版唯一活动Dispatcher,登记维护/故障恢复窗口与fencing | 不宣称跨机自动热备、active-active或零切换延迟 |
| 内部Unary合同 | P1冻结R01–R03、R05、R07–R13必需职责;方法可经批准合并,R04/R06在线改配后续冻结 | 最后许可/查询/事实/上传不裁掉,不手写另一套Schema或新增SaaS入口 |
| 启动/安全/版本 | 共享Agent证书、独立D身份;细化自动节点会话/轮换/重放、监听与兼容矩阵 | 不把共享证书当节点身份,不无凭据下发SIP/OSS配置 |
| 上游缺口 | P1关闭GAP-01、GAP-02录音、GAP-03静态交接、GAP-08双模式、GAP-09 SaaS任务AI配置/有效参数;文本归档/在线发布后续 | 按唯一源修复;明确阻塞阶段,不要求未来接口先落地 |
| 健康准入 | 单 Cell 样本口径/新鲜度、基本资源保护、固定候选选择、供应商和已加载版本 | 不建复杂评分,不用低CPU越额度或新boot清旧未知通话 |
| 运行参数 | 登记P1单租户单 Cell 受限profile及供应商授权 fixture;继承安全/恢复阈值,第二阶段再验公平与SCALE | 拓扑覆盖需版本化批准,不把测试基线当生产SLA或消费授权 |
| 开源依赖 | 锁定实际可用 module/tag/commit、许可证、漏洞处置及兼容 PoC | 无现成库匹配时先报告阻塞,不私自手写协议替代 |
| AI/音频能力 | 已选百炼/火山ASR、OpenAI兼容LLM、火山TTS;D从SaaS读取任务版本,冻结参数/默认/能力/实际SDK映射 | 未核验仍未启用/阻塞P1;无参数的SDK不能靠硬编码或静默忽略凑过 |
| 发布和停用 | P1静态制品版本/哈希/目标、维护排空和加载确认,批准唯一写入路径 | 无在线编排不等于无控制屏障,未知阻塞、不假报applied |
| 成本与保留 | OSS/录音/日志/审计/RPO/RTO、供应商额度 | 不承诺无限保留和自动灾难接管 |
| 真实验收 | 供应商能力、白名单、出口、时间窗口、费用授权 | 不自动拨号、开云主机或扩大网络放行 |
13. 参考与证据边界
- 已核验本地工具链:
go1.27.1 linux/amd64;本地 API:go doc uuid、go doc encoding/json/v2、go doc testing/synctest.Sleep、go doc net/http/httptest.NewTestServer、go doc sync.WaitGroup.Go、go doc runtime/pprof。 - Go 1.27 官方发布说明。Go 特性的可用性不等于已验证其在本项目中的收益。
- 上游实施依据:《最终开发部署监控与验收计划_v1.0.md》《SaaS对接与任务调度专项验收计划_v1.0.md》《SaaS交互_OpenAPI与MQ契约规划_v0.1.md》及对应机器可读契约。这里只记录来源名称,独立项目运行不回读这些父目录文件。
- 本文没有新的压测数据、生产容量证明或供应商验收结论;本轮文档检查不能替代实现验收。