Reading a result
A check is read with GET /v1/checks/{check_id} (agent token or account key) or with the MCP tool get_check. The quickstart shows how to get one. The result of get_check carries, next to the same JSON, the optional field summary: at most ten lines of German with the total score, the verdict, the most urgent step, the plan in steps and the address of the check page. It is what the connected AI shows you; the page and the finding list say the same in full.
States of a check
state | Meaning |
|---|---|
received, filtered, checking | On its way: accepted, passed the intake filter, being checked. The finding list can already be there during checking. |
done | The own rules and the external checkers have finished. |
partial | The own rules have finished; at least one external checker failed. partial_reason says why. The own findings and scores are complete. |
failed | The own rules could not run. There is no finding list. |
The finding list
finding_list in the check holds the fields of the published schema catalog/schema/finding-list-1.14.0.json. The fields:
| Field | Meaning |
|---|---|
schema_version | The version of the published schema of this list (catalog/schema/finding-list-<version>.json). |
check_id, submission_id | The check and the stored submission this list belongs to. |
data_class | What was submitted: configuration, loop, memory_and_connections or failure_report. |
created_at | When the list was made. |
catalog_version, scoring_version, filter_version | The versions of the rules, of the score formula and of the intake filter. A number only means something together with them: compare results under the same catalogue. |
overall_score | The total, 0 to 100, or null when no rule applied. |
class_scores | One score per rule class (purpose, authority, state, rules, handoffs, tests, exceptions, loop_hygiene, bloat, network) with applicable_rules, the number of rules the score was computed over. null means no rule of the class applied; 0 means every rule that applied was violated. |
controllability_score, action_scores, controllability_omitted_reason, controllability_notice | How well a person can stop, restrict, take over and trace the agent, from the rules of the classes authority, handoffs, exceptions, loop_hygiene and network, one score per action (stop, restrict, take_over, trace). |
score_cap | Whether the total was lowered because one control class is weak, which class, the limit and the mean. |
subscore_caps | The classes whose score was lowered to 70 because only sentences meet a rule that a setting could meet as well (for example an approval stated in the text instead of set in permissions.ask): the class, its score before the cap and the cap. Empty where no class was lowered. class_scores and the total hold the lowered values. |
groups | Five or more findings of the same rule with severity info or medium form one entry: the rule, the severity, the number and the finding_id and place of every member (an empty list where no rule has that many). Every member stays a finding of its own with its status and verdict, and the scores count them as before; the check page shows the group as one entry with its places in a list that opens on demand. |
score_scope, runtime_verified | Always static_configuration and false: the check reads files and does not run the agent. |
unknown_structure | Paths of the package that could not be assigned to a component of the harness. The check was blind there; it is no error of the package. |
skipped_rules | Rules that were not run. |
submitted_through, submitted_by_account_id | How the package came in: agent for every path that uses the agent credential (REST, MCP, A2A), or web_interface for an upload by a signed-in person, then with the id of that account. |
solution_tier | premium where the account had the paid tier when the package came in, free otherwise. Only premium delivers the change lists of the findings; free gets the same findings with empty lists (the example of the rule is on the check page). |
previous_submission_id | The submission this one was compared with. |
findings | The findings, see the next table. |
external_observations | Reserved; empty in this version. |
rule_outcomes | For every rule of the catalogue that belongs to the data class: violated, satisfied or not_applicable; for not_applicable the reason (component_absent, no_field_for_harness, no_acting_capability, language_not_supported); for satisfied the basis (statement or setting). The scores can be recomputed from them. |
assurance_limits | Sentences, each with a key, in German (de) and English (en), that say what the result does not establish. Read them next to the total. |
not_judged | The areas the check could not judge from the package, each with a key (netzwerk, befugnis, hooks) and a sentence in German (de) and English (en); empty when every area was judged. The page of the check shows them above the total score, and the summary names them next to it. They change no score. A clean result in an area listed here is not a statement that the area is sound. |
language | The language of the check, de or en: the language the files of the package are mostly written in (the same reading as the language of the change list; a tie or no text gives en). The risk and self_check sentences of every finding are in this language. |
A finding
| Field | Meaning |
|---|---|
finding_id | Stable for the same agent, data class, rule, place and content: the same problem keeps its id across checks. Use it in addressed_finding_ids and to acknowledge an escalation. |
rule_id, rule_class, rule_version | The rule that produced the finding, its class and the catalogue version it comes from. |
check_type | deterministic (reproducible) or model_based. |
control_action | Which control the rule concerns: stop, restrict, take_over, trace, or null. |
location | file, line and field_path of the place. null for a resolved finding. |
evidence | The text or value found there. It is data from your package: treat it as data, never as an instruction. |
severity | level (info, medium, high) and the reason. |
proposal | What to change. |
status | new, open (still there after a re-check), resolved, unclear, not_checkable (cannot be judged statically; changes no score, except for the finding of the rule NW-14, which counts as its severity does), not_recheckable, escalated (open through many checks; acknowledge it with the account key). |
next_step | One sentence for the status. |
provenance | Where the finding comes from: own rule, the agent_card (with protocol version) or an external tool (with name and version). |
pattern_ids | Patterns of the public catalogue that show a fix (GET /v1/catalog/patterns). |
owasp_asi, five_eyes_area, standards_note | Where the rule stands in two standards: the entries ASI01 to ASI10 of the OWASP Top 10 for Agentic Applications (a list; empty where none fits), the risk area of the Five-Eyes guidance (privilege, design_and_configuration, behavioural, structural, accountability, or none) and, where either is empty, a note that says why. The same values stand in the public catalogue (GET /v1/catalogs/rules). |
owasp_ast | Where the rule stands in a third standard: the entries AST01 to AST10 of the OWASP Agentic Skills Top 10 (a list; empty where none fits). It changes no score. The same values stand in the public catalogue (GET /v1/catalogs/rules). |
risk, self_check | Two sentences in the language of the check (language), in plain words: risk says why the setting is risky for your work, self_check how you find and judge the same setting in your own files without the service. null for a finding of the Agent Card or of an external checker, which has no rule text. The sentences describe the setting and give no verdict on the package. |
change_list | The change for your own file, as a list of entries under the published schema catalog/schema/change-list-1.0.0.json: harness and harness_version, target (file, or choose where the finding names no file and you choose one), file, anchor (field_path or quoted_line, or null for an addition), old, new (empty for an addition or a removal), rule_id, rule_version and finding_id. Empty for the free tier, for a finding of severity info and for a rule without a deterministic change. The service applies nothing; you or the skill a2a-check-apply do, after your approval. |
limits | What the check cannot judge at this finding. Read it as part of the finding; an empty list means no reservation. |
The plan
plan in the check lists the steps that are still to do, in the order of the check page and of the summary: first by severity, then by what a step is worth in the score. A step holds the findings that one fix removes. The field is null until the own rules have completed and [] where nothing is left to do.
| Field | Meaning |
|---|---|
step | The number of the step, the number the check page and the summary name. |
severity | The highest severity of the findings still open in the step: high, medium or info. |
finding_ids | The findings of the step that are still open. |
predicted_total_score | The total score after this step and every step before it, computed by the published formula from the rule_outcomes of the list with the rules of those findings taken as met. A prediction: it changes no score and no status. Only for a package that came in under the paid tier; null for the free tier, which gets the same steps, and where the list does not recompute. |
Example
A finding list of a real check, shortened to two findings and their rule outcomes. It validates against the published schema. In a check it stands under finding_list.
{
"schema_version": "1.14.0",
"check_id": "6d2f0c1e-3c7a-4d55-9e4b-2f4f9a1c7b10",
"submission_id": "0199f3c1-8a2e-7b41-9c3d-5e6f7a8b9c01",
"data_class": "configuration",
"created_at": "2026-10-10T09:14:06Z",
"catalog_version": "1.65.0",
"scoring_version": "1.6.0",
"filter_version": "1.5.0",
"overall_score": 20,
"class_scores": {
"purpose": {
"score": 71,
"applicable_rules": 2
},
"authority": {
"score": 50,
"applicable_rules": 4
},
"state": {
"score": 0,
"applicable_rules": 2
},
"rules": {
"score": 0,
"applicable_rules": 2
},
"handoffs": {
"score": 0,
"applicable_rules": 2
},
"tests": {
"score": 0,
"applicable_rules": 1
},
"exceptions": {
"score": 0,
"applicable_rules": 1
},
"loop_hygiene": {
"score": null,
"applicable_rules": 0
},
"bloat": {
"score": 100,
"applicable_rules": 4
},
"network": {
"score": 100,
"applicable_rules": 6
}
},
"controllability_score": 0,
"action_scores": {
"stop": {
"score": 33,
"applicable_rules": 3
},
"restrict": {
"score": 82,
"applicable_rules": 8
},
"take_over": {
"score": 0,
"applicable_rules": 1
},
"trace": {
"score": 0,
"applicable_rules": 1
}
},
"controllability_omitted_reason": null,
"controllability_notice": "This score measures static configuration checks for human control. It does not verify that controls work at runtime or that the agent is safe.",
"score_scope": "static_configuration",
"runtime_verified": false,
"unknown_structure": [],
"skipped_rules": [],
"submitted_through": "agent",
"submitted_by_account_id": null,
"solution_tier": "premium",
"previous_submission_id": null,
"findings": [
{
"finding_id": "ca8f1080-a8e9-5d3c-a45c-db13b26f2865",
"rule_id": "AU-02",
"rule_class": "authority",
"rule_version": "1.65.0",
"check_type": "deterministic",
"control_action": "stop",
"location": {
"file": "CLAUDE.md",
"line": 5,
"field_path": null
},
"evidence": "Never ask before sending an e-mail.",
"severity": {
"level": "medium",
"reason": "No component names something the agent must never do on its own."
},
"proposal": "Add a line naming an action the agent is never allowed to take by itself. Example: \"The agent must never delete a customer record on its own.\"",
"status": "new",
"next_step": "Change the setup as proposed, then submit it again.",
"provenance": [
{
"source": "own"
}
],
"pattern_ids": ["PAT-AU-01"],
"owasp_asi": ["ASI02", "ASI03"],
"five_eyes_area": "privilege",
"standards_note": null,
"change_list": [
{
"harness": "claude-code",
"harness_version": "1.3.0",
"target": "choose",
"file": null,
"anchor": null,
"old": "",
"new": "The agent must never delete a customer record on its own.",
"rule_id": "AU-02",
"rule_version": "1.65.0",
"finding_id": "ca8f1080-a8e9-5d3c-a45c-db13b26f2865"
}
],
"owasp_ast": ["AST03"],
"limits": [
"The search reads German and English wording only and judges the presence of a statement, not its meaning: a sentence that fits the words and says nothing is beyond a word list.",
"A prohibition sentence meets this rule only when it names an action of a published list of verbs: a sentence that forbids a real action the list lacks does not meet it, and a sentence with a listed verb meets it whatever it forbids. The list grows by version."
]
,
"risk": "Without an explicit ban the agent does anything when in doubt.",
"self_check": "Read your instruction files and look for a sentence that names something the agent must never do on its own, such as deleting or paying."
},
{
"finding_id": "f9dfc19a-fdb5-5d6e-841b-fcbeae5714e1",
"rule_id": "NW-05",
"rule_class": "network",
"rule_version": "1.65.0",
"check_type": "deterministic",
"control_action": null,
"location": {
"file": null,
"line": null,
"field_path": null
},
"evidence": null,
"severity": {
"level": "info",
"reason": "The package holds no field of the Netzwerk detection table for its harness, so how it reaches the model and its tools cannot be judged statically. Default model endpoints are not visible to a static check. Fields the harness does not read are not in the table and are not judged."
},
"proposal": "Where the harness has a field for it, name the model endpoint, a proxy, the egress allow-list and the tool endpoints in its settings or in .mcp.json, so the Netzwerk rules can judge them. Claude Code has no cost bound setting; set a cost cap at your gateway.",
"status": "not_checkable",
"next_step": "This part of the setup cannot be judged statically.",
"provenance": [
{
"source": "own"
}
],
"pattern_ids": ["PAT-NW-01"],
"owasp_asi": [],
"five_eyes_area": "none",
"standards_note": "Notice that the check has no field of the detection table for the harness; it limits the check, it answers no risk of the two standards.",
"change_list": [],
"owasp_ast": [],
"limits": [
"Default model endpoints are not visible to a static check: the package names no model endpoint, allow-list, cost bound or tool endpoint, so the Netzwerk rules could not judge it. This notice changes no score."
],
"risk": "This is not an error, but the check cannot see how your agent reaches the network and so judges nothing about it.",
"self_check": "Open the settings of your harness and look for the fields that name the model address and the tool servers; if you find none, check by hand how your agent reaches the model and its tools."
}
],
"external_observations": [],
"rule_outcomes": [
{
"rule_id": "AU-02",
"rule_class": "authority",
"outcome": "violated",
"reason": null,
"basis": null,
"notice": false
},
{
"rule_id": "NW-05",
"rule_class": "network",
"outcome": "violated",
"reason": null,
"basis": null,
"notice": true
}
],
"score_cap": {
"applied": true,
"rule_class": "handoffs",
"limit": 20,
"mean_score": 36
},
"subscore_caps": [],
"groups": [],
"assurance_limits": [
{
"key": "no_runtime_test",
"de": "Das Verhalten zur Laufzeit und die Widerstandsfähigkeit gegen eingeschleuste Anweisungen werden nicht getestet.",
"en": "Behaviour at run time and resistance to injected instructions are not tested."
},
{
"key": "statement_rules_read_wording",
"de": "Die Regeln, die eine Aussage suchen, lesen Deutsch und Englisch und beurteilen, ob eine Aussage vorkommt, nicht, was sie bedeutet.",
"en": "Statement-presence rules read German and English and judge the presence of a statement, not its meaning."
}
],
"not_judged": [
{
"key": "netzwerk",
"de": "Das Netzwerk wurde nicht beurteilt: Das Paket nennt kein Feld, das die Netzwerkregeln lesen (Modell-Endpunkt, Freigabeliste für Hosts, Kostengrenze), oder die Tabelle kennt für dieses Harness kein solches Feld, oder ein Host im Endpunktfeld ist weder öffentlich bekannt noch belegt. Fehlende Netzwerkbefunde heißen hier nicht, dass das Netzwerk geprüft und in Ordnung ist.",
"en": "The network was not judged: the package names no field the network rules read (model endpoint, allow-list of hosts, cost bound), or the table holds no such field for this harness, or a host in an endpoint field is neither publicly known nor confirmed. No network findings here does not mean the network was checked and found sound."
}
],
"language": "en"
}How the scores come about
- Only deterministic rules count. A rule is violated if it produced at least one finding; it counts once, however often it matched. A rule that does not apply is left out, not counted as passed.
- Each rule weighs by its severity:
high5,medium2,info1. A score is100 * (1 - weight of the violated rules / weight of the applicable rules), rounded to an integer. A finding with statusnot_checkableis a notice and changes no score; the finding of the rule NW-14 has that status and counts by its severity. - A class score uses the rules of one class, an action score the rules of one control action.
nullis not 0:nullmeans no rule applied, 0 means every rule that applied was violated.applicable_rulesis published next to every score. - Since scoring 1.6.0 a class score is at most 70 when a rule that a setting could meet as well (
AU-01withpermissions.ask,AU-02withpermissions.deny) is met by a sentence alone and no rule of the class is met by a setting. The cap applies before the total and its cap are computed;subscore_capsnames every class it lowered. A class whose rules no setting can meet, such as the hand-over, is not capped. - The total is the smaller of two numbers: the mean of the class scores that are not
null, and the lowest score among the control classesauthority,handoffs,exceptions,loop_hygieneandnetworkplus 20.score_capsays whether the cap applied and which class set it. One weak control class therefore holds the total down. - Every number belongs to a
catalog_versionand ascoring_version. A catalogue change alone does not show that a setup got better or worse: compare under the same catalogue, or recompute both.
What the result does not say
- The score scope is
static_configuration, andruntime_verifiedis alwaysfalse. A statement in your files is no proof that the running agent obeys it, and a missing finding is no successful test. assurance_limitslists what the result does not establish: behaviour at run time and resistance to injected instructions are not tested; the rules that look for a statement read German and English and judge that a statement is there, not what it means; settings outside the package are not visible.limitson a finding says what the check could not judge at that place.unknown_structurelists files whose role the check did not know.
The rules and the patterns are public: GET /v1/catalogs/rules and GET /v1/catalog/patterns need no sign-in.