Skip to main content

Explain Why

Type: Procedure

Retrieve the full audit trail and evaluation trace for a previous authorization decision. Every call to authorize-use (and validate-query-context with intent parameters) produces a decision record with a unique decision_id. Use this tool to inspect the complete reasoning, policy evidence, column evaluations, and governance snapshot that informed that decision.

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

ParameterTypeRequiredDescription
decision_idstringYesThe unique decision identifier returned by authorize-use or validate-query-context. Format: dec_<alphanumeric>.

Output Schema

FieldTypeDescription
decision_idstringThe decision identifier (echoed back)
snapshot_idstringIdentifier of the governance snapshot used at evaluation time
table_namestringFully qualified table name from the original request
operationstringThe operation that was evaluated
intended_usestringThe stated intended use from the original request
actor_rolestringThe role that was evaluated
decisionstringThe decision outcome: ALLOW, DENY, CONDITIONAL, UNKNOWN
confidencenumberConfidence score from 0.0 to 1.0
reason_codesarrayMachine-readable reason codes
conditionsarrayConditions attached to a CONDITIONAL decision
obligationsarrayRequired follow-up actions
evidencearrayPolicy evidence objects (same schema as authorize-use)
tracearrayStep-by-step evaluation trace
trace[].stepintegerStep number in the evaluation sequence
trace[].actionstringWhat was evaluated (e.g., "evaluate_policy", "check_column_sensitivity", "check_jurisdiction")
trace[].policy_idstringPolicy being evaluated in this step (if applicable)
trace[].inputobjectInput data for this evaluation step
trace[].resultstringResult of this step: pass, fail, condition, skip
trace[].detailstringHuman-readable explanation of the step outcome
columns_evaluatedarrayColumns that were included in the evaluation
columns_evaluated[].columnstringColumn name
columns_evaluated[].sensitivitystringColumn sensitivity level
columns_evaluated[].is_piibooleanWhether the column is PII
columns_evaluated[].impactstringHow this column affected the decision: none, condition, deny
created_atstringISO 8601 timestamp of when the decision was made
snapshot_statusstringStatus of the governance snapshot: current (policies unchanged since decision) or stale (policies have been updated)

Example Response

{
"status": "success",
"data": {
"decision_id": "dec_a1b2c3d4e5f6",
"snapshot_id": "snap_20260312_001",
"table_name": "ANALYTICS_DB.CORE.CUSTOMERS",
"operation": "export",
"intended_use": "Sync customer records to CRM",
"actor_role": "DATA_ENGINEER",
"decision": "CONDITIONAL",
"confidence": 0.92,
"reason_codes": ["PII_MASKING_REQUIRED", "AUDIT_LOGGING_REQUIRED"],
"conditions": [
"Apply column masking on EMAIL, PHONE, SSN",
"Log this access event for compliance audit"
],
"obligations": [
"Retain access log for 90 days"
],
"evidence": [
{
"policy_id": "pol_customer_pii_001",
"policy_name": "Customer PII Protection",
"rule": "PII columns require masking for non-admin roles",
"impact": "condition"
},
{
"policy_id": "pol_audit_001",
"policy_name": "Data Access Audit Policy",
"rule": "All access to confidential tables must be logged",
"impact": "condition"
}
],
"trace": [
{
"step": 1,
"action": "resolve_table",
"policy_id": null,
"input": {"table_name": "ANALYTICS_DB.CORE.CUSTOMERS"},
"result": "pass",
"detail": "Table found in governance catalog. Sensitivity: confidential."
},
{
"step": 2,
"action": "evaluate_policy",
"policy_id": "pol_customer_pii_001",
"input": {"operation": "export", "columns": ["EMAIL", "PHONE", "SSN"]},
"result": "condition",
"detail": "Policy requires PII masking for export operations by non-admin roles."
},
{
"step": 3,
"action": "evaluate_policy",
"policy_id": "pol_audit_001",
"input": {"operation": "export", "sensitivity": "confidential"},
"result": "condition",
"detail": "Policy requires audit logging for all access to confidential tables."
},
{
"step": 4,
"action": "evaluate_policy",
"policy_id": "pol_retention_001",
"input": {"operation": "export"},
"result": "pass",
"detail": "Retention policy does not restrict export operations."
},
{
"step": 5,
"action": "aggregate_decision",
"policy_id": null,
"input": {"step_results": ["pass", "condition", "condition", "pass"]},
"result": "condition",
"detail": "Final decision: CONDITIONAL. 2 conditions must be met."
}
],
"columns_evaluated": [
{
"column": "EMAIL",
"sensitivity": "confidential",
"is_pii": true,
"impact": "condition"
},
{
"column": "PHONE",
"sensitivity": "confidential",
"is_pii": true,
"impact": "condition"
},
{
"column": "SSN",
"sensitivity": "restricted",
"is_pii": true,
"impact": "condition"
},
{
"column": "CUSTOMER_ID",
"sensitivity": "internal",
"is_pii": false,
"impact": "none"
}
],
"created_at": "2026-03-12T14:30:00Z",
"snapshot_status": "current"
},
"errors": []
}

SQL Examples

Explain a previous decision

CALL METATATE_APP.CORE.EXPLAIN_DECISION(
OBJECT_CONSTRUCT('decision_id', 'dec_a1b2c3d4e5f6')
);

Chain: authorize then explain

-- Step 1: Get authorization decision
CALL METATATE_APP.CORE.AUTHORIZE_DATA_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_DECISION(
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\":\"success\",\"data\":{\"decision_id\":\"dec_a1b2c3d4e5f6\",\"snapshot_id\":\"snap_20260312_001\",\"table_name\":\"ANALYTICS_DB.CORE.CUSTOMERS\",\"operation\":\"export\",\"intended_use\":\"Sync customer records to CRM\",\"actor_role\":\"DATA_ENGINEER\",\"decision\":\"CONDITIONAL\",\"confidence\":0.92,\"reason_codes\":[\"PII_MASKING_REQUIRED\"],\"conditions\":[\"Apply column masking on EMAIL, PHONE, SSN\"],\"obligations\":[\"Retain access log for 90 days\"],\"evidence\":[{\"policy_id\":\"pol_customer_pii_001\",\"policy_name\":\"Customer PII Protection\",\"rule\":\"PII columns require masking for non-admin roles\",\"impact\":\"condition\"}],\"trace\":[{\"step\":1,\"action\":\"resolve_table\",\"result\":\"pass\",\"detail\":\"Table found in governance catalog.\"},{\"step\":2,\"action\":\"evaluate_policy\",\"policy_id\":\"pol_customer_pii_001\",\"result\":\"condition\",\"detail\":\"PII masking required for export.\"}],\"columns_evaluated\":[{\"column\":\"EMAIL\",\"sensitivity\":\"confidential\",\"is_pii\":true,\"impact\":\"condition\"}],\"created_at\":\"2026-03-12T14:30:00Z\",\"snapshot_status\":\"current\"},\"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.