A pre-action call inside the tool itself
Cortex Agents call custom tools that are Snowflake functions or stored procedures. Make the Veridect call the first thing the tool does: a Python function with an External Access Integration asks Veridect, and anything other than a greenlight returns the verdict and the record id instead of doing the work — the agent sees why, and so does the ledger.
Fail-closed by construction: the function returns {"verdict":"unavailable"} on a non-200, a timeout or a malformed body, and the procedure that calls it does its work only on a parsed greenlight. Egress is pinned by the network rule to one host; the API key lives in a Snowflake SECRET bound to the integration, never in code. This is the function Live 04 runs, from inside an account, below.
-- 1) once (ACCOUNTADMIN): egress to one host, the key as a secret, one integration binding them CREATE NETWORK RULE governance.veridect_egress MODE = EGRESS TYPE = HOST_PORT VALUE_LIST = ('<your-veridect-host>:443'); CREATE SECRET governance.veridect_key TYPE = GENERIC_STRING SECRET_STRING = '<VERIDECT_API_KEY>'; CREATE EXTERNAL ACCESS INTEGRATION veridect_eai ALLOWED_NETWORK_RULES = (governance.veridect_egress) ALLOWED_AUTHENTICATION_SECRETS = (governance.veridect_key) ENABLED = TRUE; -- 2) the judgment, as a function in your own schema CREATE OR REPLACE FUNCTION governance.veridect_pre_action(payload VARIANT) RETURNS VARIANT LANGUAGE PYTHON RUNTIME_VERSION = '3.11' HANDLER = 'judge' EXTERNAL_ACCESS_INTEGRATIONS = (veridect_eai) SECRETS = ('key' = governance.veridect_key) PACKAGES = ('requests') -- carries its own CA bundle; stdlib urllib cannot verify TLS in the UDF sandbox AS $$ import requests, _snowflake def judge(payload): try: r = requests.post('https://<your-veridect-host>/api/ai/consensus/pre-action', json=payload, timeout=60, headers={'Authorization': 'Bearer ' + _snowflake.get_generic_secret_string('key')}) d = r.json() if r.status_code == 200 else {} except Exception: d = {} # network, timeout, parse: all stay closed return d if d.get('verdict') else {'verdict': 'unavailable'} # closed until proven open $$;