Gliding Horse 根因分析引擎:从"头痛医头"到"三维会诊"
摘要:本文深入解析 Gliding Horse 根因分析引擎的设计哲学与架构演进,展示如何通过 GraphBackend 抽象层统一图遍历、快照与特征提取能力,构建跨越执行面、结构面与语义面的三维融合诊断系统。文章涵盖从模块重构到系统集成的完整实践,适合关注 AI 可观测性、多 Agent 系统稳定性与智能运维的开发者阅读。
关键词:根因分析、GraphBackend、三维诊断、多 Agent 系统、知识图谱、贝叶斯网络、故障定位、可观测性、AI 运维、系统稳定性
在多 Agent 协作的复杂系统中,定位一个故障的根因有多难?
Agent 报了一个"文件写入失败"。是权限问题?是依赖的数据库连接超时?还是上游任务变更了目录结构?传统做法要么靠人类翻日志,要么让 LLM 做一次性事后分析,效果堪忧。Gliding Horse 给出的答案是:把根因分析变成一个持续运行的三维诊断引擎,让系统自己回答"为什么会出错"以及"还会有什么会出错"。
本文将拆解这套根因分析体系的设计哲学、架构演进和最终成果。它不再是单一的规则匹配或贝叶斯模型,而是一个跨越执行面、结构面和语义面 的融合诊断系统,依托我们全新引入的 GraphBackend 抽象层,统一了图遍历、快照和特征提取能力,使得根因分析可以同时审视代码调用链、技能依赖图和实体关系网。
一、从"三座孤岛"到"一片大陆"
在优化之前,Gliding Horse 的根因分析能力其实已经相当丰富,但它们各自为政:
- 执行层 RootCauseEngine:通过 HookManager 捕获错误,执行 5-why 模式匹配,生成证据链和防御建议。
- 结构层 CausalEngine:基于贝叶斯网络,利用 petgraph 构建的技能依赖图计算错误传播概率。
- 语义层 KnowledgeGraphStore:存储所有实体的 RDF 关系,支持 SPARQL 查询和 BFS 邻居遍历。
问题是:CausalEngine 紧紧绑定着 SkillGraphStore,只看得见技能图谱里的依赖边;语义层有丰富的代码调用、实体归属等关系,却从未被根因分析使用。三套系统共享同一个 @id 命名空间,却无法联合"会诊"。
我们需要一个桥梁。于是,GraphBackend 抽象层诞生了。
二、GraphBackend 抽象层:让根因分析"有统一的图"
#mermaid-svg-2TCo6r7lyYcAzFsl{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-2TCo6r7lyYcAzFsl .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2TCo6r7lyYcAzFsl .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2TCo6r7lyYcAzFsl .error-icon{fill:#552222;}#mermaid-svg-2TCo6r7lyYcAzFsl .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2TCo6r7lyYcAzFsl .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2TCo6r7lyYcAzFsl .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2TCo6r7lyYcAzFsl .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2TCo6r7lyYcAzFsl .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2TCo6r7lyYcAzFsl .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2TCo6r7lyYcAzFsl .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2TCo6r7lyYcAzFsl .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2TCo6r7lyYcAzFsl .marker.cross{stroke:#333333;}#mermaid-svg-2TCo6r7lyYcAzFsl svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2TCo6r7lyYcAzFsl p{margin:0;}#mermaid-svg-2TCo6r7lyYcAzFsl g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-2TCo6r7lyYcAzFsl g.classGroup text .title{font-weight:bolder;}#mermaid-svg-2TCo6r7lyYcAzFsl .cluster-label text{fill:#333;}#mermaid-svg-2TCo6r7lyYcAzFsl .cluster-label span{color:#333;}#mermaid-svg-2TCo6r7lyYcAzFsl .cluster-label span p{background-color:transparent;}#mermaid-svg-2TCo6r7lyYcAzFsl .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2TCo6r7lyYcAzFsl .cluster text{fill:#333;}#mermaid-svg-2TCo6r7lyYcAzFsl .cluster span{color:#333;}#mermaid-svg-2TCo6r7lyYcAzFsl .nodeLabel,#mermaid-svg-2TCo6r7lyYcAzFsl .edgeLabel{color:#131300;}#mermaid-svg-2TCo6r7lyYcAzFsl .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-2TCo6r7lyYcAzFsl .label text{fill:#131300;}#mermaid-svg-2TCo6r7lyYcAzFsl .labelBkg{background:#ECECFF;}#mermaid-svg-2TCo6r7lyYcAzFsl .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-2TCo6r7lyYcAzFsl .classTitle{font-weight:bolder;}#mermaid-svg-2TCo6r7lyYcAzFsl .node rect,#mermaid-svg-2TCo6r7lyYcAzFsl .node circle,#mermaid-svg-2TCo6r7lyYcAzFsl .node ellipse,#mermaid-svg-2TCo6r7lyYcAzFsl .node polygon,#mermaid-svg-2TCo6r7lyYcAzFsl .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2TCo6r7lyYcAzFsl .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-2TCo6r7lyYcAzFsl g.clickable{cursor:pointer;}#mermaid-svg-2TCo6r7lyYcAzFsl g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-2TCo6r7lyYcAzFsl g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-2TCo6r7lyYcAzFsl .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-2TCo6r7lyYcAzFsl .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-2TCo6r7lyYcAzFsl .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-2TCo6r7lyYcAzFsl .dashed-line{stroke-dasharray:3;}#mermaid-svg-2TCo6r7lyYcAzFsl .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-2TCo6r7lyYcAzFsl #compositionStart,#mermaid-svg-2TCo6r7lyYcAzFsl .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2TCo6r7lyYcAzFsl #compositionEnd,#mermaid-svg-2TCo6r7lyYcAzFsl .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2TCo6r7lyYcAzFsl #dependencyStart,#mermaid-svg-2TCo6r7lyYcAzFsl .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2TCo6r7lyYcAzFsl #dependencyStart,#mermaid-svg-2TCo6r7lyYcAzFsl .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2TCo6r7lyYcAzFsl #extensionStart,#mermaid-svg-2TCo6r7lyYcAzFsl .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2TCo6r7lyYcAzFsl #extensionEnd,#mermaid-svg-2TCo6r7lyYcAzFsl .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2TCo6r7lyYcAzFsl #aggregationStart,#mermaid-svg-2TCo6r7lyYcAzFsl .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2TCo6r7lyYcAzFsl #aggregationEnd,#mermaid-svg-2TCo6r7lyYcAzFsl .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2TCo6r7lyYcAzFsl #lollipopStart,#mermaid-svg-2TCo6r7lyYcAzFsl .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2TCo6r7lyYcAzFsl #lollipopEnd,#mermaid-svg-2TCo6r7lyYcAzFsl .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-2TCo6r7lyYcAzFsl .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-2TCo6r7lyYcAzFsl .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2TCo6r7lyYcAzFsl .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2TCo6r7lyYcAzFsl .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2TCo6r7lyYcAzFsl :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} <<interface>>
GraphBackend
+list_all_nodes() : Vec<String>
+get_outgoing_edges(iri) : Vec<out>
+get_incoming_edges(iri) : Vec<in>
+bfs(seeds, depth, filter) : Vec<String>
+node_count() : usize
<<interface>>
SnapshotBackend
+snapshot() : Vec<Node>
+apply_snapshot(nodes) : Result
<<interface>>
FeatureGraph
+neighbors(iri, dir) : Vec<String>
+degree(iri, dir) : usize
+all_nodes() : Vec<String>
PetgraphBackend
-graph: DiGraph
SparqlBackend
-store: KnowledgeGraphStore
PetgraphFeatureGraph
SparqlFeatureGraph
- PetgraphBackend :包装了
SkillGraphStore的内部 petgraph,为 CausalEngine 提供轻量内存图遍历。 - SparqlBackend :包装了
KnowledgeGraphStore,通过 SPARQL 查询将 Oxigraph 中任意命名图的边关系暴露为统一的图遍历接口。这意味着,代码 AST(graph:code)、工具调用结果(graph:tool-result)、甚至 PDCA 执行记录(system:plan/exec/review/decision)都能被同一个bfs方法探索。
同时,SnapshotBackend 让版本快照不再只针对技能图谱,可以对任意命名图创建快照和 diff;FeatureGraph 让 GNN 特征提取器能够从不同数据源抽取结构特征。这三个 trait 将高级特性从"技能图谱"的孤岛中彻底解耦,变为系统级的通用能力。
三、三维修正根因分析引擎
有了统一的图接口,我们的 FusedRootCause 引擎就可以同时从三个维度审视一个故障:
#mermaid-svg-lX2EP688a41Jff27{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-lX2EP688a41Jff27 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-lX2EP688a41Jff27 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-lX2EP688a41Jff27 .error-icon{fill:#552222;}#mermaid-svg-lX2EP688a41Jff27 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-lX2EP688a41Jff27 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-lX2EP688a41Jff27 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-lX2EP688a41Jff27 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-lX2EP688a41Jff27 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-lX2EP688a41Jff27 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-lX2EP688a41Jff27 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-lX2EP688a41Jff27 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-lX2EP688a41Jff27 .marker.cross{stroke:#333333;}#mermaid-svg-lX2EP688a41Jff27 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-lX2EP688a41Jff27 p{margin:0;}#mermaid-svg-lX2EP688a41Jff27 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-lX2EP688a41Jff27 .cluster-label text{fill:#333;}#mermaid-svg-lX2EP688a41Jff27 .cluster-label span{color:#333;}#mermaid-svg-lX2EP688a41Jff27 .cluster-label span p{background-color:transparent;}#mermaid-svg-lX2EP688a41Jff27 .label text,#mermaid-svg-lX2EP688a41Jff27 span{fill:#333;color:#333;}#mermaid-svg-lX2EP688a41Jff27 .node rect,#mermaid-svg-lX2EP688a41Jff27 .node circle,#mermaid-svg-lX2EP688a41Jff27 .node ellipse,#mermaid-svg-lX2EP688a41Jff27 .node polygon,#mermaid-svg-lX2EP688a41Jff27 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lX2EP688a41Jff27 .rough-node .label text,#mermaid-svg-lX2EP688a41Jff27 .node .label text,#mermaid-svg-lX2EP688a41Jff27 .image-shape .label,#mermaid-svg-lX2EP688a41Jff27 .icon-shape .label{text-anchor:middle;}#mermaid-svg-lX2EP688a41Jff27 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-lX2EP688a41Jff27 .rough-node .label,#mermaid-svg-lX2EP688a41Jff27 .node .label,#mermaid-svg-lX2EP688a41Jff27 .image-shape .label,#mermaid-svg-lX2EP688a41Jff27 .icon-shape .label{text-align:center;}#mermaid-svg-lX2EP688a41Jff27 .node.clickable{cursor:pointer;}#mermaid-svg-lX2EP688a41Jff27 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-lX2EP688a41Jff27 .arrowheadPath{fill:#333333;}#mermaid-svg-lX2EP688a41Jff27 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-lX2EP688a41Jff27 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-lX2EP688a41Jff27 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lX2EP688a41Jff27 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-lX2EP688a41Jff27 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lX2EP688a41Jff27 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-lX2EP688a41Jff27 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-lX2EP688a41Jff27 .cluster text{fill:#333;}#mermaid-svg-lX2EP688a41Jff27 .cluster span{color:#333;}#mermaid-svg-lX2EP688a41Jff27 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-lX2EP688a41Jff27 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-lX2EP688a41Jff27 rect.text{fill:none;stroke-width:0;}#mermaid-svg-lX2EP688a41Jff27 .icon-shape,#mermaid-svg-lX2EP688a41Jff27 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lX2EP688a41Jff27 .icon-shape p,#mermaid-svg-lX2EP688a41Jff27 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-lX2EP688a41Jff27 .icon-shape .label rect,#mermaid-svg-lX2EP688a41Jff27 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lX2EP688a41Jff27 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-lX2EP688a41Jff27 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-lX2EP688a41Jff27 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} FusedRootCause 引擎
"谁调了谁?"
"谁依赖谁?"
"谁相关于谁?"
执行面
RootCauseEngine 5-why 追溯
结构面
CausalEngine 依赖传播推断
语义面
SparqlBackend RDF 语义遍历
三维加权融合诊断
TraceChain
CausalInferences
RdfContext
加权融合
FusedRootCauseResult
- 执行面 :当 HookManager 捕获到
TaskError,RootCauseEngine立即执行传统的 5-why 回溯,沿着调用链向上追踪,生成TraceChain和证据链,置信度基于证据完整性计算。 - 结构面 :
CausalEngine以故障实体为种子,在GraphBackend(可以是技能图或 RDF 全图)上运行 BFS,利用贝叶斯后验概率计算每个关联节点的因果贡献,输出CausalInference列表。 - 语义面 :
SparqlBackend对故障 IRI 进行深度为 3 的语义邻居探索,获取它在知识图谱中的所有上下文------属于哪个任务、操作了哪些实体、受哪些规则约束等,生成RdfSemanticContext。
最终,三个维度的结果通过加权融合(执行面 0.4,结构面 0.35,语义面 0.25)生成最终根因报告 FusedRootCauseResult,包含主要故障 IRI、总体置信度、各维度的贡献因子以及针对性行动建议。这种"三维会诊"远比任何单一维度的分析更可靠。
四、模块改造:从硬绑定到依赖注入
为了让这套融合引擎落地,我们对相关模块进行了低侵入性的重构:
- CausalEngine :构造函数从接受
Arc<SkillGraphStore>改为接受Arc<dyn GraphBackend>。在技能故障场景,注入PetgraphBackend;在跨领域分析时,注入SparqlBackend,无需改动引擎内部逻辑。 - TimelineStore :原本绑死技能快照,现在
create_snapshot改为接收&dyn SnapshotBackend参数,可以对任意图存储生成时间线快照,用于跨版本对比。 - FeatureExtractor :同样改为依赖
Arc<dyn FeatureGraph>,使得提取节点度、中心性等图特征时,可以从不同存储后端读取。
旧版 skill_graph/types.rs 中的 CausalEvent 和 CausalChain 被标记为弃用,统一迁移到 causal/types.rs,消除类型冗余。整个重构保持向后兼容,原有测试全部通过。
下面是一个具体的 Rust 代码示例,展示 CausalEngine 如何通过依赖注入 GraphBackend 来灵活切换后端:
rust
use std::sync::Arc;
// 1. 定义 GraphBackend trait(抽象层)
pub trait GraphBackend: Send + Sync {
fn bfs(&self, seeds: &[String], depth: usize) -> Vec<String>;
fn get_outgoing_edges(&self, iri: &str) -> Vec<String>;
// ... 其他图操作方法
}
// 2. 两个具体实现
pub struct PetgraphBackend {
// 包装 SkillGraphStore 内部的 petgraph
graph: petgraph::Graph<String, ()>,
}
impl GraphBackend for PetgraphBackend {
fn bfs(&self, seeds: &[String], depth: usize) -> Vec<String> {
// 在内存 petgraph 上执行 BFS 遍历
// 适用于技能依赖图的快速分析
vec![] // 简化示意
}
fn get_outgoing_edges(&self, iri: &str) -> Vec<String> {
vec![]
}
}
pub struct SparqlBackend {
store: Arc<KnowledgeGraphStore>,
}
impl GraphBackend for SparqlBackend {
fn bfs(&self, seeds: &[String], depth: usize) -> Vec<String> {
// 通过 SPARQL 查询在 Oxigraph 上执行 BFS
// 可遍历代码 AST、工具调用结果等任意命名图
vec![] // 简化示意
}
fn get_outgoing_edges(&self, iri: &str) -> Vec<String> {
vec![]
}
}
// 3. CausalEngine 通过依赖注入接收 GraphBackend
pub struct CausalEngine {
backend: Arc<dyn GraphBackend>,
}
impl CausalEngine {
/// 构造函数接受任意实现了 GraphBackend 的后端
pub fn new(backend: Arc<dyn GraphBackend>) -> Self {
Self { backend }
}
/// 根因推断:利用注入的后端执行 BFS 与贝叶斯后验计算
pub fn infer_root_cause(&self, fault_iri: &str) -> Vec<CausalInference> {
let neighbors = self.backend.bfs(&[fault_iri.to_string()], 3);
// 对邻居节点计算贝叶斯后验概率...
vec![]
}
}
// 4. 使用示例:根据场景注入不同的后端
fn main() {
// 场景 A:技能依赖故障 → 使用轻量内存图
let petgraph_backend = Arc::new(PetgraphBackend { /* ... */ });
let engine_for_skills = CausalEngine::new(petgraph_backend);
// 场景 B:跨领域分析 → 使用 RDF 知识图谱
let sparql_backend = Arc::new(SparqlBackend {
store: Arc::new(KnowledgeGraphStore::new()),
});
let engine_for_cross_domain = CausalEngine::new(sparql_backend);
// 两种场景共用同一套 infer_root_cause 逻辑,无需修改引擎内部代码
let result_a = engine_for_skills.infer_root_cause("task:file-write-error");
let result_b = engine_for_cross_domain.infer_root_cause("task:file-write-error");
}
关键点 :CausalEngine 不再关心具体是哪种图存储,只依赖 Arc<dyn GraphBackend> 接口。注入 PetgraphBackend 时获得轻量内存遍历性能,注入 SparqlBackend 时获得全量 RDF 语义探索能力------一行构造函数调用即可切换后端,引擎内部逻辑完全不变。
五、系统集成:从被动记录到主动诊断
融合引擎完全嵌入 Hook 系统,形成闭环:
L0 KnowledgeGraphStore CausalEngine RootCauseEngine HookManager L0 KnowledgeGraphStore CausalEngine RootCauseEngine HookManager #mermaid-svg-yjhIBwlduUnWdD3c{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yjhIBwlduUnWdD3c .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yjhIBwlduUnWdD3c .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yjhIBwlduUnWdD3c .error-icon{fill:#552222;}#mermaid-svg-yjhIBwlduUnWdD3c .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yjhIBwlduUnWdD3c .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yjhIBwlduUnWdD3c .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yjhIBwlduUnWdD3c .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yjhIBwlduUnWdD3c .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yjhIBwlduUnWdD3c .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yjhIBwlduUnWdD3c .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yjhIBwlduUnWdD3c .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yjhIBwlduUnWdD3c .marker.cross{stroke:#333333;}#mermaid-svg-yjhIBwlduUnWdD3c svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yjhIBwlduUnWdD3c p{margin:0;}#mermaid-svg-yjhIBwlduUnWdD3c .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-yjhIBwlduUnWdD3c text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-yjhIBwlduUnWdD3c .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-yjhIBwlduUnWdD3c .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-yjhIBwlduUnWdD3c .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-yjhIBwlduUnWdD3c .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-yjhIBwlduUnWdD3c #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-yjhIBwlduUnWdD3c .sequenceNumber{fill:white;}#mermaid-svg-yjhIBwlduUnWdD3c #sequencenumber{fill:#333;}#mermaid-svg-yjhIBwlduUnWdD3c #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-yjhIBwlduUnWdD3c .messageText{fill:#333;stroke:none;}#mermaid-svg-yjhIBwlduUnWdD3c .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-yjhIBwlduUnWdD3c .labelText,#mermaid-svg-yjhIBwlduUnWdD3c .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-yjhIBwlduUnWdD3c .loopText,#mermaid-svg-yjhIBwlduUnWdD3c .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-yjhIBwlduUnWdD3c .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-yjhIBwlduUnWdD3c .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-yjhIBwlduUnWdD3c .noteText,#mermaid-svg-yjhIBwlduUnWdD3c .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-yjhIBwlduUnWdD3c .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-yjhIBwlduUnWdD3c .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-yjhIBwlduUnWdD3c .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-yjhIBwlduUnWdD3c .actorPopupMenu{position:absolute;}#mermaid-svg-yjhIBwlduUnWdD3c .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-yjhIBwlduUnWdD3c .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-yjhIBwlduUnWdD3c .actor-man circle,#mermaid-svg-yjhIBwlduUnWdD3c line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-yjhIBwlduUnWdD3c :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} TaskError 事件 trace_backward() 5-why infer_root_cause(fault_iri) GraphBackend.bfs() + posterior Vec<CausalInference> get_neighbors(fault_iri, depth=3) RDF 语义子图 fuse_confidence() FusedRootCause 写入诊断报告 (JSON-LD)
诊断报告以 JSON-LD 节点存入 L0,关联原任务 IRI,后续 SA 进行相似任务编排时会参考历史根因;Batch Agent "失败模式挖掘" 也会消费这些报告,提炼出通用失败模式并挂载到技能图谱。这实现了根因分析的 "一次诊断,全局受益"。
六、带来的提升与平台效果
- 准确率提升:融合三维证据后,根因定位的置信度显著高于单维度,避免了"只看调用链以为是参数错误,实际是上游数据源变更"的片面判断。
- 跨领域通用:无论是技能依赖错误、代码缺陷、还是环境资源冲突,都能在统一框架内分析,因为图遍历后端可灵活切换。
- 可解释性强:每份诊断报告都附带三个维度的证据分项,人类审计时可以清晰回溯 AI 的推理过程。
- 系统自愈基础 :根因引擎输出的
recommended_actions已经可以直接喂给 AA(决策 Agent)进行自动修复或回滚。
在流马内部,这套根因分析系统已经从"特定模块的附属工具"升级为系统级的诊断服务,为多 Agent 复杂任务的长稳运行提供了坚实保障。它让我们从"记录错误"迈向了"理解错误",最终走向"预防错误"。
Gliding Horse 已在 GitHub 开源:https://github.com/doiito/gliding_horse