项目:lite_agent
标签:系统架构 / 多 Agent 协同 / API 安全 / 纵深防御 / 长轮询机制


摘要

在自主智能体(Autonomous Agents)深入参与代码审查、系统架构评估与关键业务决策的今天,传统的“提单-离线异步审核”模式已无法满足高响应、强对抗与高安全要求。本文深度复盘我们近期对会审会议系统(Review Meeting System)的一系列核心迭代:从构建基于长轮询与心跳感知的实时直播协同机制(P0/P1/P2),到现场排查并化解一次因 Host 421 门禁诱发的“反代全局 Admin 提权”真实攻防,最终建立起一套基于受限会话、跨域直连、读写生命周期解耦与协议化驻留的多 Agent 人机协同治理体系。


一、背景与挑战:为什么需要“会审会议”?

随着系统中多角色 AI Agent(如架构师 Agent、安全审计 Agent、代码生成 Agent)的引入,过去的单向审查流程暴露出诸多痛点:

  1. 割裂与离散:各个 Agent 各自输出 Review 结果,缺乏交叉质疑、反驳与共识收敛机制;
  2. 状态不透明:人类主持人(Human-in-the-loop)无法实时围观多个 Agent 的动态推演,难以在关键节点介入插话;
  3. “交卷即离线”痛点:Agent 往往提交完第一轮意见后立即退出进程,当线上议题出现变更或主持人提出追加质询时,无人响应。

为此,我们设计了Review Meeting 会审系统:以单议题为中心,支持人类主持人与多个 AI 席位同台辩论、多轮流转、交叉响应,并最终由人类持私钥执行终审裁决。


二、基础协同架构演进(P0 / P1 / P2)

为保证会审的实时性、确定性与低资源开销,系统在底层协议与前端呈现上实施了四项核心设计:

1. 轻量级长轮询(Long Polling)与在线心跳追踪

系统摒弃了高复杂度的 WebSocket 依赖,采用标准 HTTP/2 长轮询协议(GET /review-meetings/<id>?since=N&wait=25):

  • 挂起与即时唤醒:客户端传入本地已读的最大序列号 since,服务端无新事件时挂起(支持 1~25s 任意超时),一旦有评论(comment)、正式评审(review)或系统事件发生,毫秒级推送返回;
  • 单挂起连接防堆积:每个参会席位限制单一挂起连接,避免并发连接耗尽后端资源;
  • 在线状态感知:服务端自动根据轮询心跳刷新席位 last_poll_at,动态判定 online: true/false,使主持人能够直观洞悉席位活跃度。

2. 状态机驱动的动态指引(Dynamic Hint)

会审流程包含 open(讨论与提交)、awaiting_approval(等待审批)、approved/rejected(裁决终态)等状态。系统在每次接口响应中内置自解释的 hint 字段:

  • 例如:"本轮已提交正式意见,等待:codex;可用 comments 自由交流";
  • 指引将复杂的跨 Agent 协调逻辑收敛在服务端状态机内部,AI 席位无需猜测上下文,严格“依 Hint 行动”。

3. 治理闭环:席位豁免(Waive)与流转(Advance)

  • 异常席位豁免(Waive):当某一 Agent 席位因网络或重启掉线时,可能导致本轮意见缺失(missing: ["codex"])进而阻断流程。系统引入 waive 机制,主持人可附带原因豁免该席位,将其移出缺失列表并记入审计链;
  • 自动推进(Advance):全员意见齐备后,系统或主持人调用 advance 冻结本轮,自动推进至 Round + 1,强制要求下一轮意见必须通过 responds_to_seq 引用回应上轮发言,促成真正的共识对抗。

4. Web Dashboard 实时直播

为人类团队提供全局可视化看板:

  • 原生模块化设计,实时渲染讨论时间轴、参会者状态灯、投票立场(Support / Revise / Oppose / Abstain);
  • 支持人类主持人在页面底部直接发表评论插话,实现实时人机同频。

三、实战攻防:一次 421 拦截背后的架构重构

在 Dashboard 上线后,我们遭遇了一起典型的生产鉴权穿透与架构配置事故。这场事故的排查与解决,成为整个系统安全架构演进的分水岭。

1. 现象初现:Host 白名单拦截 421

人类主持人通过管理面板 mail.maifeipin.com 打开会议直播页面时,浏览器控制台报错:

HTTP/2 421 Misdirected Request

根因:后端会议服务部署在专用网关(如 edge.maifeipin.com),内部启用了严密的 Host 白名单防护(_review_host_allowed)。当请求经过静态站 mail.maifeipin.com 的反向代理发来时,因 Host 标头未在白名单中而被底层中间件直接拦截阻断。

2. 方案陷阱:单纯放开白名单遭遇“全局提权”

面对 421 拦截,主持人最先测试了方案 A(commit 12bdaf2):在后端配置中新增 review_meeting_allowed_hosts: ["mail.maifeipin.com"]。

421 瞬间消失,界面恢复,但评委 Agent 立即在公网发起了负向安全实测,抓到了致命铁证:

# 从外部发起无任何 Authorization、无任何 Cookie 的匿名请求
curl -i https://mail.maifeipin.com/agent/api/v1/review-meetings
# 响应:HTTP/2 200 OK!直接返回所有会议敏感情报与列表!

作为对比,直接访问 edge 网关严格返回 403 Forbidden。

深度溯源:原来 mail.maifeipin.com 的 Nginx 通用反向代理历史配置中,硬编码了以下规则:

proxy_set_header Authorization "Bearer <global_admin_token>";

这导致任何公网访客只要请求 mail 域名,流量进入后端前都会被 Nginx 强行注入超级管理员 Token!在 421 拦截存在时,这道错误门禁歪打正着阻断了公网流量;一旦放开白名单,直接把内部核心管理接口裸奔暴露给了全网!

3. 方案权衡与攻防决策

在随后的多轮会审激辩中,评委团队逐一否决了低可靠性方案:

  • 否决方案 B(弃防 Host):完全弃守 Host 校验,违背深度防御;
  • 否决纯前端伪登录:源码排查发现 login.html 历史仅依靠 sessionStorage dashboard_auth=ok 充当鉴权,毫无后端验真依据,绝不能将最高权限 Token 下发给前端暂存。

4. 终极架构落地:方案 C+ 修订版(受限会话 + 跨域隔离)

主持人与双评委最终确立并实施了方案 C+ 修订版:

                [ 浏览器 Dashboard (mail 域) ]
                 /                         \
    1. 真实账号密码登录                      2. 跨域直连 API (携带受限 Token)
               /                             \
              v                               v
    [ mail Nginx 静态托管 ]           [ edge 网关 / 后端服务 ]
    - 仅托管静态 HTML/JS             - 验证 Host 仅放行 edge
    - 撤销会议 Host 白名单           - Access-Control-Allow-Origin: *
    - 外部请求会议接口 -> 421 物理阻断  - 识别独立 review_host_sessions
                                     - 全局 _auth 拒绝该 Token

实施落点核心要件:

  1. 独立短期会议管理会话(Scoped Host Session):
    • 建立专属 SQLite 表 review_host_sessions:token_hash, username, role='host', expires_at, revoked_at;
    • 用户经 _handle_auth 校验 htpasswd 成功后,仅签发 TTL=3600、仅能管理会议的随机 Token,严禁泄露全局 auth_token;
    • 提供安全 POST /logout 撤销接口,登录接口接入 TCP 连接级限流(10次/60秒);
  2. 前端数据流切至 Edge 跨域:
    • Dashboard 静态页面保留在 mail 域托管,用户心智零迁移;
    • 封装 meeting_api.js,将会议数据请求统一重定向发往 https://edge.maifeipin.com,设置 credentials: 'omit' 完美契合 CORS 规范;
    • 遇到 401/403 自动清空会话并熔断跳转登录,杜绝死循环;
  3. 物理切断 Mail 域注入:
    • VPS 后端配置彻底剔除 mail.maifeipin.com,使任何试图走 mail 域反代的未认证请求直接被 Host 校验斩断为 421 Misdirected Request。

四、生命周期解耦与驻留协议规范

除了网络边界的加固,本次演进还解决了两个深层次的工程设计缺陷:

1. 只读操作与状态流转解耦

缺陷:历史代码中,参会者鉴权函数 authenticate 内部绑定了 _open 状态断言:

# 历史缺陷代码
if not meeting["state"] == "open":
    raise ReviewAPIError("会议非开放状态")

这导致一旦会议进入 awaiting_approval 或最终裁决归档,参会者调用 GET /show 或长轮询唤醒时全部收到 403,直接导致参会 Agent 无法接收最终裁决通知。
重构:将只读状态鉴权与**写操作门禁(Submit / Comment)**彻底解耦——冻结/终态下,读操作全生命周期可达,写入严格拦截。

2. AI 参会驻留协议(Resident Polling Protocol)

针对 AI 模型“交完卷就退出”的天性,系统在 POST /join 响应中显式内嵌了协议条款:

{
  "participant": "antigravity",
  "session_token": "...",
  "protocol": "保持长轮询(since=N&wait=20),按 hint 行动并立即轮询下一次,直到 state 变为 approved/rejected 方可退出"
}

通过规范化协议输入,确保所有参会 Agent 在全会议周期内持续在线、维持心跳、实时响应突发事件与交叉质询。


五、生产全项验收基线矩阵(Baseline a ~ f)

在代码合入及 VPS 发布上线后,我们构建了针对生产环境的六大验收基线并全部验证通过:

验收项 测试动作 预期响应 生产实测状态 安全与业务含义
Baseline a 无凭据 GET mail/review-meetings 421 PASS 物理封死 Nginx 旧反代 admin 注入越权通道
Baseline b 无凭据 GET edge/review-meetings 403 PASS 验证公共入口默认鉴权门禁有效
Baseline c 席位 Token GET edge/review-meetings 403 PASS 席位只能读自身会议,无法越权刺探全局列表
Baseline d 签发受限 Host 会话测试管理操作 200 PASS 会议列表/推进全通,调全局 API 报 403,安全解耦
Baseline e 静态文件部署与跨域直播体验 200 PASS /meeting_api.js 正常交付,前端无缝连接 Edge
Baseline f 登录连续失败试探 429 PASS 登录防暴力破解速率限制生效

六、总结与工程启示

本次迭代从一个微小的“421 跨域拦截”表象出发,最终牵出并根治了反向代理配置、会话作用域、状态生命周期与多 Agent 协议化协同的一整套架构隐患。

核心工程启示:

  1. 警惕“便捷反代”带来的提权炸弹:严禁在网关层无条件为上游注入全局超级凭据,任何通过修改白名单“快速恢复业务”的操作,必须首先评估下游反代的凭据注入逻辑;
  2. 最小权限原则(PoLP)永不过时:区分超级密钥(Global Secret)与业务会话(Scoped Session),前端浏览器只应持有短期、受限、可撤销的最小功能会话;
  3. 多 Agent 治理必须协议化与心跳化:要让多个 AI Agent 在同一业务场景下协同,长轮询心跳、动态状态指引与强制驻留协议是构建高确定性系统的基石。

目前,这套 Review Meeting 系统已在多项基础设施重构中担任关键“看门人”,为人机共存时代的软件工程治理提供了坚实的底座支持。

image