5. End to end in ten lines¶
Everything from the first four tutorials, as one object.
from hiphopsllm import AgenticReliabilityStudy, load_example, load_outcomes
study = AgenticReliabilityStudy(load_example("parallel_aggregator"))
study.observe(load_outcomes(), profile={"short": 0.3, "medium": 0.5, "long": 0.2})
study.run()
print(study.summary())
print(study.hazard_probability("H2"))
study.bayesnet("H2").show()
study.save("artifacts/")
Or as a chain:
study = (
AgenticReliabilityStudy(graph, globals_ns=globals())
.observe(outcomes, profile=profile)
.run()
)
run() calls analyse() if it has not been called, then calibrate() if
outcomes were given. Nothing happens implicitly: a study with no outcomes reports
placeholder probabilities and prints NOT CALIBRATED in capitals.
Comparing architectures¶
The comparison is where this earns its keep. Same profile, same data, three architectures:
import pandas as pd
from hiphopsllm import EXAMPLES
rows = []
for key in EXAMPLES:
s = AgenticReliabilityStudy(load_example(key), name=key)
s.analyse()
a = s.report.analysis("H2")
rows.append({
"architecture": key,
"components": len(s.system.components),
"P(H2)": round(a.quant.top_probability, 4),
"cut sets": len(a.cuts.sets),
"min order": min(len(c) for c in a.cuts.sets),
"SPOFs": len(a.single_points),
})
pd.DataFrame(rows)
architecture components P(H2) cut sets min order SPOFs
0 react_calculator 6 0.3335 4 1 4
1 parallel_aggregator 5 0.2787 11 1 3
2 supervisor_workers 8 0.4293 14 1 5
Two things worth noticing, and neither is obvious from an architecture diagram.
More components is not more reliable. supervisor_workers has the most parts
and the worst P(H2). Its router, its three specialists and its verifier are all
in series on the value path — a supervisor that routes to the wrong specialist
and a verifier that passes a wrong answer are each single points of failure. Depth
without redundancy just adds ways to be wrong.
Every one of them has min order == 1. None of these architectures is free of
single points of failure for the critical hazard.
Does diversity help?¶
The parallel architecture’s redundancy is defeated by a shared model snapshot. Test the counterfactual without changing any code:
cases = {
"as built (shared snapshot)": {},
"cot_agent diversified": {
"cot_agent": {"llm": "gpt-4o-mini", "runtime": "api"},
},
"all three diversified": {
"cot_agent": {"llm": "gpt-4o-mini", "runtime": "api"},
"aggregator": {"llm": "claude-sonnet-4-5", "runtime": "api2"},
},
}
for name, overrides in cases.items():
s = AgenticReliabilityStudy(load_example("parallel_aggregator"),
name=name, resource_overrides=overrides)
s.analyse()
a = s.report.analysis("H2")
order_1 = sorted(next(iter(c)) for c in a.cuts.sets if len(c) == 1)
print(f"{name:<28} P(H2)={a.quant.top_probability:.4f} order-1={order_1}")
as built (shared snapshot) P(H2)=0.2787 order-1=['BE-__start__-BADREQ',
'BE-aggregator-OWN',
'CCF-LLM-Qwen-…']
cot_agent diversified P(H2)=0.2787 order-1=['BE-__start__-BADREQ',
'BE-aggregator-OWN',
'CCF-LLM-Qwen-…']
all three diversified P(H2)=0.2160 order-1=['BE-__start__-BADREQ',
'BE-aggregator-OWN']
Diversifying one agent changes nothing. The common-cause group shrinks from
three members to two — but the judge is still one of them, and the judge is on
the value path on its own, so CCF-LLM-… remains an order-1 cut set. You have to
diversify the judge too before the vote is worth anything, and then P(H2) drops
by a fifth.
This is a result you would be unlikely to reach by reasoning about the diagram, and it is the kind of thing the package exists to surface.
Profile sensitivity¶
The answer is conditional on the workload. Vary it:
profiles = {
"as measured": {"short": 0.30, "medium": 0.50, "long": 0.20},
"harder": {"short": 0.05, "medium": 0.15, "long": 0.80},
"easier": {"short": 0.70, "medium": 0.25, "long": 0.05},
}
for name, profile in profiles.items():
s = AgenticReliabilityStudy(load_example("parallel_aggregator"))
s.observe(load_outcomes(), profile=profile).run()
print(f"{name:<12} P(H2) ∈ {s.hazard_probability('H2')}")
Nothing about the system changed between those three rows. Quoting a single failure probability without saying which workload it is conditional on is therefore not a claim about the system at all.
What save() writes¶
study.save("artifacts/")
artifacts/agentic_workflow_report.md the analysis, incl. loop and CCF notes
artifacts/agentic_workflow_architecture.mmd the system as mermaid
artifacts/agentic_workflow_H2.mmd/.dot/.json the tree, three ways
artifacts/agentic_workflow_H2.opsa.xml Open-PSA MEF, for XFTA / SCRAM
artifacts/agentic_workflow_cutsets.csv every cut set, with its probability
artifacts/agentic_workflow_fmea.csv the generated FMEA
artifacts/calibration.csv placeholder → measured, per event
artifacts/evidence.csv n, failures, interval, per component
The last two are the provenance record. Six months later they are the difference between a number someone can check and a number someone has to trust.