Skip to main content

Squillify development is paused indefinitely. Read why, and discover what this experiment achieved. Read the story

MicroSkills Reference

Risk Matrix Scorer

business.risk_matrix

ProductionBounded custom (Class B)Deterministicstrictinstantv1.0.0
No network

Overview

You send the risks, the likelihood and impact scales they are rated on, and how the two combine — the product of the levels, their sum, or a lookup table you fill in cell by cell. We return each risk's score, the band it falls in, and the action your band declares, plus a count per band for the summary line of a report. A level with no explicit value takes its rank on the ladder, which is what a one-to-five matrix means. A mitigated risk can be multiplied by an adjustment you set, and both the raw and the adjusted score come back so the effect of the mitigation is visible. Bands are checked for gaps and overlaps before anything is scored, and under lookup every cell must be present: a risk with no band would drop out of the report that was meant to escalate it, and a default cell would be our guess at your policy.

Risk matrices live in spreadsheets where the band boundaries are a fill colour and the arithmetic is a formula nobody re-reads. The two failures that follow are always the same: a risk that lands between two bands and quietly gets none, and a matrix that is asymmetric on paper but recomputed as a product in code. Validating the ladder up front and supporting a real lookup table removes both.

Reliability

Fully deterministic: BigDecimal at 34 significant digits, HALF_UP, published at 4 decimal places, no floating point. Bands are half-open — [from, to) — so a score exactly on a boundary belongs to the band above it, and the top band's upper bound is exclusive too, which is why it must sit above the highest score the method can produce. Under LOOKUP the cell's score is used as it stands, never recomputed, so an asymmetric matrix stays asymmetric, and a cell may name a band directly to override the ladder. SCORE_DESC keeps the order you sent for equal scores. Failures: RISK_INPUT_INVALID means a risk or a rule cannot be read — no risks, an id that is empty, too long, padded or carrying a control character, a negative adjustment, or an unaccepted property. RISK_ID_DUPLICATE means a risk id appears twice. RISK_LEVEL_UNKNOWN means a risk or a cell names a level the matrix does not declare. RISK_MATRIX_INVALID means the matrix itself is unusable: fewer than 2 or more than 20 levels, a repeated level or band id, a band that does not rise, cells sent without LOOKUP, a repeated cell, or a cell naming an undeclared band. RISK_CELL_MISSING means the LOOKUP table leaves a combination out. RISK_BANDS_OVERLAP and RISK_BANDS_GAP mean the ladder is not contiguous, or does not reach a score that was produced. RISK_LIMIT_EXCEEDED means more than 2000 risks, 400 cells or 10 bands. None is worth retrying unchanged.

Context footprint

One line per risk plus a small summary, so the response tracks your register size and not the matrix. The lookup cells are not echoed, which keeps a 400-cell request from paying for itself twice. A successful call costs 1 execution credit.

When to use it

When a register must be scored against an agreed matrix, and the bands and actions have to come out the same for everybody.

When you need help rating the risks, or when your scoring is a weighted sum of many criteria rather than a grid.

Scope

Note
Turn each risk's likelihood and impact into a score and a band through the matrix and the bands the caller declares.

Non-goals

  • Does not rate the risks: likelihood and impact are your judgement
  • Does not carry a built-in matrix, band ladder or convention
  • Does not do weighted scoring — this is table lookup and banding, and it shares no engine with business.priority_score or business.decision_matrix
  • Does not escalate, notify, assign or store anything
  • Does not guess a cell the lookup table leaves out

Properties

IdempotentRetry safeStreaming supportedFile input supportedRequires external service

Capabilities

math

Cost & billing

Flat rate per invocation

MetercallsBillable onsuccessCost per call1 credit

File handling

Accepts file_refProduces file_refMax input1 MB

How we handle your data

Sensitive input, safe output
What this means

This skill may receive sensitive content, but it does not target sensitive data and returns only a structured non-sensitive result.

Squillify guarantees
  • Runs inside Squillify
  • This skill runs inside Squillify.
  • Payloads are not sent to an external service by this skill.
  • Squillify does not permanently store submitted payloads.
  • Telemetry records metadata only, not submitted content.
  • Submitted payloads are not used for training.
  • Submitted payloads are not reviewed by humans.
  • This skill does not target sensitive data.
  • The response does not contain submitted content.
Your responsibility

Squillify does not determine whether submitted content is sensitive. Your application is responsible for deciding what data it is allowed to submit. Your application is responsible for securing the response.

Read the Microskill Data Handling Policy

Input schema

FieldTypeRequiredDescription
risksarrayYesBounded array of 1 through 2000 closed risks with unique ids.
matrixobjectYesClosed likelihood/impact matrix with method, levels, optional cells, and optional bands.
rulesobjectNoClosed optional scoring rules; omit the object for adjustment 1 and SCORE_DESC order.

Output schema

FieldTypeRequiredDescription
scoredRisksarrayYesBounded array of 1 through 2000 scored risks in the requested sort order.
summaryobjectYesClosed scoring summary with counts, extrema, and the method actually applied.
matrixobjectYesClosed matrix as actually applied, with resolved level values and bands, without echoing LOOKUP cells.

API contract

POST /v1/execute
curl
curl -sS -X POST "$BASE/v1/execute" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"skillKey":"business.risk_matrix","input":{"risks":[{"id":"r1","likelihood":"high","impact":"severe"}],"matrix":{"likelihoodLevels":[{"id":"low"},{"id":"high"}],"impactLevels":[{"id":"minor"},{"id":"severe"}],"bands":[{"id":"LOW","from":1,"to":3},{"id":"HIGH","from":3,"to":5}]}}}'
Integrations
TypeScript SDK
import { Squillify } from "@squillify/sdk";

const sq = new Squillify({ apiKey: process.env.SQUILLIFY_API_KEY });

const { output } = await sq.execute("business.risk_matrix", {"matrix":{"impactLevels":[{"id":"minor"},{"id":"moderate"},{"id":"severe"}],"bands":[{"id":"LOW","from":1,"to":4,"action":"monitor"},{"id":"MEDIUM","from":4,"to":7,"action":"plan mitigation"},{"id":"HIGH","from":7,"to":10,"action":"escalate"}],"likelihoodLevels":[{"id":"low"},{"id":"medium"},{"id":"high"}]},"risks":[{"id":"r1","likelihood":"high","impact":"severe"},{"id":"r2","likelihood":"high","impact":"severe","mitigated":true},{"id":"r3","likelihood":"low","impact":"minor"}],"rules":{"mitigatedAdjustment":0.5}});

Errors

CodeHTTPRetryableDescription
VALIDATION_ERROR400NoThe request payload failed schema validation.
UNAUTHORIZED401NoMissing or invalid API key.
SKILL_NOT_ACCESSIBLE403NoThe API key is not granted access to this skill.
SKILL_NOT_AVAILABLE_FOR_PLAN403NoThis skill is not included in your current plan.
PLAN_ELIGIBILITY_UNAVAILABLE503YesPlan eligibility could not be decided. Retry after backoff.
SKILL_NOT_FOUND404NoThe requested skill or version does not exist.
TENANT_RATE_LIMITED429YesRequest rate limit exceeded. Retry after backoff.
QUOTA_EXCEEDED429YesPlan quota exhausted. Retryable once the quota period resets.
EXECUTION_TIMEOUT504YesExecution exceeded the allowed time budget.
RISK_INPUT_INVALID400NoThe request payload failed this skill's input validation.
RISK_ID_DUPLICATE400NoThe request payload failed this skill's input validation.
RISK_LEVEL_UNKNOWN400NoThe request payload failed this skill's input validation.
RISK_MATRIX_INVALID400NoThe request payload failed this skill's input validation.
RISK_CELL_MISSING400NoThe request payload failed this skill's input validation.
RISK_BANDS_OVERLAP400NoThe request payload failed this skill's input validation.
RISK_BANDS_GAP400NoThe request payload failed this skill's input validation.
RISK_LIMIT_EXCEEDED429NoA size, quota, rate, or time limit was exceeded.

Other limits

LimitValue
Recommended inline bytes32 KiB

Limitations

  • Does not rate the risks: likelihood and impact are your judgement
  • Does not carry a built-in matrix, band ladder or convention
  • Does not do weighted scoring — this is table lookup and banding, and it shares no engine with business.priority_score or business.decision_matrix
  • Does not escalate, notify, assign or store anything
  • Does not guess a cell the lookup table leaves out
  • Deciding how likely something is, or how bad it would be
  • Weighted multi-criteria scoring — use business.priority_score
  • Registers past 2000 risks in one call: split them

How to call

POST /v1/execute (requires authentication)

Request bodyjson
{
  "skillKey": "business.risk_matrix",
  "input": {
    "matrix": {
      "impactLevels": [
        {
          "id": "minor"
        },
        {
          "id": "moderate"
        },
        {
          "id": "severe"
        }
      ],
      "bands": [
        {
          "id": "LOW",
          "from": 1,
          "to": 4,
          "action": "monitor"
        },
        {
          "id": "MEDIUM",
          "from": 4,
          "to": 7,
          "action": "plan mitigation"
        },
        {
          "id": "HIGH",
          "from": 7,
          "to": 10,
          "action": "escalate"
        }
      ],
      "likelihoodLevels": [
        {
          "id": "low"
        },
        {
          "id": "medium"
        },
        {
          "id": "high"
        }
      ]
    },
    "risks": [
      {
        "id": "r1",
        "likelihood": "high",
        "impact": "severe"
      },
      {
        "id": "r2",
        "likelihood": "high",
        "impact": "severe",
        "mitigated": true
      },
      {
        "id": "r3",
        "likelihood": "low",
        "impact": "minor"
      }
    ],
    "rules": {
      "mitigatedAdjustment": 0.5
    }
  }
}

Examples

A three-by-three product matrix with bands, and one risk halved by its mitigation

Inputjson
{
  "matrix": {
    "impactLevels": [
      {
        "id": "minor"
      },
      {
        "id": "moderate"
      },
      {
        "id": "severe"
      }
    ],
    "bands": [
      {
        "id": "LOW",
        "from": 1,
        "to": 4,
        "action": "monitor"
      },
      {
        "id": "MEDIUM",
        "from": 4,
        "to": 7,
        "action": "plan mitigation"
      },
      {
        "id": "HIGH",
        "from": 7,
        "to": 10,
        "action": "escalate"
      }
    ],
    "likelihoodLevels": [
      {
        "id": "low"
      },
      {
        "id": "medium"
      },
      {
        "id": "high"
      }
    ]
  },
  "risks": [
    {
      "id": "r1",
      "likelihood": "high",
      "impact": "severe"
    },
    {
      "id": "r2",
      "likelihood": "high",
      "impact": "severe",
      "mitigated": true
    },
    {
      "id": "r3",
      "likelihood": "low",
      "impact": "minor"
    }
  ],
  "rules": {
    "mitigatedAdjustment": 0.5
  }
}
Expected outputjson
{
  "matrix": {
    "likelihoodLevels": [
      {
        "id": "low",
        "value": 1
      },
      {
        "id": "medium",
        "value": 2
      },
      {
        "id": "high",
        "value": 3
      }
    ],
    "impactLevels": [
      {
        "id": "minor",
        "value": 1
      },
      {
        "id": "moderate",
        "value": 2
      },
      {
        "id": "severe",
        "value": 3
      }
    ],
    "method": "PRODUCT",
    "bands": [
      {
        "id": "LOW",
        "from": 1,
        "to": 4,
        "action": "monitor"
      },
      {
        "id": "MEDIUM",
        "from": 4,
        "to": 7,
        "action": "plan mitigation"
      },
      {
        "id": "HIGH",
        "from": 7,
        "to": 10,
        "action": "escalate"
      }
    ]
  },
  "summary": {
    "riskCount": 3,
    "byBand": {
      "HIGH": 1,
      "MEDIUM": 1,
      "LOW": 1
    },
    "maxScore": 9,
    "minScore": 1,
    "method": "PRODUCT"
  },
  "scoredRisks": [
    {
      "id": "r1",
      "likelihood": "high",
      "impact": "severe",
      "rawScore": 9,
      "adjustedScore": 9,
      "band": "HIGH",
      "action": "escalate",
      "mitigated": false
    },
    {
      "id": "r2",
      "likelihood": "high",
      "impact": "severe",
      "rawScore": 9,
      "adjustedScore": 4.5,
      "band": "MEDIUM",
      "action": "plan mitigation",
      "mitigated": true
    },
    {
      "id": "r3",
      "likelihood": "low",
      "impact": "minor",
      "rawScore": 1,
      "adjustedScore": 1,
      "band": "LOW",
      "action": "monitor",
      "mitigated": false
    }
  ]
}

A lookup table whose corner cell is deliberately not the product of its levels

Inputjson
{
  "risks": [
    {
      "id": "a",
      "likelihood": "rare",
      "impact": "high"
    }
  ],
  "matrix": {
    "impactLevels": [
      {
        "id": "low"
      },
      {
        "id": "high"
      }
    ],
    "likelihoodLevels": [
      {
        "id": "rare"
      },
      {
        "id": "likely"
      }
    ],
    "method": "LOOKUP",
    "cells": [
      {
        "likelihood": "rare",
        "impact": "low",
        "score": 1
      },
      {
        "likelihood": "rare",
        "impact": "high",
        "score": 5
      },
      {
        "likelihood": "likely",
        "impact": "low",
        "score": 2
      },
      {
        "likelihood": "likely",
        "impact": "high",
        "score": 9
      }
    ]
  }
}
Expected outputjson
{
  "matrix": {
    "likelihoodLevels": [
      {
        "id": "rare",
        "value": 1
      },
      {
        "id": "likely",
        "value": 2
      }
    ],
    "impactLevels": [
      {
        "id": "low",
        "value": 1
      },
      {
        "id": "high",
        "value": 2
      }
    ],
    "method": "LOOKUP"
  },
  "summary": {
    "riskCount": 1,
    "byBand": {},
    "maxScore": 5,
    "minScore": 5,
    "method": "LOOKUP"
  },
  "scoredRisks": [
    {
      "id": "a",
      "likelihood": "rare",
      "impact": "high",
      "rawScore": 5,
      "adjustedScore": 5,
      "mitigated": false
    }
  ]
}
  • Score a risk register the same way every quarter, with the bands published
  • Show the effect of a mitigation as a before-and-after score on one line
  • Enforce an agreed matrix — including an asymmetric one — across several teams
  • Produce the count-per-band figures a risk report opens with

Avoid for

  • Deciding how likely something is, or how bad it would be
  • Weighted multi-criteria scoring — use business.priority_score
  • Registers past 2000 risks in one call: split them

Composable with

Safety & privacy

  • Runs without calling any external service.
  • Your payloads are never stored permanently.
  • Telemetry captures metadata only — never your payload contents.
  • We never train models on your payloads.
  • No human reviews your payloads.

Tags

analysisriskbusinessmatrix