Snowflake Cortex Analyst lets business users ask questions in natural language and have the service automatically generate and run SQL queries against structured data. It uses a semantic model (defined in YAML) to understand the underlying table structure and business logic, producing accurate SQL. This article walks through how to design the semantic model, how the conversion flow works, and how to set up permissions.
Cortex Analyst is a managed Snowflake service that takes a natural-language question and generates a SQL query based on a semantic model. Traditional BI tools require a dashboard designer to predefine queries up front; with Cortex Analyst, end users simply ask free-form questions and get answers back.
The generated SQL is restricted to SELECT statements, so there is no risk of data modification. Snowflake's RBAC is also enforced, so data the user's role cannot access never appears in the results.
[Business user]
│ "What was last month's revenue by product category?"
▼
[Cortex Analyst API]
│
├─ 1. Load the semantic model (YAML)
│ └─ learn the table structure, column meanings and formulas
│
├─ 2. The LLM parses the natural language
│ └─ understands the intent and maps it to tables and columns
│
├─ 3. Generate the SQL query (SELECT only)
│ └─ build joins and aggregations per the semantic model
│
└─ 4. Return the SQL (run it automatically or after user confirmation)
└─ the result is returned as JSON in the API responseSemantic models are written in YAML and placed on a Snowflake stage. The model defines logical tables, dimensions, measures, time dimensions, and relationships.
# semantic_model.yaml
name: sales_analytics
description: "Semantic model for e-commerce revenue analysis"
tables:
- name: orders
base_table:
database: ANALYTICS_DB
schema: PUBLIC
table: FACT_ORDERS
description: "Order transaction table"
dimensions:
- name: order_id
expr: ORDER_ID
description: "Unique order identifier"
data_type: VARCHAR
- name: product_category
expr: PRODUCT_CATEGORY
description: "Product category (electronics, food, apparel, and so on)"
data_type: VARCHAR
time_dimensions:
- name: order_date
expr: ORDER_DATE
description: "Order date"
data_type: DATE
measures:
- name: total_revenue
expr: SUM(ORDER_AMOUNT)
description: "Total revenue"
data_type: NUMBER
- name: order_count
expr: COUNT(DISTINCT ORDER_ID)
description: "Order count"
data_type: NUMBER
- name: avg_order_value
expr: AVG(ORDER_AMOUNT)
description: "Average order value"
data_type: NUMBER
- name: customers
base_table:
database: ANALYTICS_DB
schema: PUBLIC
table: DIM_CUSTOMERS
description: "Customer master"
dimensions:
- name: customer_id
expr: CUSTOMER_ID
description: "Customer ID"
data_type: VARCHAR
- name: region
expr: REGION
description: "Customer region"
data_type: VARCHAR
relationships:
- name: order_customer
left_table: orders
right_table: customers
join_type: LEFT
relationship_columns:
- left_column: CUSTOMER_ID
right_column: CUSTOMER_ID
verified_queries:
- name: "Monthly revenue by category"
question: "Show me monthly revenue by product category"
sql: |
SELECT
DATE_TRUNC('MONTH', o.ORDER_DATE) AS month,
o.PRODUCT_CATEGORY,
SUM(o.ORDER_AMOUNT) AS total_revenue
FROM ANALYTICS_DB.PUBLIC.FACT_ORDERS o
GROUP BY 1, 2
ORDER BY 1, 3 DESC| Element | Role | Required |
|---|---|---|
| tables | Defines the tables available for queries | Yes |
| dimensions | Columns used for grouping and filtering | Yes |
| time_dimensions | Time-based columns (dates and timestamps) | Recommended |
| measures | Aggregation expressions (SUM, COUNT, AVG, etc.) | Yes |
| relationships | JOIN definitions between tables | Required for multi-table models |
| verified_queries | Verified question-SQL pairs; few-shot examples that improve accuracy | Recommended |
| description | Natural-language descriptions of tables and columns | Critical for accuracy |
Cortex Analyst can be invoked via the REST API or the Python SDK. You can also embed it in a Streamlit app inside Snowsight.
# Example call from the Python SDK
import json
from snowflake.core import Root
root = Root(session)
analyst = root.databases["ANALYTICS_DB"].schemas["PUBLIC"].cortex_analyst
response = analyst.send_message(
semantic_model_file="@my_stage/semantic_model.yaml",
messages=[
{"role": "user", "content": "Show me last month's top 5 regions by revenue"}
]
)
# Pull the SQL and the result out of the response
for item in response.message.content:
if item.type == "sql":
print("Generated SQL:", item.statement)
elif item.type == "text":
print("Explanation:", item.text)Cortex Analyst permissions follow Snowflake's standard RBAC model.
| Operation | Required Privilege |
|---|---|
| Calling the Cortex Analyst API | SNOWFLAKE.CORTEX_USER database role |
| Reading the semantic model YAML | READ on the stage |
| Target tables for the generated SQL | SELECT on the tables |
| Query execution | USAGE on the warehouse |
-- Example grants for Cortex Analyst users
GRANT DATABASE ROLE SNOWFLAKE.CORTEX_USER TO ROLE analyst_role;
GRANT USAGE ON DATABASE analytics_db TO ROLE analyst_role;
GRANT USAGE ON SCHEMA analytics_db.public TO ROLE analyst_role;
GRANT SELECT ON ALL TABLES IN SCHEMA analytics_db.public TO ROLE analyst_role;
GRANT READ ON STAGE analytics_db.public.my_stage TO ROLE analyst_role;
GRANT USAGE ON WAREHOUSE analyst_wh TO ROLE analyst_role;Registering question-SQL pairs in the verified_queries section of the semantic model improves SQL generation accuracy when similar questions come in. This is a few-shot prompting approach and is particularly effective when you have business-specific terminology or logic.
Cortex Analyst
Question 1
Which statement about the Cortex Analyst semantic model is correct?
Correct answer: B
Cortex Analyst semantic models are placed on a stage as YAML files and define tables, dimensions, measures, and relationships. A is wrong because the format is YAML on a stage, not JSON in a table. C is wrong because Cortex Analyst cannot be used without a semantic model. D is wrong because verified_queries is recommended but not required.
Where is the Cortex Analyst semantic model stored?
Semantic models are stored as YAML files on a Snowflake stage. You reference them via a stage path such as @my_stage/semantic_model.yaml, and Cortex Analyst uses the file to understand table structure, column semantics, and calculation logic before generating SQL. Git repository integration is also available for version control.
Is the SQL generated by Cortex Analyst safe?
Cortex Analyst only generates SELECT statements — it never produces INSERT/UPDATE/DELETE/DDL. The user's role permissions are also enforced at execution time, so it cannot touch tables or columns the user lacks access to. You can further restrict the query surface by limiting which tables are exposed in the semantic model.
When should I use Cortex Analyst vs. Cortex Search?
Cortex Analyst specializes in natural-language-to-SQL translation over structured data. It fits use cases like business users asking analytical questions such as "What are the top 10 products by sales last month?" Cortex Search, by contrast, specializes in hybrid search over unstructured text and is used for document search or as a RAG retriever.
Practice with certification-focused question sets
Try free questionsNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
Snowflake Certifications: All 11 Exams Explained (2026)
Every SnowPro certification — Associate, Core, Specialty, Ad...
Snowflake Exam Difficulty Ranking: All 11 Certs Compared (2026)
All 11 SnowPro exams ranked by difficulty with study-time es...
Snowflake Study Guide: Fastest Pass Route by Exam (2026)
How to pass SnowPro certifications efficiently — official ma...
SnowPro Core (COF-C03): Complete Exam Guide (2026)
Pass the SnowPro Core exam — six domains, scope, sample ques...
SnowPro Associate Platform (SOL-C01): Complete Guide (2026)
The entry-level SnowPro Associate exam — scope, weighting, s...