CREATE OR REPLACE PROCEDURE EXA_INTEGRATION.TOOLS.EXA_SEARCH(
query STRING,
num_results INTEGER DEFAULT 10,
search_type STRING DEFAULT 'auto',
category STRING DEFAULT NULL,
include_domains STRING DEFAULT NULL,
exclude_domains STRING DEFAULT NULL,
start_published_date STRING DEFAULT NULL,
end_published_date STRING DEFAULT NULL,
include_text STRING DEFAULT NULL,
get_contents BOOLEAN DEFAULT TRUE
)
RETURNS STRING
LANGUAGE PYTHON
RUNTIME_VERSION = '3.10'
PACKAGES = ('requests', 'snowflake-snowpark-python')
EXTERNAL_ACCESS_INTEGRATIONS = (EXA_API_ACCESS)
SECRETS = ('cred' = exa_integration.tools.exa_api_key)
HANDLER = 'main'
AS
$$
import _snowflake
import requests
import json
def main(session, query, num_results, search_type, category, include_domains,
exclude_domains, start_published_date, end_published_date,
include_text, get_contents):
api_key = _snowflake.get_generic_secret_string('cred')
url = "https://api.exa.ai/search"
body = {
"query": query,
"numResults": num_results,
"type": search_type,
}
if category:
body["category"] = category
if include_domains:
body["includeDomains"] = [d.strip() for d in include_domains.split(",")]
if exclude_domains:
body["excludeDomains"] = [d.strip() for d in exclude_domains.split(",")]
if start_published_date:
body["startPublishedDate"] = start_published_date
if end_published_date:
body["endPublishedDate"] = end_published_date
if include_text:
body["includeText"] = [include_text]
if get_contents:
body["contents"] = {
"text": {"maxCharacters": 3000},
"highlights": True,
"summary": True
}
headers = {
"x-api-key": api_key,
"Content-Type": "application/json",
"x-exa-integration": "snowflake-cortex-agent"
}
try:
resp = requests.post(url, json=body, headers=headers, timeout=30)
resp.raise_for_status()
data = resp.json()
results = []
for r in data.get("results", []):
result = {
"title": r.get("title", ""),
"url": r.get("url", ""),
"score": r.get("score"),
"publishedDate": r.get("publishedDate", ""),
}
if get_contents:
result["summary"] = r.get("summary", "")
result["highlights"] = r.get("highlights", [])
result["text"] = (r.get("text", "") or "")[:2000]
results.append(result)
return json.dumps({
"query": query,
"numResults": len(results),
"results": results
})
except requests.exceptions.HTTPError as e:
return json.dumps({"error": str(e), "status_code": e.response.status_code,
"detail": e.response.text})
except Exception as e:
return json.dumps({"error": str(e)})
$$;
GRANT USAGE ON PROCEDURE EXA_INTEGRATION.TOOLS.EXA_SEARCH(
STRING, INTEGER, STRING, STRING, STRING, STRING, STRING, STRING, STRING, BOOLEAN
) TO ROLE exa_agent_role;