Skip to content

ISO 23894 — AI risk management

ISO/IEC 23894:2023 is the AI-specific risk management guidance derived from the ISO 31000 generic framework. It defines an iterative six-phase process (§6.4–§6.7) that the froga engine implements directly. It is the primary process standard against which EU AI Act Art. 9 obligations and prEN 18228 coverage are projected.


Identification is the first step of the process: determining which risk events may affect the system, their potential consequences, and the relevant sources of risk.

Implementation in the engine: the AssuranceProgram (the risk: section of froga.yaml) is the live identification register. Risks are declared with explicit provenance:

ProvenanceMeaning
declaredDeclared by the team at design time
proposed_by_kagAssisted identification (the future KAG’s domain); today set by hand
derived_from_gapDerived from a gap detected in the evidence

The register grows during development: the team identifies and declares new risks by hand in froga.yaml and commits them (the KAG will assist this identification in the future; today froga assess is an honest stub, advisory). froga reconstruct can show when each risk was introduced into the register via git log -S <risk_id>.


Analysis determines the nature of each risk and its level, combining the probability of occurrence with the expected consequences.

Implementation in the engine: the function risk_level(likelihood, impact) implements the deterministic 5×5 matrix. Likelihood is expressed in five levels (Rare, Unlikely, Possible, Likely, AlmostCertain); impact follows the existing RiskLevel scale (Negligible, Low, Medium, High, Critical).

Analysis is calculated per dimension: individual, societal, and organisational. Each dimension can have different likelihood and impact levels, allowing the same risk event to have distinct profiles depending on who is affected.

The result of the analysis is stored in EvidenceBundle.risk_analysis (field Vec<RiskAssessment>) in the signed bundle.


§6.4.4 — Risk evaluation against appetite

Section titled “§6.4.4 — Risk evaluation against appetite”

Evaluation compares the analysed risk level against the acceptability criteria defined by the organisation (risk appetite). The result determines whether the risk requires treatment.

Implementation in the engine: evaluate(level, appetite) → Within | Exceeds. Appetite is declared in froga.yaml (risk.appetite) per dimension, with levels calibrated for each scenario (in the loan scenario: individual/societal → MEDIUM, organisation → HIGH).

If the analysed level does not exceed the appetite, the risk can be monitored without further treatment. If it does, treatment is required.


Treatment selects and implements options to modify the risk profile until it falls within the appetite. ISO 23894 recognises the options REDUCE, AVOID, TRANSFER, and ACCEPT.

Implementation in the engine: the TreatmentMethod type models all four options:

OptionBehaviour in the engine
REDUCEThe blocking control must pass; the risk is evaluated as closed or with discrepancy
ACCEPTThe risk is explicitly accepted; the gate does not fail for this risk (ControlResult.accepted)
AVOIDThe risk is avoided; the cycle ends in Avoided
TRANSFERThe risk is transferred to a third party; the cycle ends in Transferred

The engine also models positive risks (opportunities) with RiskKind::Opportunity and TreatmentMethod::Pursue. An opportunity is pursued, never gated.

Treatment modalities: treatment is a versioned change — to code, to an operational parameter, or (in future) to a prompt. The change commit is the treatment act; git dates it, attributes it, and anchors it to the triad (code, model, dataset).

See Two gates: freshness and risk for the complete cycle.


The residual for a risk is calculated in a hybrid manner: the measure declares the expected residual_likelihood after treatment; the blocking control confirms it empirically. If there is a discrepancy between the declared and observed residual, the cycle ends in Discrepancy status.

Possible states of the risk cycle (RiskCycle):

StateCondition
ClosedInherent level was within appetite, or treatment brought residual within appetite
MonitoredNo blocking control; level within appetite; under observation
OpenLevel exceeds appetite; treatment pending or ineffective
AcceptedRisk explicitly accepted with justification
DiscrepancyDeclared and observed residual diverge
Avoided / TransferredRisk eliminated or transferred
Realized / PursuingFor opportunities

The process requires monitoring the effectiveness of treatments and the risk state throughout the lifecycle. Changes to the system context or environment may make previously closed risks relevant again.

Implementation in the engine: froga status evaluates the freshness of the signed evidence without recomputing. If the code, model, or dataset have changed since the last run, the evidence is considered stale and the cycle restarts. The typed drift model (class A, B, C) determines which parts of the cycle need re-evaluation. See Methodology: Typed drift.


The process requires documenting the results of each phase and maintaining traceable records for subsequent review.

Implementation in the engine: froga reconstruct replays the complete treatment cycle per risk from the bundle’s git log, without recomputation. The report shows the five phases: ①identification ②analysis ③evaluation-vs-appetite ④treatment (control arc + treatment event) ⑤residual (cycle). The signed bundle stores risk_analysis + assessor (evaluator identity, §6.7). froga approve --by records management approval.


The file crates/froga-core/resources/standards/iso-23894-clauses.yaml declares the modelled clauses:

standard: iso/23894@2023
clauses:
- { id: "6.4.2", title: "Risk identification", cycle_phase: identification }
- { id: "6.4.3", title: "Risk analysis", cycle_phase: analysis }
- { id: "6.4.4", title: "Risk evaluation", cycle_phase: evaluation }
- { id: "6.5", title: "Risk treatment", cycle_phase: treatment }
- { id: "6.6", title: "Monitoring and review", cycle_phase: monitor }
- { id: "6.7", title: "Recording and reporting", cycle_phase: file }

ISO 23894 defines the process of risk management. prEN 18228 defines the product requirements for AI systems (product-safety paradigm: hazard→harm, control hierarchy, overall residual risk). Venturalítica implements ISO 23894 as the engine and projects prEN 18228 via clause catalogue. A single signed bundle can generate conformance reports for both standards.

See prEN 18228 and Guide: Dual-standard conformance.


ISO 23894 as a projection (agnostic model)

Section titled “ISO 23894 as a projection (agnostic model)”

Since PRs #518 and #522, ISO 23894 is not hardcoded in the engine: it is the default projection within the agnostic risk model.

ScoringModel::FiveByFive is the scoring seam that implements the 5×5 likelihood × impact matrix described in the sections above. It is the default implementation of the ScoringModel trait (crates/froga-core/src/risk/matrix.rs); other standards can plug in their own scoring seam without touching the core.

Canonical primitives. The fields source, pathway, consequence, and benefit_risk added to ApRisk (crates/froga-core/src/assurance/mod.rs) are the primitives of the agnostic causal chain. They are optional (serde(default)); their absence does not alter the signature of existing bundles.

risk_projection_catalog() and derive_risk_projection (crates/froga-core/src/risk_projection.rs) replicate the pattern of clause_catalog/derive_conformance from standards.rs, lifted from the measure level to the risk level. The iso/23894@2023 projection is one of the three that ship; a parity test verifies that the projected residual level matches the residual_overall computed by the engine.

The applicable_standards field in the manifest controls which projections are generated simultaneously when running froga risk-projection without --framework.

See Guide: Agnostic risk model for the full description of the projection mechanism and the three supported frameworks (ISO 14971, prEN 18228, ISO 23894).