跳转至

安全事故报告:灵通+管道黑洞事件

日期: 2026-04-09 (估)
严重程度: P0 — 全家族项目LLM调用瘫痪
报告人: 灵依 (LingYi)
状态: 事故已记录,根因分析待灵通恢复后深入


事故概述

灵通+ (LingFlow+) 将灵字辈家族所有项目的LLM请求接入其统一管道(请求队列+并发池+Token轮转),解决频繁429错误。管道成功将请求发送到大模型,但未将模型响应正确回传给各项目,导致所有项目的LLM调用变成黑洞——请求出去,响应消失,全部项目无法工作。


影响范围

项目 影响 当前状态
灵依 (LingYi) LLM调用中断 已通过系统重置恢复套餐配置
灵通 (LingFlow) LLM调用中断 已通过系统重置恢复套餐配置
灵克 (LingClaude) LLM调用中断 未恢复
灵知 (LingZhi) LLM调用中断 未恢复
灵妍 (LingResearch) LLM调用中断 未恢复
灵通问道 LLM调用中断 未恢复

影响持续时间: 待确认(用户手动恢复灵依和灵通,其余项目仍未恢复)


技术现场

管道架构

灵通+的管道由以下模块组成:

各项目请求 → LingFlowPlus.coordinator → MultiProjectScheduler
    → GLMAgent / DirectMCPAgent → GLMClient → TokenPool → OpenAI API
    → LLMResponse → ??? → 各项目(断点)

关键文件 (位于 /home/ai/LingFlow_plus/lingflow_plus/):

文件 行数 职责
llm_client.py 778 Token池轮转 + GLM API调用 + 模型降级链
coordinator.py 149 组合所有子系统(配额/限流/调度/路由)
scheduler.py 290 多项目并行调度,按project分组,asyncio.gather并行
glm_agent.py 197 GLM直连Agent,将任务转为prompt发GLM,返回TaskResult
mcp_direct_adapter.py 216 MCP工具直连适配器,绕过stdio直接调用工具函数
web.py 758 FastAPI Web服务(端口8765),项目注册/管理/看板

管道运行时状态

  • 进程: python3 -m lingflow_plus.cli web --port 8765 (PID 1126509)
  • 工作目录: /home/ai/LingFlow_plus
  • 环境变量: ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN, API_TIMEOUT_MS 已配置

Token池机制

llm_client.py 中的 TokenPool 管理多个API Key的轮转: - Key优先级: GLM_CODING_PLAN_KEYGLM_47_CC_KEYGLM_API_KEYDEEPSEEK_API_KEY - Key存储: ~/.ling_lib/ling_key_store.py - 配额窗口: 5小时周期,400次调用上限 - 模型降级链: glm-5.1 → glm-5-turbo → ... → deepseek-chat - 并发控制: threading.Semaphore(max_concurrent=3) - 请求分级: PREMIUM/STANDARD/ECONOMY,根据消息内容自动选层

注册的Agent数量

glm_agent.py 注册了 约100个GLM直连Agent,覆盖灵依/灵通/灵克/灵通问道/灵知/灵妍的所有常见操作。mcp_direct_adapter.py 另注册了MCP工具Agent。


根因分析(初步)

直接原因

管道的响应回传路径存在缺陷。从代码分析:

  1. GLMAgent路径: glm_agent.pyexecute_task() 调用 ask() 获取响应,返回 TaskResult。这条路径本身看起来正确——LLMResponse 包含 content 字段。

  2. MCP路径: mcp_direct_adapter.pyexecute_task() 直接调用工具函数,也返回 TaskResult

  3. 调度器路径: scheduler.py_execute_project() 调用 orchestrator.execute_workflow(),结果存入 self._results

  4. 可能的断点:

  5. scheduler.py_post_dispatch() 中有 if result.success and output_len == 0 的警告日志——已知输出为空的情况存在
  6. coordinator.pyrun_tasks() 返回结果但各项目如何接收这个返回值?
  7. 各项目通过什么机制发现自己的请求被路由到了灵通+?是通过环境变量、配置文件、还是API注册?

待确认问题

  1. 各项目是如何被"接入"管道的?(修改了各自的base_url?通过API注册?环境变量?)
  2. 管道故障后,灵依和灵通通过"系统重置"恢复——具体恢复了什么文件?
  3. 其他项目"仍不能进行"的具体表现——是连接超时?404?还是发不出去?
  4. 管道是否仍在运行(PID 1126509)?是否在持续拦截请求?

反事实推论分析

期待推演(Forward)

如果管道正确实现 → 429问题解决 → 所有项目受益

反向推演(Counterfactual)— 应该做但没有做的推演

如果管道失败 → 所有项目同时瘫痪 → 单点故障引发全家族停摆

两个教训方向

方向一:实现层 — 响应回传缺陷

管道的请求→模型→响应 闭环没有端到端验证就投入了全家族生产。_post_dispatch() 中已有 output_len == 0 的警告,说明代码层面已经知道存在空响应的问题,但没有在上线前解决。

反事实:如果先在测试环境用单个项目验证完整的 请求→发送→接收→回传 闭环,这个bug在测试阶段就能被发现。

方向二:部署层 — 缺乏灰度发布(核心教训

将全部项目的直连接入管道之前,没有推演"如果失败会出现什么结果"。

反事实: - 如果只先接入灵依一个项目试运行 → 即使管道有bug → 只有灵依受影响 → 其他项目正常直连 - 如果设有fallback机制(管道超时3秒自动回退直连)→ 即使管道崩溃 → 各项目自动恢复直连 → 零停摆

反事实推论的方法论总结

核心原则:在执行关键架构变更前,必须做反向推演——

"如果这个变更失败了,最坏的结果是什么?"

如果答案是"全部服务停摆",那么必须有: 1. 灰度发布 — 先1个项目,验证通过再扩展 2. 回退机制 — 管道故障时自动/手动回退到直连 3. 爆炸半径控制 — 一个变更不能同时影响所有服务


行动项

紧急(恢复服务)

# 行动 状态
1 诊断各项目LLM调用当前失败原因 待执行
2 恢复各项目的直连配置 待执行
3 确认灵通+管道(PID 1126509)是否仍在拦截 待执行

短期(根因与修复)

# 行动 负责人
4 找到响应回传的具体断点(需要灵通+代码深入调试) 灵通
5 编写端到端测试:请求→管道→模型→响应→回传→项目收到 灵通
6 实现fallback机制:管道超时/失败自动回退直连 灵通

长期(制度改进)

# 行动 说明
7 将"反事实推论"写入开发原则 关键变更前必须推演失败场景
8 建立灰度发布规范 基础设施变更必须分阶段上线
9 管道架构增加熔断器 管道故障时自动断开,各项目回退直连

相关文档

  • docs/DEVELOPMENT_PRINCIPLES.md — 现有10条开发原则
  • docs/SECURITY_INCIDENT_REPORT_20260408.md — 4/8 CI违规事件
  • 灵通+代码: /home/ai/LingFlow_plus/lingflow_plus/
  • 管道核心: llm_client.py (GLMClient/TokenPool), coordinator.py (LingFlowPlus), scheduler.py (MultiProjectScheduler)