Explain Why
Type: Procedure
Retrieve the full audit trail and stored evaluation trace for a previous authorization decision or query validation. Use decision_id from authorize-use or validation_id from validate-query-context.
Use Cases
- A compliance officer reviews why a particular data access request was denied
- An AI agent explains to a user why their query was flagged as non-compliant
- An audit workflow retrieves historical decision records for regulatory reporting
- A developer debugs unexpected authorization outcomes by examining the evaluation trace
Input Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
decision_id | string | No | The unique decision identifier returned by authorize-use. |
validation_id | string | No | The unique validation identifier returned by validate-query-context. |
Output Schema
| Field | Type | Description |
|---|---|---|
trace_type | string | authorization_decision or query_validation |
decision_id | string | The decision identifier for authorization traces |
validation_id | string | The validation identifier for query validation traces |
snapshot_id | string | Identifier of the governance snapshot used at evaluation time |
table_name | string | Fully qualified table name from the original request |
operation | string | The operation that was evaluated |
intended_use | string | The stated intended use from the original request |
actor_role | string | The role that was evaluated |
decision | string | The decision outcome: ALLOW, DENY, CONDITIONAL, UNKNOWN |
decision_kind | string | Operator-facing decision category such as explicit_allow, enforced_deny, allow_with_pii_conditions, role_denied, or insufficient_context. |
confidence | string | Categorical confidence: high, medium, or low |
certainty_reason | string | Explanation for the confidence level. |
reason_codes | array | Machine-readable reason codes |
conditions | array | Conditions attached to a CONDITIONAL decision |
obligations | array | Required follow-up actions |
matched_instructions | array | Same decisive matched instruction payload returned by authorize-use, including description, scope_match, and match_reason. |
matched_instruction_count | number | Number of decisive matched instructions stored with the decision. |
winning_instruction_ids | array | Instruction IDs that won the final precedence path. |
evidence | array | Policy evidence objects (same schema as authorize-use) |
trace | object | Stored decision trace with score comparisons, rules evaluated, precedence path, matched inputs, and final verdict derivation. |
columns_evaluated | array | Columns that were included in the evaluation, when available. |
request_context | object | Audit metadata that was logged with the original request |
raw_request_text | string | Original natural-language request, when the app prepared the canonical tool input |
normalized_request | object | Structured request used for the final authorization call |
normalization_meta | object | Preparation metadata such as provider, confidence, warnings, or fallback usage |
created_at | string | ISO 8601 timestamp of when the decision was made |
snapshot_status | string | Status of the governance snapshot: current (policies unchanged since decision) or stale (policies have been updated) |
Example Response
{
"status": "ok",
"data": {
"decision_id": "0133854f-c2ca-4e96-9cff-567f729935e4",
"snapshot_id": "619afce7-b970-47ca-92b4-b270689c1a6f",
"snapshot_status": "active",
"created_at": "2026-04-09T21:07:29Z",
"table_name": "TEST_DB.PUBLIC.CUSTOMERS",
"operation": "read",
"intended_use": "marketing",
"actor_role": "",
"decision": "DENY",
"decision_kind": "enforced_deny",
"confidence": "high",
"certainty_reason": "High certainty because the decision came from a definitive matched rule path.",
"summary": "Intended use \"marketing\" is explicitly prohibited by an enforced policy.",
"why_this_decision": "An enforced prohibition matched this intended use and outranked all alternatives.",
"matched_instruction_count": 1,
"matched_instructions": [
{
"instruction_id": "instr-usage-2",
"instruction_type": "usage_guidance",
"policy_id": "policy-1",
"policy_name": "Privacy Policy",
"title": "Restrict marketing use of customer data",
"description": "Customer data cannot be used for marketing outreach or third-party sharing.",
"priority": "high",
"enforcement_mode": "enforce",
"impact": "deny",
"scope_match": "table",
"rule_type": "prohibited_use",
"match_reason": "matched intended_use=marketing at table scope"
}
],
"winning_instruction_ids": ["instr-usage-2"],
"reason_codes": ["ENFORCED_PROHIBITION"],
"conditions": [],
"obligations": [],
"evidence": [
{
"instruction_id": "instr-usage-2",
"policy_id": "policy-1",
"rule_type": "prohibited_use",
"scope_match": "table",
"enforcement_mode": "enforce",
"score": 100313
}
],
"trace": {
"deny_score": 100313,
"deny_weight": 0.55,
"deny_comparable": 313,
"precedence_path": "enforced_deny > all",
"rules_evaluated": [
{
"instruction_id": "instr-usage-2",
"policy_id": "policy-1",
"rule_type": "prohibited_use",
"scope_match": "table",
"enforcement_mode": "enforce",
"score": 100313
}
],
"final_verdict_derivation": {
"decision": "DENY",
"matched_inputs": {
"operation": "read",
"intended_use": "marketing"
},
"winning_rule_ids": ["instr-usage-2"],
"summary": "Enforced prohibited_use matched intended_use=marketing."
}
}
},
"errors": []
}
SQL Examples
Explain a previous decision
CALL METATATE_APP.CORE.EXPLAIN_WHY(
OBJECT_CONSTRUCT('decision_id', 'dec_a1b2c3d4e5f6')
);
Chain: authorize then explain
-- Step 1: Get authorization decision
CALL METATATE_APP.CORE.AUTHORIZE_USE(
OBJECT_CONSTRUCT(
'table_name', 'ANALYTICS_DB.CORE.CUSTOMERS',
'operation', 'export',
'intended_use', 'Customer data sync to CRM'
)
);
-- Step 2: Copy the decision_id from the response, then explain
CALL METATATE_APP.CORE.EXPLAIN_WHY(
OBJECT_CONSTRUCT('decision_id', 'dec_a1b2c3d4e5f6')
);
JSON Request / Response (API)
Request:
{
"method": "tools/call",
"params": {
"name": "explain-why",
"arguments": {
"decision_id": "dec_a1b2c3d4e5f6"
}
}
}
Response:
{
"content": [
{
"type": "text",
"text": "{\"status\":\"ok\",\"data\":{\"decision_id\":\"0133854f-c2ca-4e96-9cff-567f729935e4\",\"snapshot_id\":\"619afce7-b970-47ca-92b4-b270689c1a6f\",\"snapshot_status\":\"active\",\"decision\":\"DENY\",\"decision_kind\":\"enforced_deny\",\"confidence\":\"high\",\"why_this_decision\":\"An enforced prohibition matched this intended use and outranked all alternatives.\",\"matched_instruction_count\":1,\"matched_instructions\":[{\"instruction_id\":\"instr-usage-2\",\"policy_name\":\"Privacy Policy\",\"title\":\"Restrict marketing use of customer data\",\"description\":\"Customer data cannot be used for marketing outreach or third-party sharing.\",\"impact\":\"deny\",\"scope_match\":\"table\",\"rule_type\":\"prohibited_use\",\"match_reason\":\"matched intended_use=marketing at table scope\"}],\"winning_instruction_ids\":[\"instr-usage-2\"],\"trace\":{\"precedence_path\":\"enforced_deny > all\",\"deny_score\":100313}},\"errors\":[]}"
}
]
}
Try it in the app
Open Metatate and navigate to the Test Tools tab. After running authorize-use, click the decision ID in the response to automatically load it into explain-why.