<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tsubasa Kanno</title>
    <description>The latest articles on DEV Community by Tsubasa Kanno (@tsubasa_tech).</description>
    <link>https://dev.to/tsubasa_tech</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2070831%2F23d09b26-d96e-4ae8-b223-2886d617e257.jpg</url>
      <title>DEV Community: Tsubasa Kanno</title>
      <link>https://dev.to/tsubasa_tech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tsubasa_tech"/>
    <language>en</language>
    <item>
      <title>I Asked Snowflake to Analyze Data by Voice from My Even G2 Smart Glasses</title>
      <dc:creator>Tsubasa Kanno</dc:creator>
      <pubDate>Sun, 11 Oct 2026 03:34:40 +0000</pubDate>
      <link>https://dev.to/tsubasa_tech/i-asked-snowflake-to-analyze-data-by-voice-from-my-even-g2-smart-glasses-2kpi</link>
      <guid>https://dev.to/tsubasa_tech/i-asked-snowflake-to-analyze-data-by-voice-from-my-even-g2-smart-glasses-2kpi</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I recently got my hands on the &lt;strong&gt;Even G2&lt;/strong&gt; smart glasses!&lt;/p&gt;

&lt;p&gt;Plenty of companies make smart glasses these days, but I'd personally felt it was still a little early to jump in. Then the Even G2 came along with specs that looked good enough for everyday use, and I ended up buying a pair on impulse.&lt;/p&gt;

&lt;p&gt;After using them for a while, an idea hit me: &lt;strong&gt;"Wouldn't it be incredibly handy if I could work with my Snowflake database by voice, right from these glasses?"&lt;/strong&gt; Imagine asking "How are sales this month?" in the middle of a meeting, or whenever the thought crosses your mind, and seeing the answer appear right in front of your eyes. Just picturing it is exciting, right? So I went ahead and tried it!&lt;/p&gt;

&lt;p&gt;This one is a side story with a slightly different feel from my usual feature introductions. I'll set things up so I can ask Snowflake's &lt;strong&gt;Cortex Agents (Coding Agent)&lt;/strong&gt; for data analysis by voice from the Even G2, by way of AWS Lambda. Think of it as a little break, and I'd be happy if you read it in a relaxed mood.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi0j9kvuztgu2gb4ner00.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi0j9kvuztgu2gb4ner00.jpg" alt="The Even G2 smart glasses" width="800" height="602"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The Even G2 smart glasses&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article reflects my personal views and does not represent Snowflake's official position.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: (October 2026) Some features introduced in this article are in development or Preview. They may change significantly in future updates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: In particular, Cortex AI Gateway is a Preview feature, available to accounts in AWS commercial regions (with some exceptions). Also, the request body format sent by the Even G2's Agent Configuration isn't covered in the official documentation; what I describe here is based on community analysis.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  What is Even G2?
&lt;/h2&gt;

&lt;p&gt;Even G2 is a pair of smart glasses with a built-in display from Even Realities. The official site describes them as "everyday," and they're designed to be worn all day long. Green text appears to float inside the lenses, so you can check answers to what you say, notifications, translations, and navigation at the edge of your vision. There are also features such as conversation support (Conversate) and a teleprompter that shows your talk script.&lt;/p&gt;

&lt;p&gt;The display is visible only to you, so you can check your notes mid-conversation without the other person really noticing. That's a nice touch (the official Conversate help also describes it as "visible only to the wearer"). On top of that, if you pair the glasses with the &lt;strong&gt;R1&lt;/strong&gt; ring, you can switch screens with just a tap or a scroll of your fingertip, without touching the glasses at all. It feels more natural than I expected, and it's really handy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.evenrealities.com/smart-glasses" rel="noopener noreferrer"&gt;Even G2 official site&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What I like most is that there's &lt;strong&gt;deliberately no&lt;/strong&gt; camera or speaker. The official site says "Camera-free. By design.", and the developer documentation states "No camera, no speaker on the glasses." You won't make people around you worry about being recorded. And at an official 36 g, they weigh about the same as regular glasses, so wearing them in the office doesn't feel odd at all. If anything, I think they look a little stylish.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hub.evenrealities.com/docs/get-started/overview" rel="noopener noreferrer"&gt;Overview (Even Hub Documentation)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another interesting point is how much room there is for customization. The Even G2 comes with a standard AI assistant (Even AI) that you call up with "Hey Even." But once you sign in to Even Hub, the developer platform, a setting called &lt;strong&gt;Agent Configuration&lt;/strong&gt; appears in the Even app. It lets you &lt;strong&gt;point Even AI's requests at an endpoint of your own&lt;/strong&gt;. The official help even includes a tutorial on connecting to an agent running on your own PC.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://support.evenrealities.com/hc/en-us/articles/16280926743695-Tutorial-Bridging-G2-to-OpenClaw-Bring-Your-Own-Agent" rel="noopener noreferrer"&gt;Tutorial: Bridging G2 to OpenClaw - Bring Your Own Agent&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I found this setting, it clicked right away: "Then couldn't I connect this to Snowflake, too!?"&lt;/p&gt;
&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;The setup is pretty simple. All it takes is one small Lambda function sitting between the Even app and Snowflake as a relay server.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Even G2&lt;/strong&gt;: connects to the phone over Bluetooth&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Even app on the phone&lt;/strong&gt;: converts speech to text, then sends it to Lambda over HTTPS (with the PAT as a Bearer token)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Lambda (function URL)&lt;/strong&gt;: forwards the request to Cortex Agents via &lt;code&gt;agent:run&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snowflake Cortex Agents (Coding Agent)&lt;/strong&gt;: runs read-only SQL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snowflake tables&lt;/strong&gt;: the data being analyzed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As the list shows, Lambda works as a relay server. The Even app sends requests in the OpenAI Chat Completions format, which doesn't match the request format of Cortex Agents' &lt;code&gt;agent:run&lt;/code&gt;. The model name it sends is also fixed (this part comes from community analysis), so the request can't be forwarded as-is. Instead, Lambda reshapes the request into the Cortex Agents format, forwards it, and turns the answer back into a form the glasses can display. Lambda itself never reads any table data.&lt;/p&gt;

&lt;p&gt;For authentication, I use a Snowflake &lt;strong&gt;programmatic access token (PAT)&lt;/strong&gt;. You enter the PAT in the Even app, and Lambda passes it straight through to Snowflake. Lambda never stores the PAT or writes it to logs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: For this test, I've exposed the Lambda function URL without authentication (Snowflake still authenticates the PAT). If you connect to a production database, always put Amazon API Gateway in front and add security layers such as authentication, a WAF (Web Application Firewall), and rate limiting.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  What is Coding Agent?
&lt;/h2&gt;

&lt;p&gt;The star of this article is &lt;strong&gt;Coding Agent&lt;/strong&gt; in Cortex Agents. Coding Agent became generally available (GA) on August 26, 2026. It brings the same coding capabilities as Snowflake CoCo (formerly Cortex Code) to your own apps through the Cortex Agents REST API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-coding-agent" rel="noopener noreferrer"&gt;Coding Agent (Snowflake Documentation)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's surprisingly easy to use: just specify &lt;code&gt;code_toolset_all&lt;/code&gt; as a tool when you call Cortex Agents' &lt;code&gt;agent:run&lt;/code&gt;. You don't even need to create an agent object beforehand. With that alone, the agent builds its answer inside a Snowflake-managed sandbox, using tools for running SQL, web search, file operations, and more.&lt;/p&gt;

&lt;p&gt;Even better, &lt;strong&gt;SQL is limited to operations that read tables (SELECT and SHOW)&lt;/strong&gt;. Here's how the official documentation describes &lt;code&gt;snowflake_sql_execute&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Execute SQL against Snowflake (read-only: SELECT and SHOW commands; can write to stages)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Writing to stages is the one exception. The role I create in this article has no stage privileges, though, so it can read the tables but can't change them.&lt;/p&gt;

&lt;p&gt;This "read-only" constraint is exactly why I think it pairs so well with smart glasses. It's hard to carefully review the SQL being run from a pair of glasses. Knowing the data can't be modified lets me talk to it with peace of mind.&lt;/p&gt;

&lt;p&gt;On top of that, the SQL the agent runs &lt;strong&gt;only works within the privileges of a Snowflake role&lt;/strong&gt;. If you restrict the PAT to a specific role when you create it, the agent's SQL runs with that role. Even though you can now ask questions casually by voice, Snowflake's governance still applies, so you can keep what's visible tightly scoped by role!&lt;/p&gt;

What I actually verified

The official documentation says Cortex Agents determines privileges based on the user's default role. So I tested it with a user whose default role is ACCOUNTADMIN, using a PAT restricted to PUBLIC. All of the agent's SQL ran as PUBLIC, and queries against a view that PUBLIC had no privileges on were rejected (confirmed in `QUERY_HISTORY`).

When I tried switching to a different role, the request was rejected with the following error:



```
Role '...' specified in the connect string is not granted to this user, or is not permitted for the credentials being used.
```




&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;From here, I'll walk through the steps to get it running, one at a time.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Create a Read-Only Role for the G2
&lt;/h3&gt;

&lt;p&gt;First, create a dedicated role for the glasses and allow read access to the schema you want to analyze, and nothing else. I'm using my own sample e-commerce data in &lt;code&gt;GLACIERSTYLE_DB.EC_ANALYTICS_SCHEMA&lt;/code&gt;, so replace it with the database and schema you want to analyze.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;USE&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;ACCOUNTADMIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Role used by Even G2 for read-only access&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;G2_READER&lt;/span&gt; &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Read-only role for Even G2'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Allow read access to the schema you want to analyze, and nothing more&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;USAGE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;GLACIERSTYLE_DB&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;G2_READER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;USAGE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;GLACIERSTYLE_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EC_ANALYTICS_SCHEMA&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;G2_READER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="n"&gt;TABLES&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;GLACIERSTYLE_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EC_ANALYTICS_SCHEMA&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;G2_READER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Warehouse for running SQL, and the privilege to use Cortex Agents&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;USAGE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;WAREHOUSE&lt;/span&gt; &lt;span class="n"&gt;COMPUTE_WH&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;G2_READER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;SNOWFLAKE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CORTEX_AGENT_USER&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;G2_READER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Grant the role to your user and set a default warehouse&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;G2_READER&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;USER&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;USER&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_WAREHOUSE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;COMPUTE_WH&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;SNOWFLAKE.CORTEX_AGENT_USER&lt;/code&gt; is a database role that grants access to Cortex Agents only. You can also use &lt;code&gt;SNOWFLAKE.CORTEX_USER&lt;/code&gt;, which covers all the Cortex AI features. Also, Cortex Agents runs SQL with the user's &lt;strong&gt;default warehouse&lt;/strong&gt;, so make sure your user has one set.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Create a Role-Restricted PAT
&lt;/h3&gt;

&lt;p&gt;Next, create the PAT you'll enter in the Even app. The key points are to restrict it to the role above with &lt;code&gt;ROLE_RESTRICTION&lt;/code&gt;, and to keep the expiration short (7 days here).&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;USER&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="n"&gt;PROGRAMMATIC&lt;/span&gt; &lt;span class="k"&gt;ACCESS&lt;/span&gt; &lt;span class="n"&gt;TOKEN&lt;/span&gt; &lt;span class="n"&gt;g2_even_ai&lt;/span&gt;
  &lt;span class="n"&gt;ROLE_RESTRICTION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'G2_READER'&lt;/span&gt;
  &lt;span class="n"&gt;DAYS_TO_EXPIRY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;
  &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Even G2 -&amp;gt; Cortex Agents relay'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The token is shown only once, so enter it directly into the Even app.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: By default, a PAT can only be used for authentication by users who have a network policy. On top of that, Lambda's source IP address isn't fixed, so a network policy that only allows your home or office IP will block calls from Lambda. If you're only trying it out briefly, you can temporarily lift the network policy requirement by specifying &lt;code&gt;MINS_TO_BYPASS_NETWORK_POLICY_REQUIREMENT&lt;/code&gt; when you create the PAT (up to 1 day, and not recommended in the official docs). For production, fix Lambda's source IP with something like a NAT gateway, and allow that IP in your network policy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/programmatic-access-tokens" rel="noopener noreferrer"&gt;Using programmatic access tokens (Snowflake Documentation)&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Create the Lambda Function
&lt;/h3&gt;

&lt;p&gt;Now for the relay Lambda function itself. It fits in about 90 lines using only the Python standard library. The code is a bit long, so expand the section below to see it.&lt;/p&gt;

Lambda function code (lambda_function.py)



```python
"""A minimal relay from Even G2 (Even AI's Agent Configuration) to Snowflake's Coding Agent.
Runs behind an AWS Lambda function URL. Standard library only; the PAT is forwarded as-is and never stored."""
import base64
import json
import os
import urllib.error
import urllib.request

SNOWFLAKE_HOST = os.environ["SNOWFLAKE_HOST"]  # e.g. myorg-myaccount.snowflakecomputing.com
PATH_TOKEN = os.environ["PATH_TOKEN"]          # Marker appended to the end of the URL (any long string)
MODEL = os.environ.get("MODEL", "auto")  # With auto, Snowflake picks the model
# Telling the agent where the data lives saves it from searching through every database
DATA_LOCATION = os.environ.get("DATA_LOCATION", "")  # e.g. GLACIERSTYLE_DB.EC_ANALYTICS_SCHEMA

SYSTEM_PROMPT = (
    "You are an assistant whose answers are shown on smart glasses. "
    "Answer in the same language as the question, lead with the conclusion, and use plain text of about 70 words or fewer. "
    "Do not use headings, bullet points, tables, or URLs. "
    "Use read-only SQL when you need Snowflake data, and web search when you need up-to-date information. "
) + (f"The data is in {DATA_LOCATION}." if DATA_LOCATION else "")
# Guidance on which tools to use. It isn't enforced, so apply the real restriction through the PAT's role
ORCHESTRATION_PROMPT = "Use only the snowflake_sql_execute and web_search tools."


def reply(text):
    """Return an OpenAI-style response the Even app can read. The content is what appears on the glasses."""
    body = {
        "object": "chat.completion",
        "choices": [{"index": 0, "message": {"role": "assistant", "content": text[:350]},
                     "finish_reason": "stop"}],
    }
    return {"statusCode": 200, "headers": {"Content-Type": "application/json"},
            "body": json.dumps(body, ensure_ascii=False)}


def lambda_handler(event, context):
    # Reject requests to URLs without the marker
    if event.get("rawPath", "").strip("/") != PATH_TOKEN:
        return {"statusCode": 404, "body": "not found"}
    auth = (event.get("headers") or {}).get("authorization", "")
    if not auth.startswith("Bearer "):
        return {"statusCode": 401, "body": "missing token"}

    raw = event.get("body") or "{}"
    if event.get("isBase64Encoded"):
        raw = base64.b64decode(raw).decode("utf-8")
    try:
        messages = json.loads(raw).get("messages") or []
        question = next(m["content"] for m in reversed(messages) if m.get("role") == "user")
    except (ValueError, AttributeError, KeyError, StopIteration):
        return reply("Sorry, I couldn't catch that. Please try asking again.")
    if not isinstance(question, str) or not question.strip():
        return reply("Sorry, I couldn't catch that. Please try asking again.")

    # Even always sends a fixed model name, so reshape the request into the Coding Agent format here
    payload = {
        "stream": False,
        "models": {"orchestration": MODEL},
        "instructions": {"system": SYSTEM_PROMPT, "orchestration": ORCHESTRATION_PROMPT},
        "messages": [{"role": "user", "content": [{"type": "text", "text": question}]}],
        "tools": [{"tool_spec": {"type": "code_toolset_all", "name": "code_toolset_all"}}],
        # The glasses can't approve tool use, so let the agent use tools without confirmation
        "tool_resources": {"code_toolset_all": {"permission_policy": {"type": "always_allow"}}},
    }
    req = urllib.request.Request(
        f"https://{SNOWFLAKE_HOST}/api/v2/cortex/agent:run",
        data=json.dumps(payload, ensure_ascii=False).encode("utf-8"),
        headers={"Authorization": auth, "Content-Type": "application/json", "Accept": "application/json"},
        method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=25) as resp:
            data = json.load(resp)
    except urllib.error.HTTPError as e:
        return reply(f"An error occurred in Snowflake ({e.code}).")
    except Exception:  # Timeouts, connection failures, etc.
        return reply("Couldn't get a response from Snowflake. Please try again.")

    # content is ordered tool_use -&amp;gt; tool_result -&amp;gt; text. The text after the last tool is the answer
    answer = []
    for item in data.get("content") or []:
        if item.get("type") == "text":
            answer.append(item.get("text", ""))
        elif item.get("type") in ("tool_use", "tool_result"):
            answer = []
    return reply("\n".join(answer).strip() or "The answer came back empty. Please try rephrasing your question.")
```





&lt;p&gt;All it does is pull out the utterance sent from Even, send it to &lt;code&gt;agent:run&lt;/code&gt; with &lt;code&gt;code_toolset_all&lt;/code&gt; attached, and wrap the answer in the OpenAI format before returning it. There are three key settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Set &lt;code&gt;permission_policy&lt;/code&gt; to &lt;code&gt;always_allow&lt;/code&gt;&lt;/strong&gt;: By default, Coding Agent asks the user for approval before using tools that change state (such as bash or snowflake_sql_execute). You can't approve anything from the glasses, so I've set it to run without confirmation (I'll cover the caveats of this setting later)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask for "short plain text for the glasses" in the system prompt&lt;/strong&gt;: The glasses can only show so much text, so I ask for answers of about 70 words or fewer, with no headings or tables (just in case, the code also cuts the returned string at 350 characters)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tell the agent where the data lives&lt;/strong&gt;: If you set &lt;code&gt;DATA_LOCATION&lt;/code&gt;, the agent doesn't have to search through every database from scratch, which greatly shortens the time it takes to answer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system prompt in particular comes down to personal taste, so please customize it and find an answer style that's easy to read on the glasses.&lt;/p&gt;

&lt;p&gt;In the AWS Management Console, create the function with the following settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runtime: Python 3.13&lt;/li&gt;
&lt;li&gt;Environment variables: &lt;code&gt;SNOWFLAKE_HOST&lt;/code&gt; (your account's host name), &lt;code&gt;PATH_TOKEN&lt;/code&gt; (a long, hard-to-guess string), &lt;code&gt;DATA_LOCATION&lt;/code&gt; (the schema you want to analyze), and optionally &lt;code&gt;MODEL&lt;/code&gt; (defaults to &lt;code&gt;auto&lt;/code&gt; if omitted; the examples in this article specify &lt;code&gt;claude-sonnet-5-5&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Timeout: 30 seconds (the default of 3 seconds isn't enough)&lt;/li&gt;
&lt;li&gt;Function URL: create it with the auth type &lt;code&gt;NONE&lt;/code&gt; (as mentioned earlier, put API Gateway or something similar in front for production)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  4. Configure the Even App
&lt;/h3&gt;

&lt;p&gt;Finally, set the destination in the Even app on your phone.&lt;/p&gt;

&lt;p&gt;As I mentioned earlier, though, Agent Configuration only shows up for Even Hub developers. So first, enable the developer features with the steps below. The web version of Even Hub has no sign-up screen, so create your account in the Even app beforehand.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sign in to the web version of Even Hub (&lt;code&gt;hub.evenrealities.com/login&lt;/code&gt;) with the same account you use in the Even app&lt;/li&gt;
&lt;li&gt;Quit the Even app once (close it from the app switcher instead of just sending it to the background), then reopen it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;According to the current Even Hub documentation, your account switches to developer mode as soon as you sign in, and the developer menu appears when you reopen the app. However, the tutorial I mentioned earlier also says the setting appears once you're approved. If it still doesn't show up after reopening the app, check your Even Hub developer registration status, too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hub.evenrealities.com/docs/get-started/quickstart/hardware" rel="noopener noreferrer"&gt;Hardware - Enable Developer Mode (Even Hub Documentation)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once Agent Configuration appears, set it up as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Even app, open Settings → Even AI → Agent Configuration&lt;/li&gt;
&lt;li&gt;Enter &lt;code&gt;https://&amp;lt;function URL host&amp;gt;/&amp;lt;PATH_TOKEN&amp;gt;&lt;/code&gt; as the Endpoint (unlike the example in the official tutorial, don't add &lt;code&gt;/v1/chat/completions&lt;/code&gt; at the end)&lt;/li&gt;
&lt;li&gt;Enter the PAT you created in step 2 as the API Key&lt;/li&gt;
&lt;li&gt;Tap Save &amp;amp; Activate&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqskk0gssv0557ogin8sd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqskk0gssv0557ogin8sd.png" alt="The Agent Configuration screen in the Even app" width="800" height="680"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The Agent Configuration screen in the Even app&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And that's it for the setup!&lt;/p&gt;
&lt;h2&gt;
  
  
  Talking to It
&lt;/h2&gt;

&lt;p&gt;Now, let's ask Snowflake for some analysis. Say "Hey Even" to the glasses and then ask your question, and the Even app converts it to text and sends it to Lambda. And when it's hard to speak out loud, like in a meeting or on a train, &lt;strong&gt;you can also type your question in the Even app on your phone&lt;/strong&gt;. Either way, the answer shows up on the glasses, which really widens the range of situations where you can use it.&lt;/p&gt;

&lt;p&gt;For these examples, I'm asking about sample e-commerce data (500 orders covering all of 2024), with the &lt;code&gt;MODEL&lt;/code&gt; environment variable set to &lt;code&gt;claude-sonnet-5-5&lt;/code&gt; (I'll explain why I picked this model later).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The smart glasses display was hard to photograph, so in this article I show what appears on the glasses in code blocks. The text is the agent's answer exactly as it came back.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First, let's ask for total sales. When I asked "What were Glacier Style's total sales in 2024?", here's the answer I got:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Total sales for 2024 were about ¥97.97 million,
counting only completed orders (excluding
cancellations and returns). Including cancellations
(about ¥9.53 million) and returns (about ¥3.21
million), all orders totaled about ¥110.70 million.
Amounts are tax-inclusive order totals, and I've
assumed the currency is yen.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Amazingly, without any instructions from me, it checked the order statuses and gave me both totals: one without cancellations and returns, and one with them!&lt;/p&gt;

&lt;p&gt;Behind the scenes, it checked the list of tables and columns and then ran the SQL below. To check the answer, I ran the same SQL in Snowsight. It matched exactly: completed orders totaled ¥97,970,139.81 (456 orders). (Note that "tax-inclusive" is the agent's own guess; the column descriptions don't say so.)&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;ORDER_STATUS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TOTAL_AMOUNT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;GLACIERSTYLE_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EC_ANALYTICS_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FACT_ORDERS&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nb"&gt;YEAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ORDER_DATETIME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2024&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;ORDER_STATUS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ORDER_STATUS&lt;/th&gt;
&lt;th&gt;N&lt;/th&gt;
&lt;th&gt;TOTAL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;completed&lt;/td&gt;
&lt;td&gt;456&lt;/td&gt;
&lt;td&gt;97970139.81&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cancelled&lt;/td&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;td&gt;9525519.80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;returned&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;3212132.95&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Next, I asked for a month-by-month comparison: "What were Glacier Style's best and worst months for sales in 2024?"&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Based on completed orders, the best month for sales
in 2024 was September at about ¥16.28 million, and
the worst was April at about ¥3.92 million.
Cancellations and returns are excluded. Even with
all statuses included, the best month is still
September and the worst is still April.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I also asked about the breakdown by membership tier: "How many Glacier Style customers are in each membership tier, counted by customer ID?"&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;By membership tier, there are 31 Silver customers,
26 each for Gold and Standard, and 17 Platinum.
That's 100 customers in total, counted with
duplicate customer IDs removed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The customer master in this sample data contains two rows for each customer, but it properly removed the duplicate customer IDs before counting! Both the monthly and the membership tier answers matched the correct values.&lt;/p&gt;

&lt;p&gt;Each answer took about 10–15 seconds to come back. That's a bit of a pause for a conversation, but it feels a lot like asking someone to "look that up for me," and I found it plenty practical.&lt;/p&gt;
&lt;h3&gt;
  
  
  It Can Search the Web, Too
&lt;/h3&gt;

&lt;p&gt;Coding Agent's tools include web search, so you can also ask about information outside Snowflake. The first time I tried, though, it answered "How much does the Even G2 weigh?" from the model's own knowledge without using web search. So I added one sentence to the system prompt: "Use web search when you need up-to-date information." After that, it started using web search properly (the Lambda code above already includes this sentence).&lt;/p&gt;

&lt;p&gt;When I asked "How many grams does the Even Realities Even G2 weigh?", here's what came back:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The Even G2's official weight is about 36 g. In
hands-on measurements, MoguLive got 37.7 g, and AI
Watch got 44.4 g with prescription lenses. The
weight varies a little by lens and by unit.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The official 36 g matches the official site. This answer came back in about 7 seconds, a bit faster than the questions that aggregate data. It's great to be able to ask about both your company's data and the wider world from the same "Hey Even"!&lt;/p&gt;
&lt;h2&gt;
  
  
  Going Further: Combining Semantic Views and Cortex Search
&lt;/h2&gt;

&lt;p&gt;So far, I've had Coding Agent build its SQL from scratch. With Cortex Agents, you can also pick the tools you give the agent to suit your purpose. This will be familiar to anyone already using Cortex Agents, but I'm covering it because it made a real difference in "time to answer" and "answer consistency" on the smart glasses, too.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cortex Analyst (semantic views)&lt;/strong&gt;: If you pin down definitions such as sales in a semantic view, the agent builds SQL along those definitions. It no longer needs to hunt through tables, and you can narrow the range of what can be asked&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cortex Search&lt;/strong&gt;: Lets the agent answer by searching documents such as FAQs and manuals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the Lambda code, all you do is swap the &lt;code&gt;tools&lt;/code&gt; and &lt;code&gt;tool_resources&lt;/code&gt; passed to &lt;code&gt;agent:run&lt;/code&gt; as shown below. Since &lt;code&gt;code_toolset_all&lt;/code&gt; isn't used, &lt;code&gt;permission_policy&lt;/code&gt; is no longer needed. I've also removed the &lt;code&gt;ORCHESTRATION_PROMPT&lt;/code&gt; instruction that narrows the tools (&lt;code&gt;orchestration&lt;/code&gt; in &lt;code&gt;instructions&lt;/code&gt;). Note that you need to create the semantic view and the Cortex Search service in advance (here I'm using the ones that come with my sample data).&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_spec&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cortex_analyst_text_to_sql&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sales&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Aggregate orders and sales for the e-commerce site&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_spec&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cortex_search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;faq&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Search the e-commerce site&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s frequently asked questions (FAQ) documents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;tool_resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sales&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;semantic_view&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GLACIERSTYLE_DB.EC_ANALYTICS_SCHEMA.EC_ANALYSIS_SEMANTIC_VIEW&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;execution_environment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;warehouse&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;warehouse&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;COMPUTE_WH&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;faq&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_service&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GLACIERSTYLE_DB.EC_ANALYTICS_SCHEMA.SEARCH_FAQ&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Also grant the glasses' role &lt;code&gt;SELECT&lt;/code&gt; on the semantic view and &lt;code&gt;USAGE&lt;/code&gt; on the Cortex Search service. The role needs &lt;code&gt;SELECT&lt;/code&gt; on the tables the semantic view references as well. Step 1 already allowed every table in the schema, though, so these two grants are the only additions.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;SEMANTIC&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;GLACIERSTYLE_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EC_ANALYTICS_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EC_ANALYSIS_SEMANTIC_VIEW&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;G2_READER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;USAGE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;CORTEX&lt;/span&gt; &lt;span class="k"&gt;SEARCH&lt;/span&gt; &lt;span class="n"&gt;SERVICE&lt;/span&gt; &lt;span class="n"&gt;GLACIERSTYLE_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EC_ANALYTICS_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SEARCH_FAQ&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;G2_READER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If a tool is missing privileges, by default you don't get an error. The answer simply comes back without that tool being used (the reason shows up in the response's &lt;code&gt;warnings&lt;/code&gt;). If an answer looks off, check the privileges first.&lt;/p&gt;

&lt;p&gt;Here are the results with the same model (&lt;code&gt;claude-sonnet-5-5&lt;/code&gt;):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Tool used&lt;/th&gt;
&lt;th&gt;Time to answer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What were total sales in 2024?&lt;/td&gt;
&lt;td&gt;Cortex Analyst&lt;/td&gt;
&lt;td&gt;10.7 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What were the best and worst months for sales in 2024?&lt;/td&gt;
&lt;td&gt;Cortex Analyst&lt;/td&gt;
&lt;td&gt;10.1 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How much is gift wrapping?&lt;/td&gt;
&lt;td&gt;Cortex Search&lt;/td&gt;
&lt;td&gt;9.5 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How many days after delivery can I return an item?&lt;/td&gt;
&lt;td&gt;Cortex Search&lt;/td&gt;
&lt;td&gt;7.2 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every answer matched the semantic view's definitions and the FAQ content. When I asked Coding Agent the same questions, total sales took 12.2 seconds and the monthly question took 13.9 seconds. So the semantic view cut the wait by about 1.5–4 seconds. Coding Agent checked the list of tables and columns every time, so I think building SQL from the definitions saves that step.&lt;/p&gt;

&lt;p&gt;Unlike with Coding Agent, the total sales came back as the total of all orders (¥110,707,792.56), following the semantic view's definition. Being able to decide in the definition which number counts as "sales" is another nice thing about semantic views.&lt;/p&gt;

&lt;p&gt;As for Cortex Search, when I asked "How much is gift wrapping at Glacier Style?", it answered from the FAQ documents like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Gift wrapping starts at ¥330 per item (tax
included). Standard wrapping is ¥330, large items
are ¥550, and premium wrapping is ¥880. Message
cards, gift labels, and carrier bags are free.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Semantic views for questions with established data definitions, Cortex Search for questions about documents, and Coding Agent for exploratory analysis beyond that: splitting the work this way looks like a good approach.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-run" rel="noopener noreferrer"&gt;Cortex Agents Run API (Snowflake Documentation)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/views-semantic/overview" rel="noopener noreferrer"&gt;Overview of semantic views (Snowflake Documentation)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-search/cortex-search-overview" rel="noopener noreferrer"&gt;Cortex Search (Snowflake Documentation)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Things to Watch Out For
&lt;/h2&gt;

&lt;p&gt;This setup is a lot of fun to play with. If you're thinking about using it for work, though, there are a few points to keep in mind.&lt;/p&gt;
&lt;h3&gt;
  
  
  Pair always_allow with a Least-Privilege Role
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;always_allow&lt;/code&gt; lets the agent run any tool without confirmation. The official documentation cautions that you should make sure every input to the agent is trustworthy, including content pulled in through prompts and web search. It also advises running the agent with a least-privilege role that can access only the data the task needs. Keep in mind that whatever you say to the glasses becomes input to the agent as-is.&lt;/p&gt;

&lt;p&gt;Also, the Lambda code tells the agent to use only &lt;code&gt;snowflake_sql_execute&lt;/code&gt; and &lt;code&gt;web_search&lt;/code&gt;, but that instruction isn't enforced. Depending on the situation, the agent may use other tools. As I mentioned earlier, &lt;strong&gt;apply the real restriction through the PAT's role&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Add Business Context with Semantic Views
&lt;/h3&gt;

&lt;p&gt;Coding Agent infers what the data means from the structure of the tables and columns, then aggregates it. So the more business assumptions you share, such as "which orders count as sales" or "how customers are counted," the more accurate the answers get. In the membership tier example earlier, just adding "counted by customer ID" was enough to get an accurate customer count with duplicates removed.&lt;/p&gt;

&lt;p&gt;I recommend defining this kind of business context in a &lt;strong&gt;semantic view&lt;/strong&gt;, as in the Going Further section. Once you define metrics such as sales and the relationships between tables, the agent aggregates along those definitions. That gives you more accurate analysis, based on the same criteria no matter how many times you ask.&lt;/p&gt;
&lt;h3&gt;
  
  
  Latency, Token Usage, and Models
&lt;/h3&gt;

&lt;p&gt;If you don't tell the agent where the data is, it starts by exploring the databases, so answers can take a while. The Lambda in this article gives up after 25 seconds, so I recommend giving the agent hints like &lt;code&gt;DATA_LOCATION&lt;/code&gt; (how long the Even app is willing to wait isn't officially documented either).&lt;/p&gt;

&lt;p&gt;And the feature that automatically tells the agent "what data lives where" is &lt;strong&gt;Cortex Sense&lt;/strong&gt;, announced at Snowflake Summit 26. It automatically assembles business context from past queries, metadata, semantic views, and more, and hands it to the agent. That way, the agent knows where to look and what to query without inspecting tables and schemas one by one. Cortex Sense is coming very soon. Once it's here, it should answer questions from the glasses faster and more accurately, without you having to spell out where the data lives. I'm really looking forward to it!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.snowflake.com/en/blog/enterprise-ai-agents-grounded-context/" rel="noopener noreferrer"&gt;Introducing Cortex Sense: Grounded Context for the Data You Never Modeled (Snowflake Blog)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, Coding Agent builds its answers with the same rich instructions and tool definitions as CoCo. So when the agent explores a wide range of data, the input token count can grow. That said, caching covers most of the input, and narrowing the exploration scope with &lt;code&gt;DATA_LOCATION&lt;/code&gt; or a semantic view cuts down on wasted exploration. You can check usage in &lt;code&gt;SNOWFLAKE.ACCOUNT_USAGE.CORTEX_AGENT_USAGE_HISTORY&lt;/code&gt; (it can take up to about an hour for usage to show up), so take a look once you start using it.&lt;/p&gt;

&lt;p&gt;Keep in mind that latency also varies a lot by model. The official documentation recommends choosing &lt;code&gt;auto&lt;/code&gt; for the model, so the code uses &lt;code&gt;auto&lt;/code&gt; as the default. When I compared the same questions, though, &lt;code&gt;auto&lt;/code&gt; and &lt;code&gt;claude-sonnet-5&lt;/code&gt; took about 18–25 seconds, and some questions hit the 25-second timeout.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;claude-sonnet-5-5&lt;/code&gt; model I used in the examples (a Public Preview model) isn't on the official Cortex Agents model list yet. Still, it works when you specify it, and it responded faster. For production, choose a model from the official list and check the balance between latency and the Lambda timeout. Also note that Cortex Agents models run on cross-region inference, so you may need to set the account parameter &lt;code&gt;CORTEX_ENABLED_CROSS_REGION&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  You Can Also Connect to Cortex AI Gateway
&lt;/h2&gt;

&lt;p&gt;In fact, the same setup also lets you connect to &lt;strong&gt;Cortex AI Gateway&lt;/strong&gt;, which entered Preview on September 15, 2026. Cortex AI Gateway accepts inference requests for a wide range of LLMs (large language models) through a single entry point. It lets you apply access control, tracing, and cost management to those requests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-ai-gateway" rel="noopener noreferrer"&gt;Cortex AI Gateway (Snowflake Documentation)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You only need to change three things in the Lambda code: the destination URL, the request body format, and how the answer is extracted. Claude models go to &lt;code&gt;/v1/messages&lt;/code&gt; in the Anthropic Messages format, and all other models go to &lt;code&gt;/v1/chat/completions&lt;/code&gt; in the OpenAI format.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Claude models go to /v1/messages in the Anthropic Messages format (with the Gateway, you specify the model name)
&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;SNOWFLAKE_HOST&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/api/v2/aigateways/snowflake/v1/messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-5-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SYSTEM_PROMPT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;ensure_ascii&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic-version&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2023-06-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can find the Gateway endpoint with &lt;code&gt;SHOW AI GATEWAYS&lt;/code&gt; or &lt;code&gt;DESCRIBE AI GATEWAY SNOWFLAKE&lt;/code&gt;. Using the Gateway requires the &lt;code&gt;USAGE&lt;/code&gt; privilege on it, which is granted to the &lt;code&gt;PUBLIC&lt;/code&gt; role by default. Note that the official documentation recommends short-lived tokens such as OAuth over PATs for Gateway authentication.&lt;/p&gt;

&lt;p&gt;Comparing the two with the same question makes the difference clear:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Coding Agent&lt;/th&gt;
&lt;th&gt;Cortex AI Gateway&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What it calls&lt;/td&gt;
&lt;td&gt;An agent (uses tools such as SQL and web search)&lt;/td&gt;
&lt;td&gt;An LLM on its own&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Answer to "What were total sales in 2024?"&lt;/td&gt;
&lt;td&gt;Aggregates the data and answers with the amount&lt;/td&gt;
&lt;td&gt;"I don't have that information, so I can't say"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time to answer (measured)&lt;/td&gt;
&lt;td&gt;10–15 seconds (over 25 seconds with some models)&lt;/td&gt;
&lt;td&gt;3–4 seconds (depends on the model)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Data-driven analysis and checks&lt;/td&gt;
&lt;td&gt;Quick responses such as casual chat, brainstorming, and translation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As of now, the official documentation lists three capabilities for Cortex AI Gateway: inference, observability, and cost management. It doesn't describe any way to run tools the way Coding Agent does. Meanwhile, the July 28, 2026 announcement positions Cortex AI Gateway as a foundation for governing access not just to models, but also to tools and MCP (Model Context Protocol) servers. As those capabilities become available, you'll be able to switch between "fast LLM responses" and "data-driven analysis" from a single entry point. I expect that to open up even more possibilities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.snowflake.com/en/news/press-releases/snowflake-advances-the-trusted-agentic-enterprise-era-with-unified-monitoring-and-cost-management/" rel="noopener noreferrer"&gt;Snowflake Advances the Trusted Agentic Enterprise Era with Unified Monitoring and Cost Management (Press Release)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Taking It into the Business
&lt;/h2&gt;

&lt;p&gt;This was just a playful experiment, but while trying it out, I kept picturing situations where it could be useful at work.&lt;/p&gt;

&lt;p&gt;One example is &lt;strong&gt;workplaces where your hands are full&lt;/strong&gt;, such as warehouses, stores, and factory maintenance. Imagine asking "How many of this item are left in stock?" or "When was this equipment last inspected?" without stopping what you're doing, and checking the answer at the edge of your vision. You'd no longer need to pull out a device. Store staff could also check a customer's question with Cortex Search while serving them, without flipping through a manual. Salespeople could check "How much has this customer bought this fiscal year?" right before a meeting. Managers could type a question about KPIs (key performance indicators) on their phones during a meeting and quietly glance at the numbers on their glasses. As I mentioned earlier, the display is visible only to the wearer, so not interrupting the flow of the meeting is a big plus.&lt;/p&gt;

&lt;p&gt;And these are exactly the situations where Snowflake's governance shines. If you give each person on site their own role, the same setup can "show only the data they're allowed to see." Snowflake also keeps a record of who used it and when.&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;What did you think? Just by combining the Even G2, a small Lambda function, and Coding Agent, I can now ask Snowflake for analysis by voice! SQL against tables is read-only and runs only within the role's privileges. That makes playful experiments like this one easy to take on, which I really appreciate.&lt;/p&gt;

&lt;p&gt;Smart glasses are still a device in the middle of evolving. Even so, this experiment reminded me that the place where we use data isn't just in front of a computer screen. Going forward, I'd like to build on this in various ways: growing an agent that combines semantic views and Cortex Search, as in the Going Further section, and trying out how to split the work as Cortex AI Gateway gets updated. If I build something fun, I'll share it here on the blog again. Stay tuned!&lt;/p&gt;

&lt;p&gt;Coding Agent can be called from your own app just by specifying a single tool. Please try challenging yourself with interesting uses of Coding Agent!&lt;/p&gt;
&lt;h2&gt;
  
  
  Promotion
&lt;/h2&gt;
&lt;h3&gt;
  
  
  App Runtime Explained on the Official Snowflake Japan YouTube Channel
&lt;/h3&gt;

&lt;p&gt;The official Snowflake Japan YouTube channel has launched, and it includes a walkthrough of Snowflake App Runtime. If you're interested in building apps right next to your data in Snowflake, this video is for you. It covers what App Runtime is and how to get an app deployed, with a live demo. It's in Japanese, but the demo sections are easy to follow.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/i_oA6QY8T8Y" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;h3&gt;
  
  
  Snowflake What's New Updates on X
&lt;/h3&gt;

&lt;p&gt;I share Snowflake What's New updates on X. Follow for the latest insights:&lt;/p&gt;
&lt;h4&gt;
  
  
  English Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_en" rel="noopener noreferrer"&gt;Snowflake What's New Bot (English Version)&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Japanese Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_jp" rel="noopener noreferrer"&gt;Snowflake's What's New Bot (Japanese Version)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Change Log
&lt;/h2&gt;

&lt;p&gt;(20261011) Initial post&lt;/p&gt;
&lt;h2&gt;
  
  
  Original Japanese Article
&lt;/h2&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://zenn.dev/snowflakejp/articles/87e658f1d5be4f" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Fupload%2Fs--GGPtFW8R--%2Fc_fit%252Cg_north_west%252Cl_text%3Anotosansjp-medium.otf_55%3A%2525E3%252582%2525B9%2525E3%252583%25259E%2525E3%252583%2525BC%2525E3%252583%252588%2525E3%252582%2525B0%2525E3%252583%2525A9%2525E3%252582%2525B9%252520Even%252520G2%252520%2525E3%252581%25258B%2525E3%252582%252589%2525E5%2525A3%2525B0%2525E3%252581%2525A7%252520Snowflake%252520%2525E3%252581%2525AB%2525E3%252583%252587%2525E3%252583%2525BC%2525E3%252582%2525BF%2525E5%252588%252586%2525E6%25259E%252590%2525E3%252582%252592%2525E9%2525A0%2525BC%2525E3%252582%252593%2525E3%252581%2525A7%2525E3%252581%2525BF%2525E3%252581%25259F%252Cw_1010%252Cx_90%252Cy_100%2Fg_south_west%252Cl_text%3Anotosansjp-medium.otf_34%3Atsubasa%252Cx_220%252Cy_108%2Fbo_3px_solid_rgb%3Ad6e3ed%252Cg_south_west%252Ch_90%252Cl_fetch%3AaHR0cHM6Ly9zdGF0aWMuemVubi5zdHVkaW8vdXNlci11cGxvYWQvYXZhdGFyLzQ0ZmE2OGQyM2YuanBlZw%3D%3D%252Cr_20%252Cw_90%252Cx_92%252Cy_102%2Fco_rgb%3A6e7b85%252Cg_south_west%252Cl_text%3Anotosansjp-medium.otf_30%3ASnowflake%252520Japan%252Cx_220%252Cy_160%2Fbo_4px_solid_white%252Cg_south_west%252Ch_50%252Cl_fetch%3AaHR0cHM6Ly9zdGF0aWMuemVubi5zdHVkaW8vdXNlci11cGxvYWQvYXZhdGFyL2RkODMzYmYwZDcuanBlZw%3D%3D%252Cr_max%252Cw_50%252Cx_139%252Cy_84%2Fv1627283836%2Fdefault%2Fog-base-w1200-v2.png%3F_a%3DBACMTiAE" height="630" class="m-0" width="1200"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://zenn.dev/snowflakejp/articles/87e658f1d5be4f" rel="noopener noreferrer" class="c-link"&gt;
            スマートグラス Even G2 から声で Snowflake にデータ分析を頼んでみた
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstatic.zenn.studio%2Fimages%2Flogo-transparent.png" width="315" height="315"&gt;
          zenn.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>snowflake</category>
      <category>eveng2</category>
      <category>llm</category>
      <category>ai</category>
    </item>
    <item>
      <title>Give Your Snowflake App Runtime App a Real Backend with Snowflake Postgres</title>
      <dc:creator>Tsubasa Kanno</dc:creator>
      <pubDate>Fri, 24 Jul 2026 14:31:03 +0000</pubDate>
      <link>https://dev.to/tsubasa_tech/give-your-snowflake-app-runtime-app-a-real-backend-with-snowflake-postgres-2fgm</link>
      <guid>https://dev.to/tsubasa_tech/give-your-snowflake-app-runtime-app-a-real-backend-with-snowflake-postgres-2fgm</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Major revision notice (September 2026)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since the original July 2026 post, Snowflake App Runtime has reached GA and its configuration file layout has changed, so I &lt;strong&gt;rewrote the integration steps in September 2026&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The App Runtime updates themselves (GA, and the consolidation into &lt;code&gt;app.yml&lt;/code&gt;) are covered in detail in the previous article, &lt;a href="https://dev.to/tsubasa_tech/snowflake-app-runtime-deploy-full-stack-web-apps-right-next-to-your-data-from-a-single-prompt-1a29"&gt;Snowflake App Runtime - Deploy Full-Stack Web Apps Right Next to Your Data from a Single Prompt&lt;/a&gt;. Two changes matter for the integration steps here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can now declare the running app's external access in &lt;strong&gt;&lt;code&gt;external_access_integrations&lt;/code&gt; in &lt;code&gt;app.yml&lt;/code&gt;&lt;/strong&gt;. The centerpiece of the original post — "attach the EAI with &lt;code&gt;ALTER APPLICATION SERVICE&lt;/code&gt; after deploying" — is no longer needed.&lt;/li&gt;
&lt;li&gt;Deploys also became &lt;strong&gt;declarative&lt;/strong&gt;, so anything you add with &lt;code&gt;ALTER APPLICATION SERVICE&lt;/code&gt; is reverted on the next deploy. I've added that as a new thing to watch out for.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In a previous article, &lt;a href="https://dev.to/tsubasa_tech/snowflake-app-runtime-deploy-full-stack-web-apps-right-next-to-your-data-from-a-single-prompt-1a29"&gt;Snowflake App Runtime - Deploy Full-Stack Web Apps Right Next to Your Data from a Single Prompt&lt;/a&gt;, I introduced a mechanism that lets you deploy a full-stack web app (Next.js and friends) right next to your data — inside Snowflake itself. In that article, I built a sales dashboard that reads and displays analytical tables in Snowflake.&lt;/p&gt;

&lt;p&gt;Snowflake is an extremely strong platform for aggregating and analyzing large volumes of data (OLAP). Business apps, on the other hand, often have moments where &lt;strong&gt;row-level transactions happen at high frequency&lt;/strong&gt; — inserting a single request, or updating and deleting statuses one at a time. For these &lt;strong&gt;OLTP (online transaction processing)&lt;/strong&gt; workloads, a database purpose-built for that job is the right fit.&lt;/p&gt;

&lt;p&gt;Snowflake offers &lt;strong&gt;Snowflake Postgres&lt;/strong&gt; for exactly this space. Because you can have a PostgreSQL-compatible database inside Snowflake, using it as the &lt;strong&gt;backend DB&lt;/strong&gt; for an app built on App Runtime lets you keep a business app — one where inserts, updates, and deletes happen frequently — entirely within Snowflake's security perimeter.&lt;/p&gt;

&lt;p&gt;In recent years, PostgreSQL has been getting renewed attention as the backend DB for AI agents and applications. Behind this is the fact that it is a proven, standard database in the enterprise, while its rich extension ecosystem lets you stretch it to many use cases. Snowflake Postgres makes it possible to ride this trend on top of the Snowflake platform.&lt;/p&gt;

&lt;p&gt;In this article, I'll walk through how to connect an App Runtime app to Snowflake Postgres — in the order of benefits, use cases, and concrete steps. I've also included the record of the verification I ran by hand to confirm "does this really connect?"&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Want to get hands-on right away?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The explanation of how things work can wait. Integration Steps opens with a prompt you can paste as-is, and CoCo can handle everything from creating the Snowflake Postgres instance through deploying the app and setting up the network permissions.&lt;/p&gt;

&lt;p&gt;The verification part in the first half is the record of &lt;em&gt;why&lt;/em&gt; the configuration ends up the way it does. Come back to it whenever you want to understand the mechanics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article reflects my personal views and does not represent Snowflake's official position.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: (September 2026) Snowflake App Runtime reached general availability (GA) on September 1, 2026, and Snowflake Postgres on February 24, 2026. The data mirroring feature discussed later is still in Preview, so it may change significantly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A Quick Recap of Snowflake App Runtime
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Snowflake App Runtime&lt;/strong&gt; is a platform that lets you deploy web apps like Next.js directly onto Snowflake. No infrastructure to build, no Docker expertise required, and authentication (SSO) is applied automatically. The app runs as a dedicated object called an &lt;strong&gt;&lt;code&gt;APPLICATION SERVICE&lt;/code&gt;&lt;/strong&gt; on &lt;strong&gt;Snowpark Container Services (SPCS)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Configuration lives in a &lt;strong&gt;single &lt;code&gt;app.yml&lt;/code&gt; file (&lt;code&gt;version: 2&lt;/code&gt;)&lt;/strong&gt;, where you declare the deploy destination, scale, secrets, and external access. The &lt;code&gt;app.yml&lt;/code&gt; in this article follows that format.&lt;/p&gt;

&lt;p&gt;For a fuller overview and how to build one with &lt;strong&gt;CoCo&lt;/strong&gt; (Cortex Code was renamed CoCo at Snowflake Summit 2026), please see my previous article.&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/tsubasa_tech/snowflake-app-runtime-deploy-full-stack-web-apps-right-next-to-your-data-from-a-single-prompt-1a29" class="crayons-story__hidden-navigation-link"&gt;Snowflake App Runtime - Deploy Full-Stack Web Apps Right Next to Your Data from a Single Prompt&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/tsubasa_tech" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2070831%2F23d09b26-d96e-4ae8-b223-2886d617e257.jpg" alt="tsubasa_tech profile" class="crayons-avatar__image" width="800" height="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/tsubasa_tech" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Tsubasa Kanno
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Tsubasa Kanno
                
                
              
              &lt;div id="story-author-preview-content-3826995" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/tsubasa_tech" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2070831%2F23d09b26-d96e-4ae8-b223-2886d617e257.jpg" class="crayons-avatar__image" alt="" width="800" height="800"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Tsubasa Kanno&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/tsubasa_tech/snowflake-app-runtime-deploy-full-stack-web-apps-right-next-to-your-data-from-a-single-prompt-1a29" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 5&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/tsubasa_tech/snowflake-app-runtime-deploy-full-stack-web-apps-right-next-to-your-data-from-a-single-prompt-1a29" id="article-link-3826995"&gt;
          Snowflake App Runtime - Deploy Full-Stack Web Apps Right Next to Your Data from a Single Prompt
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/snowflake"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;snowflake&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/llm"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;llm&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/agents"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;agents&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/nextjs"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;nextjs&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/tsubasa_tech/snowflake-app-runtime-deploy-full-stack-web-apps-right-next-to-your-data-from-a-single-prompt-1a29" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/tsubasa_tech/snowflake-app-runtime-deploy-full-stack-web-apps-right-next-to-your-data-from-a-single-prompt-1a29#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            25 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;In this article, I'll focus on making the &lt;strong&gt;data store&lt;/strong&gt; for that App Runtime app be Snowflake Postgres.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Snowflake Postgres?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Snowflake Postgres&lt;/strong&gt; is a fully managed PostgreSQL service where you can create and manage PostgreSQL instances directly from Snowflake. Here's a quick summary of its characteristics.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;What it is&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A PostgreSQL server running on a dedicated virtual machine managed by Snowflake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compatibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Existing PostgreSQL tools, drivers, and ORMs work as-is (&lt;code&gt;psql&lt;/code&gt;, Prisma, &lt;code&gt;pg&lt;/code&gt;, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Versions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Choose from PostgreSQL major versions (16 / 17 / 18)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best at&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High-throughput, high-concurrency &lt;strong&gt;transaction processing (OLTP)&lt;/strong&gt; with writes and updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;How to connect&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Connect directly from any PostgreSQL client via host name, port &lt;code&gt;5432&lt;/code&gt;, and SSL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Status&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Generally available (GA, February 24, 2026)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;While Snowflake's regular tables are strong at aggregating and analyzing large volumes of data (OLAP), Snowflake Postgres is good at OLTP such as "inserting, updating, and deleting one row at a time." The official documentation positions Postgres as the choice &lt;strong&gt;when you need a high-throughput, high-concurrency operational database&lt;/strong&gt;. Combined with an App Runtime app, this division of labor works as-is.&lt;/p&gt;

&lt;p&gt;Official docs: &lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-postgres/about" rel="noopener noreferrer"&gt;About Snowflake Postgres&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why App Runtime × Snowflake Postgres?
&lt;/h2&gt;

&lt;p&gt;You could point your app's backend at an external DB (say, an OLTP database in another cloud), but choosing Snowflake Postgres brings the following benefits.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Everything stays inside the perimeter&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Both the app and the DB live inside Snowflake. You can build a business app with writes and updates without letting data leave your organization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Less data movement&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Handle OLTP and analytics on the same platform. &lt;code&gt;pg_lake&lt;/code&gt; and data mirroring make the handoff to the analytics side smooth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Standard Postgres assets work as-is&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use the &lt;code&gt;pg&lt;/code&gt; driver and ORMs (Prisma, etc.) directly. No special SDK required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Simpler operations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Provisioning, patching, and backups of the DB are left to Snowflake&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you shape it as "transactions in Snowflake Postgres, analysis of the accumulated data in Snowflake tables," you can do both operational work and analytics within a single platform.&lt;/p&gt;

&lt;p&gt;One thing I'm especially watching is &lt;strong&gt;data mirroring (Preview)&lt;/strong&gt;. It lets you sync writes to Snowflake Postgres into your Snowflake analytics environment in near real time — without building an ETL pipeline.&lt;/p&gt;

&lt;p&gt;Under the hood, changes captured by PostgreSQL logical replication are written to Apache Iceberg™ tables through &lt;code&gt;pg_lake&lt;/code&gt;. That design gives you a couple of useful properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Changes land while preserving the source transaction boundaries, so joining mirrored tables keeps consistency intact&lt;/li&gt;
&lt;li&gt;Even with a longer refresh interval configured, the &lt;code&gt;$live&lt;/code&gt; view shows the latest state including changes that haven't been merged yet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, you can achieve "OLTP in Snowflake Postgres, analytics in Snowflake" &lt;strong&gt;without sacrificing freshness and without ETL&lt;/strong&gt;. And Snowflake Postgres itself can be stood up quickly, in just a few clicks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Data mirroring isn't used in this article's steps, but there's a constraint worth knowing if you're planning ahead. It's currently available on AWS and Azure, and &lt;strong&gt;BURSTABLE tier instances (&lt;code&gt;BURST_S&lt;/code&gt; / &lt;code&gt;BURST_M&lt;/code&gt;) are out of scope&lt;/strong&gt;. The steps below use the lightweight &lt;code&gt;BURST_S&lt;/code&gt;, so if mirroring is on your roadmap, pick a &lt;code&gt;STANDARD&lt;/code&gt; or &lt;code&gt;HIGHMEM&lt;/code&gt; family instead.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Official blog: &lt;a href="https://www.snowflake.com/en/blog/engineering/postgres-to-snowflake-replication-mirroring/" rel="noopener noreferrer"&gt;How we pushed CDC into Postgres, and turned replication into clockwork&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Request / entry forms&lt;/strong&gt;: Business apps that write user input to a DB, such as expense requests or inquiry logging&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approval workflows&lt;/strong&gt;: Apps that advance a record's state, like request → approval → done&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Master data tools&lt;/strong&gt;: Apps that add and edit product or customer master data from the screen&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stateful internal tools&lt;/strong&gt;: Apps with frequent updates, such as task management or inventory management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these are apps where "inserts, updates, and deletes happen frequently" — cases where an OLTP database fits better than an analytical table.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Sample App We'll Build
&lt;/h2&gt;

&lt;p&gt;In this article, I'll take the &lt;strong&gt;approval workflow&lt;/strong&gt; from the list above and build an "expense approval app." The key points are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Beyond just listing (SELECT), it also performs &lt;strong&gt;new requests from a form (INSERT)&lt;/strong&gt; and &lt;strong&gt;status updates via approve/reject (UPDATE)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;KPI cards (total requests, pending, approved, and so on) let you grasp the situation at a glance&lt;/li&gt;
&lt;li&gt;The data store is &lt;strong&gt;Snowflake Postgres&lt;/strong&gt;, and writes are reflected instantly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's what the finished app looks like. The frontend is built with Next.js, and pending / approved / rejected states are color-coded with status badges.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc9xjnh7yzipp8jqkutlu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc9xjnh7yzipp8jqkutlu.png" alt="The completed Expense Approval Workflow app — KPI cards and color-coded status badges" width="800" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From here, I'll connect this app to Snowflake Postgres.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integration Architecture
&lt;/h2&gt;

&lt;p&gt;Here's the overall picture as a diagram. The App Runtime app (Application Service) connects to Snowflake Postgres by way of an &lt;strong&gt;External Access Integration (EAI)&lt;/strong&gt;, which I'll cover below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyt6qfxw913otdlcxv0jj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyt6qfxw913otdlcxv0jj.png" alt=" " width="800" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The key point is that &lt;strong&gt;the connection from the app to Snowflake Postgres is treated as "egress to an external network."&lt;/strong&gt; This is the crux of the whole thing, so in the next chapter I'll verify it hands-on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verification: Can App Runtime Really Reach Snowflake Postgres?
&lt;/h2&gt;

&lt;p&gt;The official documentation states that "external connections from a running App Runtime app require an EAI." But since Snowflake Postgres lives inside the same Snowflake, it's natural to wonder, "do I really need an EAI? Won't it just connect without doing anything?" So I deployed a minimal app to find out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verification 1: Without an EAI, even name resolution fails
&lt;/h3&gt;

&lt;p&gt;First, I deployed the app &lt;strong&gt;without&lt;/strong&gt; an EAI and tried to connect to Snowflake Postgres. Looking at the app's logs, here's what I saw.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELFTEST#1 {"connected":false,"error":"getaddrinfo ENOTFOUND &amp;lt;instance-host&amp;gt;.us-west-2.aws.postgres.snowflake.app"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;getaddrinfo ENOTFOUND&lt;/code&gt; — in other words, &lt;strong&gt;even the host name resolution fails&lt;/strong&gt;. By default, the running App Runtime container has no egress to the outside at all, so it can't even resolve the Postgres host name. This made it clear that "an EAI is required."&lt;/p&gt;
&lt;h3&gt;
  
  
  Verification 2: With an EAI, the behavior changes
&lt;/h3&gt;

&lt;p&gt;Next, I created an EAI that allows the Snowflake Postgres host:port, declared it in &lt;code&gt;external_access_integrations&lt;/code&gt; in &lt;code&gt;app.yml&lt;/code&gt;, and redeployed (I'll show the concrete SQL in the steps later). The same app's log then changed like this.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELFTEST#12 {"connected":false,"error":"timeout expired"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The error &lt;strong&gt;changed&lt;/strong&gt; from &lt;code&gt;ENOTFOUND&lt;/code&gt; to &lt;code&gt;timeout expired&lt;/code&gt;. Name resolution now succeeds and the connection is being attempted — but this time it times out. That's because &lt;strong&gt;Snowflake Postgres is not accepting the connection from the app&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Snowflake Postgres rejects inbound connections by default. To allow one, you need to attach a &lt;strong&gt;network policy that includes a network rule in &lt;code&gt;POSTGRES_INGRESS&lt;/code&gt; mode&lt;/strong&gt; to the instance. The official documentation is explicit that without a network policy, the instance can't accept incoming connections. So the integration requires &lt;strong&gt;both&lt;/strong&gt; of the following permissions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;egress&lt;/strong&gt; permission on the app side (EAI)&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;ingress&lt;/strong&gt; permission on the Postgres side (network policy)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Verification 3: Which IPs to allow — Snowflake's egress IP ranges
&lt;/h3&gt;

&lt;p&gt;What's left is "which IPs to allow on the Postgres ingress." The thing to keep in mind here is that &lt;strong&gt;the IP address Snowflake uses when it connects out is not fixed — it's dynamic&lt;/strong&gt;. So rather than allowing a single specific IP, you need to know the &lt;strong&gt;range of egress IPs Snowflake uses&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The function that tells you this is &lt;strong&gt;&lt;code&gt;SYSTEM$GET_SNOWFLAKE_EGRESS_IP_RANGES&lt;/code&gt;&lt;/strong&gt;. It returns the egress IPs Snowflake uses when it reaches out, as &lt;strong&gt;stable CIDR ranges&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The uses the official documentation lists are three: external access from UDFs and stored procedures, &lt;strong&gt;SPCS external access&lt;/strong&gt;, and integration with IP-restricted Git servers. App Runtime isn't named in that list, but because the app runs as an &lt;code&gt;APPLICATION SERVICE&lt;/code&gt; on SPCS, I was able to confirm in this verification that allowing the same ranges does get you connected.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Stable egress IP addresses are generally available (GA) on AWS commercial regions and in Preview on Azure. Also, in Azure regions this function returns JSON with inline comments, so pass the argument to suppress them: &lt;code&gt;PARSE_JSON(SYSTEM$GET_SNOWFLAKE_EGRESS_IP_RANGES(TRUE))&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;"ipv4_prefix"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt;   &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;ip_cidr_range&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;"effective"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;   &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;effective_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;"expires"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;     &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;expiration_date&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FLATTEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;INPUT&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;PARSE_JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SYSTEM&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;GET_SNOWFLAKE_EGRESS_IP_RANGES&lt;/span&gt;&lt;span class="p"&gt;())));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When you run it, you get CIDR ranges and expiration dates per region.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IP_CIDR_RANGE      | EFFECTIVE_DATE          | EXPIRATION_DATE
&amp;lt;CIDR range 1&amp;gt;     | 2025-08-01 00:00:00.000 | 2026-10-22 ...
&amp;lt;CIDR range 2&amp;gt;     | 2025-08-01 00:00:00.000 | 2026-10-22 ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When I allowed these ranges on the Postgres ingress, the app connected to Snowflake Postgres without issue, and the writes succeeded too. Even though the source IP is dynamic, allowing the range keeps the connection stable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: These ranges have an &lt;strong&gt;expiration&lt;/strong&gt;. As the expiry approaches, new ranges are added, so for production I'd recommend setting up a mechanism to re-fetch them periodically and update the network policy. For details, see the official docs: &lt;a href="https://docs.snowflake.com/en/user-guide/egress-ip/network-egress" rel="noopener noreferrer"&gt;Protect request inbounds with Snowflake egress IPs&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With that, the correct configuration comes into view. From the next chapter, I'll summarize it as concrete steps.&lt;/p&gt;
&lt;h2&gt;
  
  
  Integration Steps
&lt;/h2&gt;

&lt;p&gt;Through the verification, the pieces needed for the integration are settled (the EAI on the app side, the ingress permission on the Postgres side). There are two broad ways to proceed. Let me start with the fastest route.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Fastest Route: Let CoCo Handle It All
&lt;/h3&gt;

&lt;p&gt;The quickest approach is to &lt;strong&gt;tell CoCo Desktop (or the CLI) not only to create the app, but also to prepare Snowflake Postgres, create the EAI, and set up the ingress permission — all in one go — and have the &lt;code&gt;snowflake-apps&lt;/code&gt; skill run it end to end.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I wrote the original post, attaching the EAI to a running app was a separate task after deploying, so the order of operations needed care. Now that you can &lt;strong&gt;declare the EAI in &lt;code&gt;external_access_integrations&lt;/code&gt; in &lt;code&gt;app.yml&lt;/code&gt;&lt;/strong&gt;, it's enough to prepare the EAI first and then deploy.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the Snowflake Postgres instance (and get its host)&lt;/li&gt;
&lt;li&gt;Store the credentials in a Secret&lt;/li&gt;
&lt;li&gt;Create the egress network rule and the EAI&lt;/li&gt;
&lt;li&gt;Build the app with CoCo, declaring the EAI and Secret in &lt;code&gt;app.yml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;snow app deploy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Allow the egress IP ranges with &lt;code&gt;POSTGRES_INGRESS&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Connection established — verify it works&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key is to &lt;strong&gt;pin down the Postgres host and the EAI before you deploy&lt;/strong&gt;. Once the values that go into &lt;code&gt;app.yml&lt;/code&gt; are settled, a single deploy is all it takes.&lt;/p&gt;

&lt;p&gt;If you tell CoCo this order and configuration up front in the prompt, it will proceed without getting lost. For this expense approval app, the prompt would look something like this.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/snowflake-apps
Build an "expense approval app" in Next.js with Snowflake Postgres as the backend.

[Features]
- List requests, submit a new request from a form (INSERT), and update status via approve/reject (UPDATE)
- KPI cards for total requests, pending, approved, and so on
- Color-code the status (Pending / Approved / Rejected) with badges

[Deploy &amp;amp; connection plan]
- If needed, create the Snowflake Postgres instance from scratch (use its host if one already exists)
- Write app.yml in the version: 2 format, with name / database / schema / query_warehouse spelled out
- Deploy the app to the APP_DB.APP schema
- Create a Snowflake Secret (APP_DB.APP.PG_CRED) and read it by mounting it via secrets in app.yml
- Pass the host, port (5432), and DB name via environment_variables in app.yml
- Enable SSL for the connection
- Before deploying, create an EAI that allows egress to Snowflake Postgres,
  and list its name under external_access_integrations in app.yml
- Finally, take the IP ranges from SYSTEM$GET_SNOWFLAKE_EGRESS_IP_RANGES and
  set them as a POSTGRES_INGRESS network policy on the Postgres instance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The key is to &lt;strong&gt;state up front that it should "mount and read the Secret," "declare the EAI in app.yml," and "allow ingress with the egress IP range."&lt;/strong&gt; Skip these, and the credential handoff or network permissions tend to fall through the cracks — leaving you stuck wondering why it won't connect after deploy.&lt;/p&gt;

&lt;p&gt;Just a few rounds of back-and-forth with CoCo based on this prompt, and the whole configuration for this article (deploying the app, the EAI, and the ingress permission) comes together. For everyday use, this fastest route alone is plenty.&lt;/p&gt;

&lt;p&gt;So, what is CoCo actually doing behind the scenes? In the next chapter, I'll build the same thing by hand, one piece at a time, to see what's inside. If you're not interested in the internals and just want it to work, you can skip the rest.&lt;/p&gt;
&lt;h3&gt;
  
  
  Doing It Step by Step
&lt;/h3&gt;

&lt;p&gt;If you do it yourself one step at a time, the flow looks like this. It's also a useful reference when you want to fold this into an existing workflow.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the Snowflake Postgres instance&lt;/li&gt;
&lt;li&gt;Check the connection info (host / 5432 / SSL)&lt;/li&gt;
&lt;li&gt;Store the credentials in a Secret&lt;/li&gt;
&lt;li&gt;Create the egress network rule and the EAI&lt;/li&gt;
&lt;li&gt;Implement the app and &lt;code&gt;app.yml&lt;/code&gt; (EAI / Secret / environment variables)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;snow app deploy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Allow the Postgres ingress (egress IP ranges)&lt;/li&gt;
&lt;li&gt;Verify it works&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The SQL below assumes a database/schema to hold the network rules and Secret (&lt;code&gt;APP_DB.APP&lt;/code&gt; in the examples) and a role that can create EAIs (&lt;code&gt;ACCOUNTADMIN&lt;/code&gt; in the examples).&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: Create the Snowflake Postgres Instance
&lt;/h3&gt;

&lt;p&gt;First, create the Snowflake Postgres instance. You can do this in SQL or in the Snowsight GUI.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;POSTGRES&lt;/span&gt; &lt;span class="n"&gt;INSTANCE&lt;/span&gt; &lt;span class="n"&gt;MY_PG_INSTANCE&lt;/span&gt;
  &lt;span class="n"&gt;COMPUTE_FAMILY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'BURST_S'&lt;/span&gt;
  &lt;span class="n"&gt;STORAGE_SIZE_GB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
  &lt;span class="n"&gt;AUTHENTICATION_AUTHORITY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;POSTGRES&lt;/span&gt;
  &lt;span class="n"&gt;POSTGRES_VERSION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;
  &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Backend DB for App Runtime app'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When it's created, the connection info (password) for the &lt;code&gt;snowflake_admin&lt;/code&gt; user is returned. &lt;strong&gt;This info is not shown again&lt;/strong&gt;, so be sure to keep it somewhere safe. Creation takes a little while, so wait until the state becomes &lt;code&gt;READY&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DESCRIBE&lt;/span&gt; &lt;span class="n"&gt;POSTGRES&lt;/span&gt; &lt;span class="n"&gt;INSTANCE&lt;/span&gt; &lt;span class="n"&gt;MY_PG_INSTANCE&lt;/span&gt;
  &lt;span class="o"&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="nv"&gt;"value"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;state&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nv"&gt;"property"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'state'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Step 2: Check the Connection Info (Host Name)
&lt;/h3&gt;

&lt;p&gt;The host name your app connects to is available via &lt;code&gt;DESCRIBE POSTGRES INSTANCE&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DESCRIBE&lt;/span&gt; &lt;span class="n"&gt;POSTGRES&lt;/span&gt; &lt;span class="n"&gt;INSTANCE&lt;/span&gt; &lt;span class="n"&gt;MY_PG_INSTANCE&lt;/span&gt;
  &lt;span class="o"&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="nv"&gt;"value"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;host&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nv"&gt;"property"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'host'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You'll get a host name like &lt;code&gt;&amp;lt;instance-id&amp;gt;.&amp;lt;...&amp;gt;.us-west-2.aws.postgres.snowflake.app&lt;/code&gt;. Connections use &lt;strong&gt;port &lt;code&gt;5432&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;SSL is required&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Prepare the table at this stage. There are two ways to do it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Create it from a local PostgreSQL client (psql, etc.)&lt;/strong&gt;: In this case, you first need to &lt;strong&gt;allow your local IP in &lt;code&gt;POSTGRES_INGRESS&lt;/code&gt;&lt;/strong&gt; the same way as &lt;code&gt;PG_INGRESS_LOCAL&lt;/code&gt; in Step 7 (finish the network permission before connecting).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create it in the app's initialization or a migration&lt;/strong&gt;: Have the app itself run &lt;code&gt;CREATE TABLE&lt;/code&gt; after deploy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Either way, note that this &lt;code&gt;CREATE TABLE&lt;/code&gt; runs &lt;strong&gt;against Postgres, not in a Snowflake worksheet&lt;/strong&gt;. The &lt;code&gt;DESCRIBE POSTGRES INSTANCE&lt;/code&gt; calls in Steps 1–2 are Snowflake SQL, but from here on it's Postgres dialect.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Example: expense requests table (run this against Postgres)&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;expense_requests&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;         &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;applicant&lt;/span&gt;  &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;category&lt;/span&gt;   &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;amount&lt;/span&gt;     &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;purpose&lt;/span&gt;    &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;status&lt;/span&gt;     &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'pending'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="n"&gt;TIMESTAMPTZ&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="n"&gt;updated_at&lt;/span&gt; &lt;span class="n"&gt;TIMESTAMPTZ&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Step 3: Store the Credentials in a Snowflake Secret
&lt;/h3&gt;

&lt;p&gt;You want to avoid hardcoding the password in the app, so store the credentials in a &lt;strong&gt;Snowflake Secret&lt;/strong&gt;. App Runtime can mount this Secret into the container via &lt;code&gt;app.yml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="n"&gt;SECRET&lt;/span&gt; &lt;span class="n"&gt;APP_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PG_CRED&lt;/span&gt;
  &lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PASSWORD&lt;/span&gt;
  &lt;span class="n"&gt;USERNAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'snowflake_admin'&lt;/span&gt;
  &lt;span class="n"&gt;PASSWORD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;YOUR_POSTGRES_PASSWORD&amp;gt;'&lt;/span&gt;
  &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Snowflake Postgres credentials for the app'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;For production, I'd recommend preparing a role/user with least-privilege access for the purpose at hand, and using those credentials.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Step 4: Create the egress Network Rule and EAI
&lt;/h3&gt;

&lt;p&gt;So the app can reach out to the Snowflake Postgres host:port, create an &lt;strong&gt;egress&lt;/strong&gt; network rule and an External Access Integration (EAI). Specify port &lt;code&gt;5432&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Network rule allowing egress to Snowflake Postgres&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="n"&gt;NETWORK&lt;/span&gt; &lt;span class="k"&gt;RULE&lt;/span&gt; &lt;span class="n"&gt;APP_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PG_EGRESS_RULE&lt;/span&gt;
  &lt;span class="k"&gt;MODE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EGRESS&lt;/span&gt;
  &lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HOST_PORT&lt;/span&gt;
  &lt;span class="n"&gt;VALUE_LIST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;instance-host&amp;gt;.us-west-2.aws.postgres.snowflake.app:5432'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- EAI bundling the rule above&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;EXTERNAL&lt;/span&gt; &lt;span class="k"&gt;ACCESS&lt;/span&gt; &lt;span class="n"&gt;INTEGRATION&lt;/span&gt; &lt;span class="n"&gt;APP_PG_EAI&lt;/span&gt;
  &lt;span class="n"&gt;ALLOWED_NETWORK_RULES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;APP_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PG_EGRESS_RULE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;ENABLED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;TRUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Note that since the credential Secret is mounted and read from &lt;code&gt;app.yml&lt;/code&gt; in the next Step, you don't need to include the Secret in this EAI (&lt;code&gt;ALLOWED_AUTHENTICATION_SECRETS&lt;/code&gt;). The EAI is solely responsible for permitting the egress path.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 5: Implement the App and &lt;code&gt;app.yml&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;On the app side, connect with the standard &lt;code&gt;pg&lt;/code&gt; driver. Read the credentials from the Secret files mounted in Step 3 (&lt;code&gt;/secrets/PG_CRED/username&lt;/code&gt;, &lt;code&gt;/secrets/PG_CRED/password&lt;/code&gt;), and receive the host and port from environment variables — that keeps things easy to manage. SSL is required.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/db.ts (excerpt of the connection part)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;readFileSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Pool&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Read credentials from the Secret mounted via app.yml&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;readSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/secrets/PG_CRED/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PGHOST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PGPORT&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;readSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;username&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;readSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PGDATABASE&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postgres&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;rejectUnauthorized&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// SSL required (equivalent to sslmode=require)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;If you want stricter server certificate verification for SSL, you can specify the &lt;code&gt;certificate&lt;/code&gt; returned by &lt;code&gt;DESCRIBE POSTGRES INSTANCE&lt;/code&gt; as the CA.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The host, port, target DB, the Secret to mount, and the EAI you created in Step 4 all go into &lt;code&gt;app.yml&lt;/code&gt;. &lt;strong&gt;This is the crux of the integration.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MY_APP&lt;/span&gt;
&lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;APP_DB&lt;/span&gt;
&lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;APP&lt;/span&gt;
&lt;span class="na"&gt;query_warehouse&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;APP_WH&lt;/span&gt;

&lt;span class="na"&gt;environment_variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PGHOST&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;instance-host&amp;gt;.us-west-2.aws.postgres.snowflake.app"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PGPORT&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PGDATABASE&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres"&lt;/span&gt;
&lt;span class="na"&gt;secrets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PG_CRED&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;APP_DB.APP.PG_CRED&lt;/span&gt;

&lt;span class="c1"&gt;# EAI for the running app to reach out to Snowflake Postgres&lt;/span&gt;
&lt;span class="na"&gt;external_access_integrations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;APP_PG_EAI&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The thing to watch here is that &lt;strong&gt;build time and run time use different fields&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Timing&lt;/th&gt;
&lt;th&gt;What it's for here&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;build_eai&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Build time&lt;/td&gt;
&lt;td&gt;npm and Google Fonts are allowed by default. Not needed here&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;external_access_integrations&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run time&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;This is the one you need to reach Snowflake Postgres&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The original post predated this run-time field, so the EAI had to be attached with &lt;code&gt;ALTER APPLICATION SERVICE&lt;/code&gt; after deploying. Now that it lives in the manifest, it's wired up as part of the deploy.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 6: Deploy
&lt;/h3&gt;

&lt;p&gt;Deploy to App Runtime with &lt;code&gt;snow app deploy&lt;/code&gt;. Uploading the source → remote build → creating the &lt;code&gt;APPLICATION SERVICE&lt;/code&gt; all proceed automatically, and the EAI you declared in &lt;code&gt;app.yml&lt;/code&gt; is wired up at the same time.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;snow app deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you want to check the service state after deploying, use:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;APPLICATION&lt;/span&gt; &lt;span class="n"&gt;SERVICES&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;APP_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️&lt;/strong&gt; Since the move to &lt;code&gt;app.yml&lt;/code&gt;, &lt;strong&gt;deploys are declarative&lt;/strong&gt;. Every &lt;code&gt;snow app deploy&lt;/code&gt; applies the whole manifest with &lt;code&gt;CREATE OR ALTER APPLICATION SERVICE ... SPECIFICATION&lt;/code&gt;, so &lt;strong&gt;any field you leave out goes back to its default&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That means even if you add an EAI afterwards with &lt;code&gt;ALTER APPLICATION SERVICE&lt;/code&gt;, it &lt;strong&gt;comes off again on the next deploy&lt;/strong&gt; unless &lt;code&gt;external_access_integrations&lt;/code&gt; is in your &lt;code&gt;app.yml&lt;/code&gt;. This is the classic "it was working, then I deployed and it stopped connecting" case, so always keep connection settings in the manifest.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Step 7: Allow the Snowflake Postgres Ingress
&lt;/h3&gt;

&lt;p&gt;Finally, allow inbound connections from the app on the Snowflake Postgres side. As we saw in the verification, the source IP is not fixed, so allow the &lt;strong&gt;egress IP range&lt;/strong&gt; you get from &lt;code&gt;SYSTEM$GET_SNOWFLAKE_EGRESS_IP_RANGES&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- 1. Check the egress IP ranges&lt;/span&gt;
&lt;span class="c1"&gt;-- On Azure, pass TRUE to suppress the inline comments&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;"ipv4_prefix"&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;ip_cidr_range&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FLATTEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;INPUT&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;PARSE_JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SYSTEM&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;GET_SNOWFLAKE_EGRESS_IP_RANGES&lt;/span&gt;&lt;span class="p"&gt;())));&lt;/span&gt;

&lt;span class="c1"&gt;-- 2. Ingress rule for the app (App Runtime)&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="n"&gt;NETWORK&lt;/span&gt; &lt;span class="k"&gt;RULE&lt;/span&gt; &lt;span class="n"&gt;APP_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PG_INGRESS_APP&lt;/span&gt;
  &lt;span class="k"&gt;MODE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;POSTGRES_INGRESS&lt;/span&gt;
  &lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IPV4&lt;/span&gt;
  &lt;span class="n"&gt;VALUE_LIST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;fetched CIDR range&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- 3. Ingress rule for your local client (used for the psql checks)&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="n"&gt;NETWORK&lt;/span&gt; &lt;span class="k"&gt;RULE&lt;/span&gt; &lt;span class="n"&gt;APP_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PG_INGRESS_LOCAL&lt;/span&gt;
  &lt;span class="k"&gt;MODE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;POSTGRES_INGRESS&lt;/span&gt;
  &lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IPV4&lt;/span&gt;
  &lt;span class="n"&gt;VALUE_LIST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;your global IP&amp;gt;/32'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- 4. Bundle both into a network policy&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="n"&gt;NETWORK&lt;/span&gt; &lt;span class="n"&gt;POLICY&lt;/span&gt; &lt;span class="n"&gt;MY_PG_POLICY&lt;/span&gt;
  &lt;span class="n"&gt;ALLOWED_NETWORK_RULE_LIST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'APP_DB.APP.PG_INGRESS_APP'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'APP_DB.APP.PG_INGRESS_LOCAL'&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- 5. Attach it to the instance&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="n"&gt;POSTGRES&lt;/span&gt; &lt;span class="n"&gt;INSTANCE&lt;/span&gt; &lt;span class="n"&gt;MY_PG_INSTANCE&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;NETWORK_POLICY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'MY_PG_POLICY'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;What matters here is &lt;strong&gt;putting both the app rule and the local rule into the policy&lt;/strong&gt;. Attaching a policy replaces what was there before, so an app-only policy leaves you unable to check from psql.&lt;/p&gt;

&lt;p&gt;Because these ranges can change and expire, if the app suddenly can't connect one day, the first thing to check is re-fetching &lt;code&gt;SYSTEM$GET_SNOWFLAKE_EGRESS_IP_RANGES&lt;/code&gt; and updating the network rule to the latest ranges. Note also that network policy changes can take a few minutes to take effect — if it won't connect right after you set it, wait a little and try again.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 8: Verify It Works — Confirm Writes Land in Snowflake Postgres
&lt;/h3&gt;

&lt;p&gt;At this point, the app can read from and write to Snowflake Postgres. Let's confirm that "the app's operations really do change the data in Snowflake Postgres."&lt;/p&gt;

&lt;p&gt;First, submit a new expense request from the app's form (INSERT).&lt;/p&gt;

&lt;p&gt;At that moment, on the Snowflake Postgres side, a record has actually been added. Peeking at the same table from outside App Runtime (e.g., a local client) shows the new row.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; id |  applicant   | category | amount | status
----+--------------+----------+--------+---------
  6 | Maria Lopez  | Travel   |   340  | pending   ← the row submitted from the app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Next, let's "approve" this request in the app (UPDATE). The &lt;code&gt;status&lt;/code&gt; on the Postgres side flips instantly.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; id |  applicant   | status   | updated_at
----+--------------+----------+------------
  6 | Maria Lopez  | approved | 12:32:55    ← updated by the approve action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Just like that, submissions and approvals in the App Runtime app are reflected directly in the Snowflake Postgres data. I confirmed that a "writable business app running right next to the data" is actually working.&lt;/p&gt;
&lt;h2&gt;
  
  
  Things to Watch Out For
&lt;/h2&gt;

&lt;p&gt;Here are the points I found worth knowing up front so you don't stumble when you actually wire this up.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Write the running app's EAI in &lt;code&gt;app.yml&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The egress EAI for the running app (Application Service) goes in &lt;strong&gt;&lt;code&gt;external_access_integrations&lt;/code&gt;&lt;/strong&gt; in &lt;code&gt;app.yml&lt;/code&gt;. &lt;code&gt;build_eai&lt;/code&gt; is a build-time-only field, so putting it there won't let the running app reach out. Having separate fields for build time and run time is the easy spot to mix up.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Settings added with &lt;code&gt;ALTER APPLICATION SERVICE&lt;/code&gt; are reverted on deploy
&lt;/h3&gt;

&lt;p&gt;Since the move to &lt;code&gt;app.yml&lt;/code&gt;, deploys are declarative and each one applies the whole manifest. So an EAI or an auto-suspend setting you add later in SQL &lt;strong&gt;comes off on the next deploy unless it's in the manifest&lt;/strong&gt;. Using &lt;code&gt;ALTER&lt;/code&gt; for a quick experiment is fine, but fold it back into &lt;code&gt;app.yml&lt;/code&gt; afterwards.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Connecting needs both egress and ingress permissions
&lt;/h3&gt;

&lt;p&gt;Neither the egress (EAI) on the app side alone, nor the ingress (network policy) on the Postgres side alone, is enough. The connection is established only when &lt;strong&gt;both&lt;/strong&gt; are set.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. The source IP is not fixed
&lt;/h3&gt;

&lt;p&gt;The App Runtime source IP is not fixed, so allow the &lt;strong&gt;range&lt;/strong&gt; from &lt;code&gt;SYSTEM$GET_SNOWFLAKE_EGRESS_IP_RANGES&lt;/code&gt; rather than an individual IP. The ranges have an expiration, so for production, set up a mechanism for periodic updates.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. SSL is required
&lt;/h3&gt;

&lt;p&gt;Connections to Snowflake Postgres require SSL. If SSL isn't enabled on the driver side, you can't connect.&lt;/p&gt;
&lt;h3&gt;
  
  
  6. An app deployed to a personal database can't be shared
&lt;/h3&gt;

&lt;p&gt;If you don't specify a deploy target, the app may be placed in a personal database (&lt;code&gt;USER$...&lt;/code&gt;) and can't be shared with other roles. If you have internal sharing in mind, specify a regular database/schema. Note that &lt;code&gt;app.yml&lt;/code&gt; won't fill in &lt;code&gt;database&lt;/code&gt; / &lt;code&gt;schema&lt;/code&gt; from your connection, so spelling them out in the manifest is the safe move.&lt;/p&gt;
&lt;h3&gt;
  
  
  7. Mind the instance family if mirroring is on your roadmap
&lt;/h3&gt;

&lt;p&gt;The examples here use the lightweight &lt;code&gt;BURST_S&lt;/code&gt;, but &lt;strong&gt;the BURSTABLE tier is out of scope for data mirroring&lt;/strong&gt;. You can change the family later with &lt;code&gt;ALTER POSTGRES INSTANCE ... SET COMPUTE_FAMILY&lt;/code&gt;, but if you're thinking "get the app running now, wire up analytics later," picking a &lt;code&gt;STANDARD&lt;/code&gt; or &lt;code&gt;HIGHMEM&lt;/code&gt; family from the start means less rework.&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;What did you think of the App Runtime × Snowflake Postgres integration?&lt;/p&gt;

&lt;p&gt;Let's recap the key points of this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With an &lt;strong&gt;App Runtime app + Snowflake Postgres&lt;/strong&gt;, you can keep a full-fledged, write-heavy business app entirely within Snowflake's security perimeter&lt;/li&gt;
&lt;li&gt;The connection from the app to Snowflake Postgres is &lt;strong&gt;treated as egress&lt;/strong&gt;, so an &lt;strong&gt;EAI is required&lt;/strong&gt; (without it, even name resolution fails)&lt;/li&gt;
&lt;li&gt;The EAI for the running app goes in &lt;strong&gt;&lt;code&gt;external_access_integrations&lt;/code&gt; in &lt;code&gt;app.yml&lt;/code&gt;&lt;/strong&gt;. Deploys are declarative, so adding it later in SQL means it comes off on the next deploy&lt;/li&gt;
&lt;li&gt;On the Postgres side, allow inbound connections with a &lt;strong&gt;&lt;code&gt;POSTGRES_INGRESS&lt;/code&gt; network policy&lt;/strong&gt;. Since the source IP is not fixed, allow the &lt;strong&gt;range from &lt;code&gt;SYSTEM$GET_SNOWFLAKE_EGRESS_IP_RANGES&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;When building with CoCo, it goes smoothly if you convey the order — &lt;strong&gt;"create Postgres → create the Secret → create the EAI → build the app (declaring the EAI in app.yml) → deploy → allow ingress"&lt;/strong&gt; — up front in the prompt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I was able to confirm the "running a writable business app right next to your data" setup all the way through to INSERTs and UPDATEs landing in Postgres behind an authenticated URL. Request forms and master data management are good places to start. I'd love for you to get hands-on and share what you discover. Let's grow this new app-building experience together!&lt;/p&gt;
&lt;h2&gt;
  
  
  Promotion
&lt;/h2&gt;
&lt;h3&gt;
  
  
  App Runtime Explained on the Official Snowflake Japan YouTube Channel
&lt;/h3&gt;

&lt;p&gt;The official Snowflake Japan YouTube channel has launched, and it already includes a walkthrough of Snowflake App Runtime — the foundation this article builds on. The video covers what App Runtime is and how to get an app deployed, with a live demo. It's in Japanese, but the demo sections should still be easy to follow alongside this article.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/i_oA6QY8T8Y" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;h3&gt;
  
  
  Snowflake What's New Updates on X
&lt;/h3&gt;

&lt;p&gt;I share Snowflake What's New updates on X. Follow for the latest insights:&lt;/p&gt;
&lt;h4&gt;
  
  
  English Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_en" rel="noopener noreferrer"&gt;Snowflake What's New Bot (English Version)&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Japanese Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_jp" rel="noopener noreferrer"&gt;Snowflake's What's New Bot (Japanese Version)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Change Log
&lt;/h2&gt;

&lt;p&gt;(20260724) Initial post&lt;br&gt;
(20260830) Added the App Runtime walkthrough from the official Snowflake Japan YouTube channel&lt;br&gt;
(20260923) &lt;strong&gt;Major revision.&lt;/strong&gt; Reflected App Runtime's GA (September 1, 2026). Rewrote the integration around declaring the running app's EAI in &lt;code&gt;external_access_integrations&lt;/code&gt; in &lt;code&gt;app.yml&lt;/code&gt;, and dropped the original post's centerpiece — attaching it with &lt;code&gt;ALTER APPLICATION SERVICE&lt;/code&gt;. Added a new caveat for declarative deploys (settings added in SQL are reverted on the next deploy). Consolidated the walkthrough from nine steps to eight, and replaced the CoCo prompt and the flow outlines. Split the Postgres ingress rule into app and local rules so the psql checks keep working. Noted data mirroring's availability (AWS / Azure, BURSTABLE tier out of scope) and the Azure specifics of the egress IP function&lt;/p&gt;
&lt;h2&gt;
  
  
  Original Japanese Article
&lt;/h2&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://zenn.dev/snowflakejp/articles/ae7a9c2f40fc50" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Fupload%2Fs--5PwnNDIN--%2Fc_fit%252Cg_north_west%252Cl_text%3Anotosansjp-medium.otf_55%3ASnowflake%252520App%252520Runtime%252520%2525E3%252581%2525AE%2525E3%252583%252590%2525E3%252583%252583%2525E3%252582%2525AF%2525E3%252582%2525A8%2525E3%252583%2525B3%2525E3%252583%252589%2525E3%252582%252592%252520Snowflake%252520Postgres%252520%2525E3%252581%2525AB%2525E3%252581%252597%2525E3%252581%2525A6%2525E6%25259C%2525AC%2525E6%2525A0%2525BC%2525E7%25259A%252584%2525E3%252581%2525AA...%252Cw_1010%252Cx_90%252Cy_100%2Fg_south_west%252Cl_text%3Anotosansjp-medium.otf_34%3Atsubasa%252Cx_220%252Cy_108%2Fbo_3px_solid_rgb%3Ad6e3ed%252Cg_south_west%252Ch_90%252Cl_fetch%3AaHR0cHM6Ly9zdGF0aWMuemVubi5zdHVkaW8vdXNlci11cGxvYWQvYXZhdGFyLzQ0ZmE2OGQyM2YuanBlZw%3D%3D%252Cr_20%252Cw_90%252Cx_92%252Cy_102%2Fco_rgb%3A6e7b85%252Cg_south_west%252Cl_text%3Anotosansjp-medium.otf_30%3ASnowflake%252520Japan%252Cx_220%252Cy_160%2Fbo_4px_solid_white%252Cg_south_west%252Ch_50%252Cl_fetch%3AaHR0cHM6Ly9zdGF0aWMuemVubi5zdHVkaW8vdXNlci11cGxvYWQvYXZhdGFyL2RkODMzYmYwZDcuanBlZw%3D%3D%252Cr_max%252Cw_50%252Cx_139%252Cy_84%2Fv1627283836%2Fdefault%2Fog-base-w1200-v2.png%3F_a%3DBACMTiAE" height="630" class="m-0" width="1200"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://zenn.dev/snowflakejp/articles/ae7a9c2f40fc50" rel="noopener noreferrer" class="c-link"&gt;
            Snowflake App Runtime のバックエンドを Snowflake Postgres にして本格的な業務アプリを作る
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstatic.zenn.studio%2Fimages%2Flogo-transparent.png" width="315" height="315"&gt;
          zenn.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>snowflake</category>
      <category>postgres</category>
      <category>llm</category>
      <category>app</category>
    </item>
    <item>
      <title>Snowflake App Runtime - Deploy Full-Stack Web Apps Right Next to Your Data from a Single Prompt</title>
      <dc:creator>Tsubasa Kanno</dc:creator>
      <pubDate>Fri, 05 Jun 2026 10:26:48 +0000</pubDate>
      <link>https://dev.to/tsubasa_tech/snowflake-app-runtime-deploy-full-stack-web-apps-right-next-to-your-data-from-a-single-prompt-1a29</link>
      <guid>https://dev.to/tsubasa_tech/snowflake-app-runtime-deploy-full-stack-web-apps-right-next-to-your-data-from-a-single-prompt-1a29</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Major revision notice (September 2026)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Snowflake App Runtime has reached GA since this article was first published in June 2026, and the configuration file layout changed substantially along the way. So I &lt;strong&gt;rewrote this article from top to bottom in September 2026&lt;/strong&gt;. Here's what changed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Snowflake App Runtime became &lt;strong&gt;generally available (GA) on September 1, 2026&lt;/strong&gt;. Everything written on the assumption of Public Preview has been revisited.&lt;/li&gt;
&lt;li&gt;Configuration has consolidated into a &lt;strong&gt;single &lt;code&gt;app.yml&lt;/code&gt; manifest (&lt;code&gt;version: 2&lt;/code&gt;)&lt;/strong&gt;. The &lt;code&gt;snowflake.yml&lt;/code&gt; that the first version centered on is now treated as legacy.&lt;/li&gt;
&lt;li&gt;You can now set &lt;strong&gt;scale (&lt;code&gt;min_instances&lt;/code&gt; / &lt;code&gt;max_instances&lt;/code&gt;) and auto-suspend (&lt;code&gt;auto_suspend_secs&lt;/code&gt;)&lt;/strong&gt; in &lt;code&gt;app.yml&lt;/code&gt;, so I added a dedicated section for it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy targets&lt;/strong&gt; for switching between dev / stage / prod (&lt;code&gt;targets&lt;/code&gt; / &lt;code&gt;--target&lt;/code&gt;) are now supported, so I added a section for those too.&lt;/li&gt;
&lt;li&gt;I corrected how Caller's Rights is configured. The first version said you needed a setting in &lt;code&gt;app.yml&lt;/code&gt;; in fact the correct shape is a flag in your code combined with &lt;code&gt;GRANT CALLER&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;snow app deploy&lt;/code&gt; flags, the required Snowflake CLI version, and other details that have moved on since the first version are now aligned with the current spec.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Snowflake App Runtime&lt;/strong&gt;, announced at Snowflake Summit 2026, reached general availability (GA) in September 2026. It's one of the features I've been keeping a close eye on since it was first announced.&lt;/p&gt;

&lt;p&gt;Have you ever felt one of these frustrations?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your data is neatly organized inside Snowflake, but the &lt;strong&gt;web app that surfaces it runs somewhere else entirely&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;To ship an app, you have to stand up &lt;strong&gt;Docker, infrastructure, and an auth layer&lt;/strong&gt; every single time&lt;/li&gt;
&lt;li&gt;You just want to build an internal tool, but you end up &lt;strong&gt;copying data out to the app side&lt;/strong&gt;, and governance goes out the window&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Snowflake App Runtime answers exactly these pain points. In a nutshell, it lets you &lt;strong&gt;deploy a full-stack web app (Next.js and friends) right next to your data — inside Snowflake itself&lt;/strong&gt;. No infrastructure to build, authentication handled for you, and no data movement.&lt;/p&gt;

&lt;p&gt;On top of that, when you pair it with the AI coding agent &lt;strong&gt;Snowflake CoCo&lt;/strong&gt; (formerly Cortex Code), you can &lt;strong&gt;go from a prompt to a scaffolded app and all the way to deployment&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Cortex Code was renamed CoCo at Snowflake Summit 2026, so I'll use CoCo throughout this article. That said, parts of the official documentation and some URLs still carry the Cortex Code name.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Configuration now lives in a single file: &lt;code&gt;app.yml&lt;/code&gt; with &lt;code&gt;version: 2&lt;/code&gt;. I'll walk through the current way to build one — starting from the overview, then the &lt;code&gt;snowflake-apps&lt;/code&gt; skill bundled with CoCo, and on to how you write scale and auto-suspend settings.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Want to get hands-on right away?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The explanation of how things work can wait. Once you have CoCo Desktop, a recent Snowflake CLI, and Node.js 22 or later on your machine, skip ahead to Hands-On: Building a Sales Dashboard from a Prompt. Three steps — hand over a prompt, check it locally, deploy — and you land on an authenticated URL.&lt;/p&gt;

&lt;p&gt;How to write &lt;code&gt;app.yml&lt;/code&gt;, along with the scale and auto-suspend settings, is worth coming back to in "Basic Workflow" when you're ready to run the app in production.&lt;/p&gt;

&lt;p&gt;Note: This article reflects my personal views and does not represent Snowflake's official position.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is Snowflake App Runtime?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Snowflake App Runtime&lt;/strong&gt; is a platform for building and deploying full-stack web applications on Snowflake. The official documentation describes it like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Snowflake App Runtime lets you go from an idea to a live, deployed web application in minutes. No infrastructure to provision, no credentials to configure, no Docker expertise required.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's a summary of its characteristics:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Status&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Generally available (GA)&lt;/strong&gt;. It moved from Public Preview to GA on September 1, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Supported stack&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Builds Node.js apps (especially Next.js). &lt;strong&gt;Python support is also planned&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Runtime&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Runs as a dedicated &lt;strong&gt;&lt;code&gt;APPLICATION SERVICE&lt;/code&gt;&lt;/strong&gt; object on Snowpark Container Services (SPCS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Authentication&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Snowflake SSO is applied &lt;strong&gt;automatically&lt;/strong&gt; — no auth code required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data access&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Directly queries data in the same Snowflake account. No data copies, no external API layer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Public URL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;An authenticated URL in the form &lt;code&gt;https://&amp;lt;id&amp;gt;-&amp;lt;org&amp;gt;-&amp;lt;account&amp;gt;-&amp;lt;region&amp;gt;.snowflakecomputing.app/&lt;/code&gt; is issued automatically&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Where you can use it&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AWS, Azure, and Google Cloud commercial regions. Trial accounts and government regions are out of scope&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here's a point that's easy to trip over. When you hear "runs on SPCS," you might picture the SPCS services you know — the ones where you build a container yourself and run &lt;code&gt;CREATE SERVICE&lt;/code&gt;. But App Runtime uses a &lt;strong&gt;different object type, &lt;code&gt;APPLICATION SERVICE&lt;/code&gt;&lt;/strong&gt;. The big difference is that instead of writing a service specification (spec) file yourself, it deploys from a &lt;strong&gt;versioned package&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The official docs spell this out:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Unlike a Snowpark Container Services service, an Application Service deploys from a versioned package rather than from a user-supplied service specification.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So when you want to check a deployed app, just remember to use &lt;strong&gt;&lt;code&gt;SHOW APPLICATION SERVICES&lt;/code&gt;&lt;/strong&gt; rather than &lt;code&gt;SHOW SERVICES&lt;/code&gt; (I'll come back to this in the "Things to Watch Out For" section).&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture at a Glance
&lt;/h3&gt;

&lt;p&gt;Here's the flow of how App Runtime gets an app running (this uses a Next.js project as the example, but the basic flow is the same for any Node.js app):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7w69b6jjjfa3wnr8hn3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7w69b6jjjfa3wnr8hn3w.png" alt=" " width="798" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All the developer does is "write the app code and run &lt;code&gt;snow app deploy&lt;/code&gt;." Building the container, placing it on SPCS, and wiring up authentication are all handled by Snowflake.&lt;/p&gt;

&lt;p&gt;Official docs: &lt;a href="https://docs.snowflake.com/en/developer-guide/snowflake-app-runtime/about-snowflake-app-runtime" rel="noopener noreferrer"&gt;About Snowflake App Runtime&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Ways to Build Apps — How to Choose
&lt;/h2&gt;

&lt;p&gt;There are currently three main ways to build apps on Snowflake. Plenty of people wonder "which one should I actually use?", so let's sort out where each fits.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Streamlit in Snowflake&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Snowflake App Runtime&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;Native App Framework&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary language&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;JavaScript / TypeScript&lt;/td&gt;
&lt;td&gt;Any (packaged for distribution)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best at&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Data exploration, dashboards, analyst self-serve&lt;/td&gt;
&lt;td&gt;Custom UI, multi-step business flows, rich web experiences&lt;/td&gt;
&lt;td&gt;Distributing/monetizing apps and data across accounts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Frontend&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No need to write it (handled for you)&lt;/td&gt;
&lt;td&gt;Fully customizable&lt;/td&gt;
&lt;td&gt;Fully customizable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Main use&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Internal analytics tools&lt;/td&gt;
&lt;td&gt;Internal web apps in general&lt;/td&gt;
&lt;td&gt;Marketplace publishing, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The official docs position Streamlit and App Runtime like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Streamlit in Snowflake&lt;/strong&gt;: Python-first and guardrailed. You can build a polished data app without writing any frontend code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snowflake App Runtime&lt;/strong&gt;: The full power of the web. Ideal when you need custom UI or rich interactions that leverage the React / Next.js ecosystem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Put simply: &lt;strong&gt;Streamlit when you want to visualize data quickly&lt;/strong&gt;, &lt;strong&gt;App Runtime when you want a web app with elaborate UI or business workflows&lt;/strong&gt;, and &lt;strong&gt;Native Apps when you want to distribute to other companies or accounts&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;My past articles on Snowflake apps &amp;amp; UI (some details may be a bit dated)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Snowflake Data UI Guide - Choose the Right Tool for Every Analytics Use Case&lt;/li&gt;
&lt;li&gt;SiS Container Runtime - Run Streamlit Apps at a Fraction of the Cost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One note on scope: what I build in this article is a dashboard that &lt;strong&gt;reads&lt;/strong&gt; Snowflake tables and displays them. If you want a business app with &lt;strong&gt;frequent writes&lt;/strong&gt; — a request form or an approval workflow, say — putting Snowflake Postgres behind it as the backend is the better fit. I cover that configuration in the follow-up article.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/tsubasa_tech/give-your-snowflake-app-runtime-app-a-real-backend-with-snowflake-postgres-2fgm"&gt;Give Your Snowflake App Runtime App a Real Backend with Snowflake Postgres&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Closer Look at the snowflake-apps Skill (CoCo)
&lt;/h2&gt;

&lt;p&gt;This is the heart of the article. Snowflake App Runtime works on its own, but pairing it with &lt;strong&gt;CoCo&lt;/strong&gt; makes the experience much smoother.&lt;/p&gt;

&lt;p&gt;CoCo ships with a skill called &lt;code&gt;snowflake-apps&lt;/code&gt; (a workflow definition specialized for a particular task), and it supports App Runtime app creation end to end.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisite: Setting Up CoCo Desktop
&lt;/h3&gt;

&lt;p&gt;This article assumes the &lt;strong&gt;CoCo Desktop&lt;/strong&gt; native app for Mac / Windows. If you haven't set it up yet, see the official documentation first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Official docs: &lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code-desktop" rel="noopener noreferrer"&gt;Cortex Code Desktop&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Official docs: &lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code-desktop/building-apps" rel="noopener noreferrer"&gt;Building apps (Cortex Code Desktop)&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since you'll be running a dev server locally, things go more smoothly if you have &lt;strong&gt;Node.js 22 or later&lt;/strong&gt; and a recent Snowflake CLI on your machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the snowflake-apps Skill Takes Care Of
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;snowflake-apps&lt;/code&gt; skill does more than just "scaffold an app." Following App Runtime's conventions, it sets up a foundation like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What the skill provides&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Next.js template&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Copies a scaffold with Next.js + React + snowflake-sdk. No need to start from zero&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;lib/snowflake.ts&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A Snowflake connection helper. Just call &lt;code&gt;querySnowflake()&lt;/code&gt; to run SQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;app.yml&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Auto-generates a single manifest covering the deploy destination, build commands, and display metadata (title, description, icon)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Authentication conventions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in patterns for switching between Owner's Rights and Caller's Rights&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Accessing Data with querySnowflake()
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;querySnowflake()&lt;/code&gt;, provided by &lt;code&gt;lib/snowflake.ts&lt;/code&gt;, is the function you use to run SQL from the app's server side (server components or API routes) and fetch data from Snowflake. The helper takes care of authentication and connection pooling, so you can fetch data by simply &lt;strong&gt;calling &lt;code&gt;querySnowflake()&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;querySnowflake&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/lib/snowflake&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// Run SQL from the app's server side to fetch data&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;querySnowflake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM MY_DB.MY_SCHEMA.SALES&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When you pass user input into SQL, use &lt;strong&gt;bind variables&lt;/strong&gt; rather than string concatenation. This is the basic defense against SQL injection.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;querySnowflake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM ORDERS WHERE CUSTOMER_ID = ? AND STATUS = ?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;binds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For work that might run longer than a few seconds — aggregations, large scans, stored procedure calls — there's &lt;code&gt;querySnowflakeLongRunning()&lt;/code&gt;. It submits the statement, waits for it to finish, and then returns the rows, so you can write it without worrying about timeouts.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;querySnowflakeLongRunning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CALL MY_LONG_JOB()&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For how data access permissions are handled (the authentication mode), you have two choices. This is a spot that's easy to get confused about if you're not used to Snowflake's privilege model, so let's lay it out in a table (Owner's Rights / Caller's Rights are also concepts that come up frequently on the SnowPro certification exams!).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Whose privileges run the SQL&lt;/th&gt;
&lt;th&gt;When to use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Owner's Rights&lt;/strong&gt; (default)&lt;/td&gt;
&lt;td&gt;The app's &lt;strong&gt;execution role&lt;/strong&gt; (on a standard database, the role that owns the app)&lt;/td&gt;
&lt;td&gt;Shared dashboards / reference data where all users see the same thing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Caller's Rights&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The &lt;strong&gt;signed-in user's own&lt;/strong&gt; privileges&lt;/td&gt;
&lt;td&gt;When data should differ per user, or you want row-level security to apply&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To use Caller's Rights, you just add an option to the query.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Run SQL with the signed-in user's privileges (row-level security and so on apply)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;querySnowflake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM MY_DB.MY_SCHEMA.SENSITIVE_TABLE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;callersRights&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Caller's Rights is &lt;strong&gt;available automatically&lt;/strong&gt; on an Application Service. You don't need to write any setting for it in &lt;code&gt;app.yml&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That alone isn't enough to make it work, though. App Runtime's Caller's Rights sits on top of a mechanism called &lt;strong&gt;Restricted Caller's Rights&lt;/strong&gt;, and data becomes readable only when &lt;strong&gt;both&lt;/strong&gt; pieces are in place: &lt;strong&gt;the calling user's own privileges&lt;/strong&gt; and &lt;strong&gt;the caller grants held by the app's execution role&lt;/strong&gt;. So an administrator needs to issue &lt;code&gt;GRANT CALLER&lt;/code&gt; ahead of time, like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="n"&gt;CALLER&lt;/span&gt; &lt;span class="k"&gt;USAGE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;MY_DB&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;SERVICE_OWNER_ROLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="n"&gt;CALLER&lt;/span&gt; &lt;span class="k"&gt;USAGE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;MY_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MY_SCHEMA&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;SERVICE_OWNER_ROLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="n"&gt;CALLER&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="n"&gt;TABLES&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;MY_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MY_SCHEMA&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;SERVICE_OWNER_ROLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you want tables created later to be covered as well, use &lt;strong&gt;&lt;code&gt;GRANT INHERITED CALLER&lt;/code&gt;&lt;/strong&gt; instead of &lt;code&gt;GRANT CALLER&lt;/code&gt;. That form applies to both current and future objects.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="n"&gt;INHERITED&lt;/span&gt; &lt;span class="n"&gt;CALLER&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt; &lt;span class="n"&gt;TABLES&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;MY_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MY_SCHEMA&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;SERVICE_OWNER_ROLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Note that running these &lt;code&gt;GRANT CALLER&lt;/code&gt; statements requires the account-level &lt;strong&gt;&lt;code&gt;MANAGE CALLER GRANTS&lt;/code&gt;&lt;/strong&gt; privilege. If you hit a privilege error, that's the first place to check.&lt;/p&gt;

&lt;p&gt;In other words, Caller's Rights is a two-part setup: &lt;strong&gt;pass &lt;code&gt;{ callersRights: true }&lt;/code&gt; in your code&lt;/strong&gt;, and &lt;strong&gt;issue &lt;code&gt;GRANT CALLER&lt;/code&gt; on the administrator side&lt;/strong&gt;. Being able to choose "whose privileges this runs as" per query, while administrators keep the scope bounded, is a genuinely convenient point from a governance standpoint.&lt;/p&gt;

&lt;p&gt;No connection string, no external auth layer. Call &lt;code&gt;querySnowflake()&lt;/code&gt; from the server side and you can read tables in the same account. Only when you want what each user sees to differ do you need those separate &lt;code&gt;GRANT CALLER&lt;/code&gt; statements from an administrator.&lt;/p&gt;

&lt;p&gt;Official docs: &lt;a href="https://docs.snowflake.com/en/developer-guide/snowflake-app-runtime/query-snowflake" rel="noopener noreferrer"&gt;Query Snowflake&lt;/a&gt; / &lt;a href="https://docs.snowflake.com/en/developer-guide/restricted-callers-rights" rel="noopener noreferrer"&gt;Restricted caller's rights&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The &lt;code&gt;snow app&lt;/code&gt; CLI Command Surface
&lt;/h3&gt;

&lt;p&gt;Deployment and lifecycle management are done with the Snowflake CLI's &lt;code&gt;snow app&lt;/code&gt; command. &lt;code&gt;snow app&lt;/code&gt; handles both Native Apps and App Runtime, and routes automatically based on your project layout.&lt;/p&gt;

&lt;p&gt;That said, you don't need to memorize these commands one by one. Basically, &lt;strong&gt;CoCo gets the context from the &lt;code&gt;snowflake-apps&lt;/code&gt; skill and runs the right commands for you&lt;/strong&gt;, so all you have to do is say "deploy it." I'm listing the main commands here just so you understand "what's happening behind the scenes."&lt;/p&gt;

&lt;p&gt;The main subcommands are as follows:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;snow app setup&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Initialize the project and generate &lt;code&gt;app.yml&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;snow app bundle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Resolve the artifacts to upload, locally (no connection required)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;snow app validate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Validate &lt;code&gt;app.yml&lt;/code&gt; and confirm the deploy destination exists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;snow app deploy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run upload → remote build → deploy in one shot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;snow app open&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Open the deployed app in a browser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;snow app events --last N&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fetch the app's container logs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;snow app teardown&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Remove the app and related resources&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;snow app deploy&lt;/code&gt; is made up of three phases — upload, build, and deploy — and you can run just one of them with a flag.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;What runs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;(none)&lt;/td&gt;
&lt;td&gt;All three phases, in order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--upload-only&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Upload the source only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--build-only&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Remote build only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--promote-only&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Skip upload and build, and apply the manifest only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: When you want to skip the build and reflect only configuration changes, use &lt;strong&gt;&lt;code&gt;--promote-only&lt;/code&gt;&lt;/strong&gt;. The &lt;code&gt;--deploy-only&lt;/code&gt; you'll see in older material is treated as a deprecated alias for the same thing. It still works, but &lt;code&gt;--promote-only&lt;/code&gt; is the one to reach for going forward.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Official docs: &lt;a href="https://docs.snowflake.com/en/developer-guide/snowflake-cli/command-reference/snowflake-app-runtime-commands/overview" rel="noopener noreferrer"&gt;Snowflake Apps CLI commands&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Writing your deploy configuration in &lt;code&gt;app.yml&lt;/code&gt; requires a &lt;strong&gt;recent Snowflake CLI&lt;/strong&gt;. You can check with &lt;code&gt;snow helpers check-version&lt;/code&gt; (more on this in "Things to Watch Out For" below).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Basic Workflow
&lt;/h2&gt;

&lt;p&gt;The basic flow for getting an App Runtime app up and running is these five steps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xel46muuzc0skef3sp2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xel46muuzc0skef3sp2.png" alt=" " width="800" height="1761"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  One app.yml for Everything
&lt;/h3&gt;

&lt;p&gt;It used to be a two-file arrangement: the deploy destination in &lt;code&gt;snowflake.yml&lt;/code&gt;, and build settings alone in &lt;code&gt;app.yml&lt;/code&gt;. Today &lt;strong&gt;it's all consolidated into &lt;code&gt;app.yml&lt;/code&gt;&lt;/strong&gt;. The key point is to put &lt;code&gt;version: 2&lt;/code&gt; at the top. Without that one line, the CLI won't read the deploy configuration in &lt;code&gt;app.yml&lt;/code&gt; at all.&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;snow app setup&lt;/code&gt; generates this &lt;code&gt;app.yml&lt;/code&gt;. The minimal form looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SALES_DASHBOARD&lt;/span&gt;            &lt;span class="c1"&gt;# Application Service name&lt;/span&gt;
&lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SNOWFLAKE_APPS&lt;/span&gt;         &lt;span class="c1"&gt;# destination database&lt;/span&gt;
&lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PUBLIC&lt;/span&gt;                   &lt;span class="c1"&gt;# destination schema&lt;/span&gt;
&lt;span class="na"&gt;query_warehouse&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MY_QUERY_WH&lt;/span&gt;     &lt;span class="c1"&gt;# warehouse the app uses for queries&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Only those five keys are required (&lt;code&gt;version&lt;/code&gt; / &lt;code&gt;name&lt;/code&gt; / &lt;code&gt;database&lt;/code&gt; / &lt;code&gt;schema&lt;/code&gt; / &lt;code&gt;query_warehouse&lt;/code&gt;). Add display metadata and build commands on top of that, and you get something like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SALES_DASHBOARD&lt;/span&gt;
&lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SNOWFLAKE_APPS&lt;/span&gt;
&lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PUBLIC&lt;/span&gt;
&lt;span class="na"&gt;query_warehouse&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MY_QUERY_WH&lt;/span&gt;

&lt;span class="c1"&gt;# App title, description, and icon&lt;/span&gt;
&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Sales Dashboard&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;An app that visualizes online retail sales&lt;/span&gt;
&lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;public/icon.svg&lt;/span&gt;

&lt;span class="c1"&gt;# Patterns excluded from upload&lt;/span&gt;
&lt;span class="na"&gt;ignore&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;node_modules&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.env*&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.next&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.git&lt;/span&gt;

&lt;span class="c1"&gt;# Build and start commands&lt;/span&gt;
&lt;span class="na"&gt;install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;npm&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;ci&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;npm&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;node&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;.next/standalone/server.js&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you omit &lt;code&gt;install&lt;/code&gt; / &lt;code&gt;build&lt;/code&gt; / &lt;code&gt;run&lt;/code&gt;, they default to &lt;code&gt;npm ci&lt;/code&gt; / &lt;code&gt;npm run build&lt;/code&gt; / &lt;code&gt;npm start&lt;/code&gt; respectively. You declare &lt;code&gt;run&lt;/code&gt; explicitly when you need a start command that differs from the default — for example running Next.js with &lt;code&gt;output: 'standalone'&lt;/code&gt;. Note that those three keys are &lt;strong&gt;top-level only&lt;/strong&gt; (putting them under &lt;code&gt;targets&lt;/code&gt;, covered below, has no effect).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Title, description, and icon go in the &lt;strong&gt;top-level&lt;/strong&gt; &lt;code&gt;label&lt;/code&gt; / &lt;code&gt;description&lt;/code&gt; / &lt;code&gt;icon&lt;/code&gt;. The &lt;code&gt;profile:&lt;/code&gt; block used by the older format is no longer read, and leaving it in place means &lt;strong&gt;the title, description, and icon disappear on every deploy&lt;/strong&gt;. When migrating an existing project, don't forget to fix this.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One more thing: deploying with &lt;code&gt;app.yml&lt;/code&gt; is &lt;strong&gt;declarative&lt;/strong&gt;. The whole manifest is applied each time, so &lt;strong&gt;any field you don't write goes back to its default&lt;/strong&gt;. That property comes up again in the next section, so it's worth keeping in the back of your mind.&lt;/p&gt;

&lt;p&gt;Official docs: &lt;a href="https://docs.snowflake.com/en/developer-guide/snowflake-app-runtime/app-yml" rel="noopener noreferrer"&gt;app.yml manifest for Snowflake App Runtime&lt;/a&gt; / &lt;a href="https://docs.snowflake.com/en/developer-guide/snowflake-app-runtime/migrate-to-app-yml" rel="noopener noreferrer"&gt;Migrate from snowflake.yml to app.yml&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Scale and Auto-Suspend in app.yml
&lt;/h3&gt;

&lt;p&gt;Instance counts and stopping on idle are &lt;strong&gt;just a few lines in &lt;code&gt;app.yml&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Add instances as traffic grows&lt;/span&gt;
&lt;span class="na"&gt;min_instances&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="na"&gt;max_instances&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;

&lt;span class="c1"&gt;# Auto-suspend after 15 minutes of idle time, and resume when a request arrives&lt;/span&gt;
&lt;span class="na"&gt;auto_suspend_secs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;900&lt;/span&gt;
&lt;span class="na"&gt;auto_resume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here's what each one means, along with its default:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Constraint&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;min_instances&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fewest instances to run while the app is up&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;At least 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max_instances&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Most instances to scale up to&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;At least &lt;code&gt;min_instances&lt;/code&gt;, and &lt;strong&gt;no more than 10&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;auto_suspend_secs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Auto-suspend after this many idle seconds&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0&lt;/code&gt; (disabled)&lt;/td&gt;
&lt;td&gt;If non-zero, must be &lt;strong&gt;300 or more&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;auto_resume&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Whether to resume automatically when a request arrives&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Set &lt;code&gt;max_instances&lt;/code&gt; higher than &lt;code&gt;min_instances&lt;/code&gt; and &lt;strong&gt;Snowflake adds and removes instances based on CPU utilization&lt;/strong&gt;. It's the same CPU-based autoscaling mechanism as SPCS.&lt;/p&gt;

&lt;p&gt;The thing to internalize here is that &lt;strong&gt;you're billed per node, not per instance&lt;/strong&gt;. Multiple instances are packed onto the same node while there's room, and a new node is added only once the existing ones are full. So raising &lt;code&gt;max_instances&lt;/code&gt; doesn't directly translate into more nodes.&lt;/p&gt;

&lt;p&gt;Going the other way, &lt;strong&gt;lowering the instance count won't take you to zero&lt;/strong&gt;. A running service keeps at least one instance, so to stop it completely you suspend it explicitly.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Stop it&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="n"&gt;APPLICATION&lt;/span&gt; &lt;span class="n"&gt;SERVICE&lt;/span&gt; &lt;span class="n"&gt;MY_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MY_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MY_APP&lt;/span&gt; &lt;span class="n"&gt;SUSPEND&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Resume it&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="n"&gt;APPLICATION&lt;/span&gt; &lt;span class="n"&gt;SERVICE&lt;/span&gt; &lt;span class="n"&gt;MY_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MY_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MY_APP&lt;/span&gt; &lt;span class="n"&gt;RESUME&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Set &lt;code&gt;auto_suspend_secs&lt;/code&gt; and you can automate that stop. Apps basically keep running once deployed, so &lt;strong&gt;it's worth setting for any app that has idle stretches in its day&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you change instance counts or auto-suspend with &lt;code&gt;ALTER APPLICATION SERVICE&lt;/code&gt;, &lt;strong&gt;the next &lt;code&gt;snow app deploy&lt;/code&gt; rolls that change back to what's in &lt;code&gt;app.yml&lt;/code&gt;&lt;/strong&gt; (or to the defaults, if you didn't write it there). Anything you want to stick permanently belongs in &lt;code&gt;app.yml&lt;/code&gt;. This is where the declarative deploy from the previous section comes into play.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Official docs: &lt;a href="https://docs.snowflake.com/en/developer-guide/snowflake-app-runtime/scale-and-suspend" rel="noopener noreferrer"&gt;Scale and suspend Snowflake App Runtime apps&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Environment Variables, Secrets, and External Access in app.yml Too
&lt;/h3&gt;

&lt;p&gt;Configuration values, credentials, and permission to reach external networks all go in &lt;code&gt;app.yml&lt;/code&gt; as well.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Environment variables passed to the container (non-sensitive config values)&lt;/span&gt;
&lt;span class="na"&gt;environment_variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LOG_LEVEL&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;INFO"&lt;/span&gt;

&lt;span class="c1"&gt;# Mount a Snowflake secret object&lt;/span&gt;
&lt;span class="na"&gt;secrets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;API_KEY&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MY_DB.MY_SCHEMA.API_KEY_SECRET&lt;/span&gt;

&lt;span class="c1"&gt;# External Access Integration (EAI) for the running app's egress to external hosts&lt;/span&gt;
&lt;span class="na"&gt;external_access_integrations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;my_api_integration&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A secret listed under &lt;code&gt;secrets&lt;/code&gt; is mounted as &lt;strong&gt;files under &lt;code&gt;/secrets/&amp;lt;name&amp;gt;/&lt;/code&gt;&lt;/strong&gt; rather than as an environment variable. Handy when you'd rather not put a password in an environment variable.&lt;/p&gt;

&lt;p&gt;For external access, note that &lt;strong&gt;build time and run time use different fields&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;When it applies&lt;/th&gt;
&lt;th&gt;What it's for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;build_eai&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Build time&lt;/td&gt;
&lt;td&gt;npm and Google Fonts are allowed by default. Use this when the build needs additional destinations, such as a private registry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;external_access_integrations&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run time&lt;/td&gt;
&lt;td&gt;When the app connects to an external API or to Snowflake Postgres&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: External access for a running app used to require attaching the integration with &lt;code&gt;ALTER APPLICATION SERVICE&lt;/code&gt; (the follow-up article mentioned earlier shows that approach). You can now write it in &lt;code&gt;app.yml&lt;/code&gt; under &lt;code&gt;external_access_integrations&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Switching Between dev / stage / prod (Deploy Targets)
&lt;/h3&gt;

&lt;p&gt;When you want to deploy the same project to multiple environments, use &lt;code&gt;targets&lt;/code&gt;. The trick is to put shared configuration at the top level and give &lt;strong&gt;each target only the differences&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;

&lt;span class="c1"&gt;# Everything below is the baseline that every target inherits&lt;/span&gt;
&lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SNOWFLAKE_APPS&lt;/span&gt;
&lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PUBLIC&lt;/span&gt;
&lt;span class="na"&gt;query_warehouse&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MY_QUERY_WH&lt;/span&gt;
&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Sales Dashboard&lt;/span&gt;
&lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;public/icon.svg&lt;/span&gt;

&lt;span class="na"&gt;default_target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dev&lt;/span&gt;

&lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;dev&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SALES_DASHBOARD_DEV&lt;/span&gt;
    &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;USER$&lt;/span&gt;              &lt;span class="c1"&gt;# place it in the personal database&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SALES_DASHBOARD_STAGE&lt;/span&gt;
  &lt;span class="na"&gt;prod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SALES_DASHBOARD_PROD&lt;/span&gt;
    &lt;span class="na"&gt;query_warehouse&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PROD_WH&lt;/span&gt;
    &lt;span class="na"&gt;min_instances&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
    &lt;span class="na"&gt;max_instances&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You switch with &lt;code&gt;--target&lt;/code&gt; at deploy time. Omit it and &lt;code&gt;default_target&lt;/code&gt; is used.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;snow app deploy &lt;span class="nt"&gt;--target&lt;/span&gt; prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;snow app open&lt;/code&gt; / &lt;code&gt;events&lt;/code&gt; / &lt;code&gt;teardown&lt;/code&gt; / &lt;code&gt;validate&lt;/code&gt; all accept &lt;code&gt;--target&lt;/code&gt; too, so you can keep working per environment without breaking stride.&lt;/p&gt;

&lt;p&gt;Writing &lt;code&gt;database: USER$&lt;/code&gt; deploys to that user's &lt;strong&gt;personal database&lt;/strong&gt;. It's convenient for experimenting during development, but &lt;strong&gt;an app placed in a personal database can't be shared with other roles&lt;/strong&gt;. For an app your team will use, specify a standard database.&lt;/p&gt;

&lt;p&gt;Official docs: &lt;a href="https://docs.snowflake.com/en/developer-guide/snowflake-app-runtime/deploy-targets" rel="noopener noreferrer"&gt;Deploy targets&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Hands-On: Building a Sales Dashboard from a Prompt
&lt;/h2&gt;

&lt;p&gt;From here, I'll walk through how I actually built a sales dashboard app in CoCo Desktop. The subject is the sales data of a fictional online retailer, "Glacier Style" (&lt;code&gt;GLACIERSTYLE_DB.EC_ANALYTICS_SCHEMA&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;app.yml&lt;/code&gt; covered in the previous chapter is something CoCo generates for you as part of this flow. If you started reading here, there's nothing you need to write by hand.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: Give CoCo a Prompt
&lt;/h3&gt;

&lt;p&gt;In the CoCo Desktop chat, select &lt;code&gt;/snowflake-apps&lt;/code&gt; (or use the "Build an app" starter card), then describe the app you want in natural language. Here's roughly the prompt I gave:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/snowflake-apps
Using the sales data in GLACIERSTYLE_DB.EC_ANALYTICS_SCHEMA,
build a sales dashboard that runs on Snowflake App Runtime, in Next.js.
Deploy the app itself to the GLACIERSTYLE_DB.APPS schema.

- Show KPIs (sales, order count, average order value, completion rate) as cards
- Filters to narrow by period, channel, and category
- Charts for sales by category, by channel, and the monthly trend
- Use a cool, glacier-inspired color palette
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;There are two points worth highlighting here. First, the prompt explicitly invokes the &lt;code&gt;/snowflake-apps&lt;/code&gt; skill at the top. Second, it &lt;strong&gt;explicitly specifies &lt;code&gt;GLACIERSTYLE_DB.APPS&lt;/code&gt; as the deployment target&lt;/strong&gt;. If you don't specify a target, the app may be placed in your personal database and become impossible to share with other roles — so if you have internal sharing in mind, it's best to specify it up front.&lt;/p&gt;

&lt;p&gt;When CoCo receives this prompt, it launches the &lt;code&gt;snowflake-apps&lt;/code&gt; skill, first runs &lt;code&gt;DESCRIBE&lt;/code&gt; on the target tables to understand the schema, then copies the Next.js template and implements &lt;code&gt;app/page.tsx&lt;/code&gt;, the API routes, the chart components, and the styling — all in one pass, according to your requirements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegk1xjlehtly34x2h5tk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fegk1xjlehtly34x2h5tk.png" alt="Entering a prompt like the above in the CoCo Desktop chat" width="576" height="184"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 2: Preview Locally
&lt;/h3&gt;

&lt;p&gt;Once the implementation is done, CoCo starts a local development server (&lt;code&gt;npm run dev&lt;/code&gt;) and checks that it works. During local development, the Snowflake connection automatically falls back to your local connection info (&lt;code&gt;connections.toml&lt;/code&gt;), so you can verify the look and the numbers against real data before deploying.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcrjosqmgtr7u80wkh6gz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcrjosqmgtr7u80wkh6gz.png" alt="The local preview started with  raw `npm run dev` endraw " width="800" height="611"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 3: Deploy
&lt;/h3&gt;

&lt;p&gt;Once the look and the numbers check out, it's time to deploy. Tell CoCo to "deploy it," and &lt;code&gt;snow app deploy&lt;/code&gt; runs.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;snow app deploy &lt;span class="nt"&gt;--verbose&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This single command automatically runs through uploading the source → building the container remotely → creating the &lt;code&gt;APPLICATION SERVICE&lt;/code&gt;. The first build takes a little while (more on that below), and when it's done, an authenticated URL is issued.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz70fb4g791orzbpqb2ss.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz70fb4g791orzbpqb2ss.png" alt="The  raw `snow app deploy --verbose` endraw  run log" width="545" height="50"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 4: Verify It's Running
&lt;/h3&gt;

&lt;p&gt;Once deployment completes, you can access the app at a URL of the form &lt;code&gt;https://&amp;lt;id&amp;gt;-&amp;lt;org&amp;gt;-&amp;lt;account&amp;gt;-&amp;lt;region&amp;gt;.snowflakecomputing.app/&lt;/code&gt;. This URL is protected by Snowflake SSO, so only authenticated users can use it.&lt;/p&gt;

&lt;p&gt;You can also confirm the deployed app via SQL:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;APPLICATION&lt;/span&gt; &lt;span class="n"&gt;SERVICES&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;GLACIERSTYLE_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APPS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name                  : GLACIER_SALES_APP
status                : RUNNING
database_name         : GLACIERSTYLE_DB
schema_name           : APPS
query_warehouse       : GLACIERSTYLE_WH
compute_pool          :
url                   : &amp;lt;id&amp;gt;-&amp;lt;org&amp;gt;-&amp;lt;account&amp;gt;-&amp;lt;region&amp;gt;.snowflakecomputing.app
auto_resume           : true
auto_suspend_secs     : 0
min_instances         : 1
max_instances         : 1
current_instances     : 1
source                : {"artifactRepository":"GLACIERSTYLE_DB.APPS.GLACIER_SALES_APP_REPO","version":"VERSION$2","alias":"LATEST","package":"GLACIER_SALES_APP"}
additional_properties : {"label":"Glacier Style Sales Dashboard","icon":"public/icon.svg"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The status is &lt;code&gt;RUNNING&lt;/code&gt;, and you can see it's deployed to &lt;code&gt;GLACIERSTYLE_DB.APPS&lt;/code&gt; exactly as specified, under version management. The &lt;code&gt;min_instances&lt;/code&gt; / &lt;code&gt;max_instances&lt;/code&gt; / &lt;code&gt;auto_suspend_secs&lt;/code&gt; / &lt;code&gt;auto_resume&lt;/code&gt; settings from the previous section show up as columns here as well. In this example &lt;code&gt;auto_suspend_secs&lt;/code&gt; is &lt;code&gt;0&lt;/code&gt;, so auto-suspend is still disabled and the app stays up around the clock.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;compute_pool&lt;/code&gt; column is empty because App Runtime runs on a &lt;strong&gt;Snowflake-managed compute pool&lt;/strong&gt; (I'll add a note on this in "Things to Watch Out For").&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fve9e4ymg6w6p2fy2uryq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fve9e4ymg6w6p2fy2uryq.png" alt="The running sales dashboard opened at the issued authenticated URL" width="800" height="578"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scaffold from a prompt, confirm the numbers with &lt;code&gt;npm run dev&lt;/code&gt;, then check for &lt;code&gt;RUNNING&lt;/code&gt; with &lt;code&gt;SHOW APPLICATION SERVICES&lt;/code&gt; after &lt;code&gt;snow app deploy&lt;/code&gt;. You can get all the way through that without writing a container definition file.&lt;/p&gt;


An aggregation SQL aside: watch for duplicates in dimension tables

There's one thing to watch in your aggregation SQL too. If a dimension table contains duplicate rows for the same ID, joining it directly will inflate your counts (fanout). Deduplicate first with `QUALIFY ROW_NUMBER() OVER (PARTITION BY  ORDER BY ) = 1` before joining, and you'll get correct aggregates. Checking the nature of your data is essential even when building an app.


&lt;h2&gt;
  
  
  Things to Watch Out For
&lt;/h2&gt;

&lt;p&gt;Here are some points worth keeping in mind when you actually build an app — things you won't see by just skimming the official docs. Knowing them up front should help you move along smoothly without stumbling.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Mind the CLI version
&lt;/h3&gt;

&lt;p&gt;Writing your deploy configuration in &lt;code&gt;app.yml&lt;/code&gt; requires a recent Snowflake CLI. An older CLI &lt;strong&gt;silently ignores&lt;/strong&gt; the deploy configuration in &lt;code&gt;app.yml&lt;/code&gt; and goes looking for &lt;code&gt;snowflake.yml&lt;/code&gt;, which shows up as the confusing symptom of "I changed the setting but nothing happened" or "it deployed with the old values." Check with &lt;code&gt;snow helpers check-version&lt;/code&gt; and update with &lt;code&gt;pip install --upgrade snowflake-cli&lt;/code&gt; before you start.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. &lt;code&gt;app.yml&lt;/code&gt; is declarative, so anything you forget to write disappears
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;snow app deploy&lt;/code&gt; applies the contents of &lt;code&gt;app.yml&lt;/code&gt; &lt;strong&gt;as a whole&lt;/strong&gt; every time. So &lt;strong&gt;removing a field you had written previously resets that setting to its default&lt;/strong&gt;. Manual changes made with &lt;code&gt;ALTER APPLICATION SERVICE&lt;/code&gt; get rolled back on the next deploy too.&lt;/p&gt;

&lt;p&gt;The case that trips people up most is leaving an old-format &lt;code&gt;profile:&lt;/code&gt; block in place. Since &lt;code&gt;profile:&lt;/code&gt; is no longer read, the title, description, and icon &lt;strong&gt;disappear on every deploy&lt;/strong&gt;. Move &lt;code&gt;label&lt;/code&gt; / &lt;code&gt;description&lt;/code&gt; / &lt;code&gt;icon&lt;/code&gt; to the top level.&lt;/p&gt;

&lt;p&gt;Adopt "anything I want to stick permanently goes in &lt;code&gt;app.yml&lt;/code&gt;" as your rule and you won't get lost.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. &lt;code&gt;snow app setup&lt;/code&gt; needs a warehouse, and watch the deploy target
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;snow app setup&lt;/code&gt; requires a query warehouse. If you see a &lt;code&gt;Missing warehouse&lt;/code&gt; error, pass &lt;code&gt;--warehouse&lt;/code&gt; or set the account parameter &lt;code&gt;DEFAULT_SNOWFLAKE_APPS_QUERY_WAREHOUSE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The deploy target deserves extra care. Unlike &lt;code&gt;snowflake.yml&lt;/code&gt;, &lt;code&gt;app.yml&lt;/code&gt; &lt;strong&gt;doesn't fill in the database or schema from your connection info&lt;/strong&gt;. If &lt;code&gt;name&lt;/code&gt; / &lt;code&gt;database&lt;/code&gt; / &lt;code&gt;schema&lt;/code&gt; / &lt;code&gt;query_warehouse&lt;/code&gt; can't be resolved from the manifest alone, the deploy fails with &lt;code&gt;Missing required field(s)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also, an app placed in a personal database with &lt;code&gt;database: USER$&lt;/code&gt; can't be shared with other roles, so if you have internal sharing in mind, it's best to specify a standard database and schema. State the destination in your prompt and CoCo will reflect it in this configuration for you.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. The compute pool is Snowflake-managed, by design
&lt;/h3&gt;

&lt;p&gt;App Runtime runs on an SPCS compute pool, but &lt;strong&gt;the pool is Snowflake-managed and fixed&lt;/strong&gt; — you can't point it at a pool you created yourself, and &lt;code&gt;app.yml&lt;/code&gt; has no field for specifying one.&lt;/p&gt;

&lt;p&gt;As a result, you don't need to create a compute pool yourself, nor set up an External Access Integration for fetching npm packages (remote builds already allow npm and Google Fonts by default). Being able to start without worrying about infrastructure is a big plus. This is also why the &lt;code&gt;compute_pool&lt;/code&gt; column is empty on a deployed app.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. Next.js standalone builds need an explicit static asset copy
&lt;/h3&gt;

&lt;p&gt;The build service used to &lt;strong&gt;copy &lt;code&gt;.next/static&lt;/code&gt; and &lt;code&gt;public/&lt;/code&gt; into the standalone directory automatically&lt;/strong&gt; when Next.js was set to &lt;code&gt;output: 'standalone'&lt;/code&gt;. The current build service runs only the commands you write under &lt;code&gt;build:&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So if you migrate a project that got by with just &lt;code&gt;npm run build&lt;/code&gt;, you'll see the symptom where &lt;strong&gt;the app opens but CSS and images come back 404&lt;/strong&gt;. Write the copy steps out explicitly.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;npm&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;cp&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;-r&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;.next/static&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;.next/standalone/.next/static&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;cp&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;-r&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;public&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;.next/standalone/public&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If your project has no &lt;code&gt;public/&lt;/code&gt; directory, you don't need that last line.&lt;/p&gt;
&lt;h3&gt;
  
  
  6. Deployment spends more time on "endpoint provisioning" than the build
&lt;/h3&gt;

&lt;p&gt;With &lt;code&gt;snow app deploy&lt;/code&gt;, the remote build itself finishes relatively quickly, and the subsequent &lt;strong&gt;endpoint provisioning (&lt;code&gt;Endpoints provisioning in progress...&lt;/code&gt;) can take a few minutes&lt;/strong&gt;. Even if the log looks stuck on the same line, work is progressing — so wait until &lt;code&gt;App ready at https://...&lt;/code&gt; appears. When you want to reflect a configuration-only change quickly without touching code, &lt;code&gt;snow app deploy --promote-only&lt;/code&gt; lets you skip the upload and build.&lt;/p&gt;
&lt;h3&gt;
  
  
  7. Watch the connection's role during local development
&lt;/h3&gt;

&lt;p&gt;During local &lt;code&gt;npm run dev&lt;/code&gt;, &lt;code&gt;querySnowflake()&lt;/code&gt; automatically falls back to the default connection in &lt;code&gt;~/.snowflake/connections.toml&lt;/code&gt;. If the connection has no role set, it runs with the default role, which can lead to a &lt;code&gt;Database '...' does not exist or not authorized&lt;/code&gt; error. Set a role that can access the target data on the connection, or specify it via the &lt;code&gt;SNOWFLAKE_ROLE&lt;/code&gt; environment variable.&lt;/p&gt;

&lt;p&gt;Note that &lt;code&gt;{ callersRights: true }&lt;/code&gt; &lt;strong&gt;has no effect when running locally&lt;/strong&gt;. The helper just uses your local connection and emits a warning. If you want to confirm Caller's Rights behavior, check it after deploying.&lt;/p&gt;
&lt;h3&gt;
  
  
  8. A deployed app doesn't show up in &lt;code&gt;SHOW SERVICES&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Because App Runtime runs as a separate object type, &lt;code&gt;APPLICATION SERVICE&lt;/code&gt;, a deployed app does not appear in &lt;code&gt;SHOW SERVICES&lt;/code&gt;. Use &lt;strong&gt;&lt;code&gt;SHOW APPLICATION SERVICES&lt;/code&gt;&lt;/strong&gt; to check it. The ordinary SPCS commands &lt;code&gt;CREATE SERVICE&lt;/code&gt; / &lt;code&gt;ALTER SERVICE&lt;/code&gt; don't work either, so reach for the &lt;code&gt;APPLICATION SERVICE&lt;/code&gt; variants. The reliable way to judge a successful deploy is to look at the CLI output (&lt;code&gt;App ready at https://...&lt;/code&gt; and the URL).&lt;/p&gt;
&lt;h3&gt;
  
  
  9. Stop apps you're not using
&lt;/h3&gt;

&lt;p&gt;Apps basically keep running once deployed. &lt;strong&gt;Compute stays up even with no traffic&lt;/strong&gt;, so an app you've stopped using is worth suspending with &lt;code&gt;ALTER APPLICATION SERVICE ... SUSPEND&lt;/code&gt; or removing with &lt;code&gt;DROP APPLICATION SERVICE&lt;/code&gt;. For an app that's only used during certain hours, setting &lt;code&gt;auto_suspend_secs&lt;/code&gt; is the easy option.&lt;/p&gt;

&lt;p&gt;You can check account-wide usage by the hour in &lt;code&gt;SNOWFLAKE.ACCOUNT_USAGE.SNOWFLAKE_APP_RUNTIME_COMPUTE_HISTORY&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;START_TIME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END_TIME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CREDITS_USED&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;SNOWFLAKE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ACCOUNT_USAGE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SNOWFLAKE_APP_RUNTIME_COMPUTE_HISTORY&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;START_TIME&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;DATEADD&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'day'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;START_TIME&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Since every app in the account shares a single managed compute pool, what this view gives you is &lt;strong&gt;account-level credits&lt;/strong&gt;. Per-app cost attribution isn't available. Billing is per &lt;strong&gt;node&lt;/strong&gt;, not per instance: App Runtime packs multiple instances onto a node while there's room, and only adds a node once the existing ones are full. So you don't need to think about "how many apps fit" as a compute pool sizing question.&lt;/p&gt;

&lt;p&gt;Cost is the &lt;em&gt;only&lt;/em&gt; thing that's account-level. Service state, logs, and metrics are all available per app, as follows.&lt;/p&gt;
&lt;h3&gt;
  
  
  10. Check state, logs, and metrics per app
&lt;/h3&gt;

&lt;p&gt;There's no need to go poking at the compute pool. App Runtime's observability is built around the &lt;strong&gt;app (&lt;code&gt;APPLICATION SERVICE&lt;/code&gt;)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Start with state, via &lt;code&gt;DESCRIBE APPLICATION SERVICE&lt;/code&gt;. A service reports states such as &lt;code&gt;PENDING&lt;/code&gt;, &lt;code&gt;RUNNING&lt;/code&gt;, &lt;code&gt;SUSPENDED&lt;/code&gt;, and &lt;code&gt;FAILED&lt;/code&gt;, which is how you catch the "I thought it was up, but it had died" case.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DESCRIBE&lt;/span&gt; &lt;span class="n"&gt;APPLICATION&lt;/span&gt; &lt;span class="n"&gt;SERVICE&lt;/span&gt; &lt;span class="n"&gt;APP_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MY_APP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For logs, you can pull the container logs directly. From SQL, use &lt;code&gt;SYSTEM$GET_APPLICATION_SERVICE_LOGS&lt;/code&gt;: the second argument is the line count (default 500), and the third selects an instance by number. The role running it needs the &lt;code&gt;MONITOR&lt;/code&gt; privilege on the service.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;SYSTEM&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;GET_APPLICATION_SERVICE_LOGS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'APP_DB.APP.MY_APP'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The CLI is handier still, and gives you &lt;strong&gt;CPU / memory / network metrics&lt;/strong&gt; and lifecycle events on top of logs.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Recent logs (500 lines by default; size it with --last)&lt;/span&gt;
snow app events

&lt;span class="c"&gt;# Historical logs via the event table (works even after a suspend)&lt;/span&gt;
snow app events &lt;span class="nt"&gt;--type&lt;/span&gt; log &lt;span class="nt"&gt;--since&lt;/span&gt; 6h

&lt;span class="c"&gt;# CPU / memory / network metrics&lt;/span&gt;
snow app events &lt;span class="nt"&gt;--type&lt;/span&gt; metric &lt;span class="nt"&gt;--metric&lt;/span&gt; cpu &lt;span class="nt"&gt;--since&lt;/span&gt; 1h

&lt;span class="c"&gt;# Service and container state changes&lt;/span&gt;
snow app events &lt;span class="nt"&gt;--type&lt;/span&gt; lifecycle &lt;span class="nt"&gt;--since&lt;/span&gt; 2d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ask CoCo to "show me the logs for this app" and it will run these for you and walk through what they say. When a deploy fails, this is the fastest path to narrowing down the cause.&lt;/p&gt;

&lt;p&gt;Official docs: &lt;a href="https://docs.snowflake.com/en/developer-guide/snowflake-app-runtime/observability" rel="noopener noreferrer"&gt;Observability for Snowflake App Runtime&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Business Value and Use Cases
&lt;/h2&gt;

&lt;p&gt;The technical ease is what we've seen so far, but where App Runtime really shines is the &lt;strong&gt;business and organizational angle&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Governance stays intact&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Because the app runs inside Snowflake's security perimeter, it inherits RBAC, audit logging, SSO, and data governance as-is&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;No data movement&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No data copies or external API layer needed, reducing the risk of data leaking outside or to the app side&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Integrated authentication&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;An authenticated URL is issued automatically — no separate login infrastructure required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Easier to build in-house&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Since Snowflake handles infrastructure, Docker, and server management, you can ship internal apps without creating shadow IT&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Concrete use cases include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Internal data visualization dashboards&lt;/strong&gt;: Department-level KPIs delivered in an easy-to-read custom UI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internal search / reference tools&lt;/strong&gt;: Reference apps that control what each user can see via Caller's Rights&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Entry forms and approval workflows&lt;/strong&gt;: Business apps where requests get created and updated. For these write-heavy cases, start with the configuration that puts Snowflake Postgres behind the app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For organizations where "the data is in Snowflake, but the apps that use it rely on outsourcing or a separate platform," this looks like an option that shortens the path to building in-house.&lt;/p&gt;
&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;As handy as it is, there are some limitations to be aware of.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note (limitations):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Not available on trial accounts&lt;/strong&gt; (a paid account is required)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not available in government regions.&lt;/strong&gt; AWS, Azure, and Google Cloud commercial regions are in scope&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apps deployed to a personal database (&lt;code&gt;USER$...&lt;/code&gt;) can't be shared with other roles.&lt;/strong&gt; To share, place it in a standard database&lt;/li&gt;
&lt;li&gt;Each build produces an &lt;strong&gt;immutable version&lt;/strong&gt;. You can't overwrite an existing version, so every change needs a new build&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CREATE OR REPLACE APPLICATION SERVICE&lt;/code&gt; isn't supported. Use &lt;code&gt;CREATE OR ALTER APPLICATION SERVICE&lt;/code&gt; instead&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;UNDROP&lt;/code&gt; isn't supported, so &lt;strong&gt;a dropped &lt;code&gt;APPLICATION SERVICE&lt;/code&gt; can't be brought back&lt;/strong&gt;. That said, the artifact repository that holds your built versions (&lt;code&gt;&amp;lt;app_name&amp;gt;_REPO&lt;/code&gt;) is a separate object from the service, so dropping the service leaves the repository in place. To bring the app back, you deploy it again&lt;/li&gt;
&lt;li&gt;The supported stack centers on Node.js / Next.js (&lt;strong&gt;Python support is also planned&lt;/strong&gt;, and coverage is expected to expand over time)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Please check the official documentation for the latest limitations.&lt;/p&gt;

&lt;p&gt;Official docs: &lt;a href="https://docs.snowflake.com/en/developer-guide/snowflake-app-runtime/limitations" rel="noopener noreferrer"&gt;Snowflake App Runtime limitations&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;So, what did you think of Snowflake App Runtime?&lt;/p&gt;

&lt;p&gt;Let's recap the key points of this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;App Runtime is a platform that lets you deploy full-stack web apps (Next.js and friends) inside Snowflake, as an SPCS &lt;code&gt;APPLICATION SERVICE&lt;/code&gt;&lt;/strong&gt;. It reached GA in September 2026&lt;/li&gt;
&lt;li&gt;No infrastructure, Docker, or auth implementation needed — you can publish an app &lt;strong&gt;while inheriting SSO and governance&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configuration is consolidated into a &lt;strong&gt;single &lt;code&gt;app.yml&lt;/code&gt; file (&lt;code&gt;version: 2&lt;/code&gt;)&lt;/strong&gt;, where you declaratively write the deploy destination, &lt;strong&gt;scale and auto-suspend&lt;/strong&gt;, secrets, external access, and deploy targets&lt;/li&gt;
&lt;li&gt;With &lt;strong&gt;CoCo's &lt;code&gt;snowflake-apps&lt;/code&gt; skill&lt;/strong&gt;, you go from prompt to scaffold to local preview to deploy in one continuous flow&lt;/li&gt;
&lt;li&gt;When you actually build one, there are points worth knowing up front — &lt;strong&gt;the CLI version, how declarative deploys behave, specifying the deploy target, and the role during local development&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The approach of "running a real web app right next to your data" looks set to make in-house app development — previously a time-consuming effort — much more approachable. Now that it's GA and the configuration side has settled, I'd expect the supported stack and features to keep expanding.&lt;/p&gt;

&lt;p&gt;I'd love for you to get hands-on and share what you discover. Let's grow this new app-building experience together!&lt;/p&gt;
&lt;h2&gt;
  
  
  Promotion
&lt;/h2&gt;
&lt;h3&gt;
  
  
  App Runtime Explained on the Official Snowflake Japan YouTube Channel
&lt;/h3&gt;

&lt;p&gt;The official Snowflake Japan YouTube channel has launched, and it already includes a walkthrough of Snowflake App Runtime — the very topic of this article. The video covers what App Runtime is and how to get an app deployed, with a live demo. It's in Japanese, but the demo sections should still be easy to follow alongside this article.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/i_oA6QY8T8Y" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;h3&gt;
  
  
  Snowflake What's New Updates on X
&lt;/h3&gt;

&lt;p&gt;I share Snowflake What's New updates on X. Follow for the latest insights:&lt;/p&gt;
&lt;h4&gt;
  
  
  English Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_en" rel="noopener noreferrer"&gt;Snowflake What's New Bot (English Version)&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Japanese Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_jp" rel="noopener noreferrer"&gt;Snowflake's What's New Bot (Japanese Version)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Change Log
&lt;/h2&gt;

&lt;p&gt;(20260605) Initial post&lt;br&gt;
(20260830) Added the App Runtime walkthrough from the official Snowflake Japan YouTube channel&lt;br&gt;
(20260923) &lt;strong&gt;Major revision.&lt;/strong&gt; Reflected App Runtime's GA (September 1, 2026). Rewrote the configuration around the single &lt;code&gt;app.yml&lt;/code&gt; manifest (&lt;code&gt;version: 2&lt;/code&gt;), and added sections on scale (&lt;code&gt;min_instances&lt;/code&gt; / &lt;code&gt;max_instances&lt;/code&gt;) and auto-suspend (&lt;code&gt;auto_suspend_secs&lt;/code&gt;), on environment variables / secrets / external access, and on deploy targets (&lt;code&gt;targets&lt;/code&gt; / &lt;code&gt;--target&lt;/code&gt;). Corrected how Caller's Rights is configured (no &lt;code&gt;app.yml&lt;/code&gt; setting required; &lt;code&gt;GRANT CALLER&lt;/code&gt; is) and the &lt;code&gt;snow app deploy&lt;/code&gt; flags (&lt;code&gt;--deploy-only&lt;/code&gt; → &lt;code&gt;--promote-only&lt;/code&gt;). Added migration notes such as the static asset copy for Next.js standalone builds&lt;br&gt;
(20260923) Added a section on per-app observability (&lt;code&gt;DESCRIBE APPLICATION SERVICE&lt;/code&gt;, &lt;code&gt;SYSTEM$GET_APPLICATION_SERVICE_LOGS&lt;/code&gt;, and the log / metric / lifecycle streams of &lt;code&gt;snow app events&lt;/code&gt;). Clarified that cost is the only thing reported at the account level. Noted that when an app is dropped, its artifact repository remains as an object independent of the service&lt;/p&gt;
&lt;h2&gt;
  
  
  Original Japanese Article
&lt;/h2&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://zenn.dev/snowflakejp/articles/9e5b8fa393ccd8" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Fupload%2Fs--86w7oASz--%2Fc_fit%252Cg_north_west%252Cl_text%3Anotosansjp-medium.otf_55%3ASnowflake%252520App%252520Runtime%252520%2525E5%252585%2525A5%2525E9%252596%252580%252520-%252520%2525E3%252583%252597%2525E3%252583%2525AD%2525E3%252583%2525B3%2525E3%252583%252597%2525E3%252583%252588%2525E3%252581%2525B2%2525E3%252581%2525A8%2525E3%252581%2525A4%2525E3%252581%2525A7%2525E3%252583%252587%2525E3%252583%2525BC%2525E3%252582%2525BF%2525E3%252581%2525AE%2525E9%25259A%2525A3%2525E3%252581%2525AB%2525E6%25259C%2525AC%2525E6%2525A0%2525BCWeb%2525E3%252582%2525A2%2525E3%252583%252597%2525E3%252583%2525AA%2525E3%252582%252592%2525E3%252583%252587%2525E3%252583%252597%2525E3%252583%2525AD%2525E3%252582%2525A4%2525E3%252581%252599%2525E3%252582%25258B%2525EF%2525BC%252581%252Cw_1010%252Cx_90%252Cy_100%2Fg_south_west%252Cl_text%3Anotosansjp-medium.otf_34%3Atsubasa%252Cx_220%252Cy_108%2Fbo_3px_solid_rgb%3Ad6e3ed%252Cg_south_west%252Ch_90%252Cl_fetch%3AaHR0cHM6Ly9zdGF0aWMuemVubi5zdHVkaW8vdXNlci11cGxvYWQvYXZhdGFyLzQ0ZmE2OGQyM2YuanBlZw%3D%3D%252Cr_20%252Cw_90%252Cx_92%252Cy_102%2Fco_rgb%3A6e7b85%252Cg_south_west%252Cl_text%3Anotosansjp-medium.otf_30%3ASnowflake%252520Japan%252Cx_220%252Cy_160%2Fbo_4px_solid_white%252Cg_south_west%252Ch_50%252Cl_fetch%3AaHR0cHM6Ly9zdGF0aWMuemVubi5zdHVkaW8vdXNlci11cGxvYWQvYXZhdGFyL2RkODMzYmYwZDcuanBlZw%3D%3D%252Cr_max%252Cw_50%252Cx_139%252Cy_84%2Fv1627283836%2Fdefault%2Fog-base-w1200-v2.png%3F_a%3DBACMTiAE" height="630" class="m-0" width="1200"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://zenn.dev/snowflakejp/articles/9e5b8fa393ccd8" rel="noopener noreferrer" class="c-link"&gt;
            Snowflake App Runtime 入門 - プロンプトひとつでデータの隣に本格Webアプリをデプロイする！
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstatic.zenn.studio%2Fimages%2Flogo-transparent.png" width="315" height="315"&gt;
          zenn.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>snowflake</category>
      <category>llm</category>
      <category>agents</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Beyond Transcription - Multimodal Video and Audio Analysis with Snowflake AI_COMPLETE</title>
      <dc:creator>Tsubasa Kanno</dc:creator>
      <pubDate>Sun, 17 May 2026 12:50:45 +0000</pubDate>
      <link>https://dev.to/tsubasa_tech/beyond-transcription-multimodal-video-and-audio-analysis-with-snowflake-aicomplete-3g7c</link>
      <guid>https://dev.to/tsubasa_tech/beyond-transcription-multimodal-video-and-audio-analysis-with-snowflake-aicomplete-3g7c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Major revision notice (September 2026)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This article was originally published in May 2026. Cortex AI's multimodal support has expanded considerably since then, so &lt;strong&gt;I rewrote it in September 2026&lt;/strong&gt;. The main changes are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;gemini-3.1-flash-lite&lt;/code&gt; joined the models&lt;/strong&gt; that accept video and audio directly, adding a lighter-weight option&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI_TRANSCRIBE now accepts video files as-is&lt;/strong&gt;, so you no longer need to extract the audio track first. The comparison section has been rewritten accordingly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI_MULTI_EMBED enables semantic video search&lt;/strong&gt;, which is covered in a new section&lt;/li&gt;
&lt;li&gt;Per-request limits are now broken down by images, audio, and video, and there's a new section on passing multiple files in one call&lt;/li&gt;
&lt;li&gt;AI_TRANSCRIBE's &lt;strong&gt;10-second minimum billing duration&lt;/strong&gt; is now documented, and is noted in the comparison section&lt;/li&gt;
&lt;li&gt;The sample app is now &lt;strong&gt;model-selectable&lt;/strong&gt;, and a new section covers how to create a stage for media files&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Snowflake's unstructured data analytics has just taken another big leap forward. After progressively adding support for images, documents, and audio, &lt;strong&gt;AI_COMPLETE&lt;/strong&gt; can now accept &lt;strong&gt;video and audio files as direct input&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;This update — &lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/ai-multimodal" rel="noopener noreferrer"&gt;the multimodal video and audio extension of AI_COMPLETE&lt;/a&gt; — is one of the Cortex AI Functions updates I've been watching most closely. You can now hand a video or audio file directly to AI from SQL, and get summaries, classification, sentiment analysis, and structured extraction in a single shot.&lt;/p&gt;

&lt;p&gt;Until now, audio analysis usually meant a two-step pipeline with transcription in the middle, and video analysis required building your own preprocessing stack on something like Snowpark Container Services (SPCS). With this update, you can skip those steps and &lt;strong&gt;let the model directly understand vocal tone, pauses, and visual content&lt;/strong&gt; — opening the door to analyses that were previously hard to attempt.&lt;/p&gt;

&lt;p&gt;With images, documents, audio, and now video — nearly every major unstructured data format used in business is queryable from SQL. This means you can now &lt;strong&gt;build multimodal analytics in a much simpler way&lt;/strong&gt; than before.&lt;/p&gt;

&lt;p&gt;We'll work through the basics, how AI_COMPLETE compares with AI_TRANSCRIBE, semantic video search, and a sample app built with Streamlit in Snowflake — running each piece along the way.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;strong&gt;AI_COMPLETE's video and audio input is in Public Preview&lt;/strong&gt;, so expect it to change in future updates. AI_TRANSCRIBE and AI_MULTI_EMBED, which this article also covers, are generally available (GA). Supported models and limits are expected to keep expanding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article reflects my personal views and does not represent Snowflake's official position.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What's New: AI_COMPLETE Multimodal Extension
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/sql-reference/functions/ai_complete" rel="noopener noreferrer"&gt;AI_COMPLETE&lt;/a&gt; is the central general-purpose LLM function in the Snowflake Cortex AI Functions family. It already supported text, images, and documents as multimodal input, but with this update you can now pass &lt;strong&gt;video and audio files directly&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Audio analytics used to follow a "transcribe with AI_TRANSCRIBE → analyze text with AI_COMPLETE" pattern. Video analytics required either extracting frames as images with Python libraries and feeding them into AI_COMPLETE's image input, or building an end-to-end frame-extraction-and-inference pipeline with SPCS. With this multimodal extension, you can skip those preprocessing steps and &lt;strong&gt;hand the audio or video file itself to AI_COMPLETE&lt;/strong&gt; for summarization, sentiment analysis, and structured extraction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Highlights
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SQL-native&lt;/strong&gt;: Same calling convention as before — just pass a video or audio file&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Joint audio + visual understanding&lt;/strong&gt;: For video, the model considers both visual content and audio track&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multimodal composition&lt;/strong&gt;: Combine with text prompts for conditional analysis or JSON-structured output&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wide format support&lt;/strong&gt;: Most common video and audio formats are accepted&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure processing&lt;/strong&gt;: Processing stays inside Snowflake&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Part of the Cortex AI Functions Family
&lt;/h3&gt;

&lt;p&gt;The multimodal extension shines when you &lt;strong&gt;chain its output into downstream AI Functions&lt;/strong&gt;. After extracting a summary from a video, common follow-up patterns include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI_CLASSIFY&lt;/strong&gt;: Categorize the extracted summary into industries or risk levels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI_SENTIMENT&lt;/strong&gt;: Score sentiment along multiple dimensions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI_AGG&lt;/strong&gt;: Aggregate insights across many media files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI_EMBED&lt;/strong&gt;: Embed extracted text or images for cross-corpus search&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI_TRANSCRIBE&lt;/strong&gt;: A purpose-built function for transcription, ideal when you need timestamps and speaker labels from audio or video&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI_MULTI_EMBED&lt;/strong&gt;: Embeds the video itself, enabling semantic search like "find scenes similar to this one" (covered later)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating a Stage for Media Files
&lt;/h2&gt;

&lt;p&gt;Cortex AI's media functions read files from a stage via &lt;code&gt;TO_FILE&lt;/code&gt;. The stage has to meet a couple of requirements, so let's create one first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="n"&gt;STAGE&lt;/span&gt; &lt;span class="n"&gt;media_stage&lt;/span&gt;
  &lt;span class="n"&gt;DIRECTORY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;ENABLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;TRUE&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;ENCRYPTION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'SNOWFLAKE_SSE'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Two things matter here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Specify server-side encryption (&lt;code&gt;SNOWFLAKE_SSE&lt;/code&gt;)&lt;/strong&gt;: internal stages default to client-side encryption, and media functions can't read from client-side encrypted stages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add &lt;code&gt;DIRECTORY = ( ENABLE = TRUE )&lt;/code&gt;&lt;/strong&gt;: required when you want to process every file in the stage via &lt;code&gt;DIRECTORY()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that user stages (&lt;code&gt;@~&lt;/code&gt;) and table stages aren't supported. If you use an external stage on Amazon S3 or similar, enable encryption and a directory table the same way.&lt;/p&gt;

&lt;p&gt;The examples below assume your media files live in this &lt;code&gt;@media_stage&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Basic Usage
&lt;/h2&gt;

&lt;p&gt;Passing a video or audio file directly to AI_COMPLETE follows the same simple syntax as image input.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;AI_COMPLETE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Parameters
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;model&lt;/strong&gt;: Name of an LLM that supports video/audio input. &lt;code&gt;gemini-3.1-pro&lt;/code&gt;, &lt;code&gt;gemini-3.1-flash-lite&lt;/code&gt;, and &lt;code&gt;gemini-3.5-flash&lt;/code&gt; are listed as supported, and the lineup keeps growing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;prompt&lt;/strong&gt;: Natural-language instruction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;file&lt;/strong&gt;: A reference to a staged file via &lt;code&gt;TO_FILE&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Example 1: Summarizing a Video File
&lt;/h3&gt;

&lt;p&gt;The simplest use case is to hand a video to the model and ask for a summary that takes both visuals and audio into account.&lt;/p&gt;

&lt;p&gt;This article uses &lt;a href="https://www.pexels.com/video/pouring-fresh-coffee-into-ceramic-mug-27938665/" rel="noopener noreferrer"&gt;Pexels: Pouring Fresh Coffee into Ceramic Mug&lt;/a&gt; (&lt;a href="https://www.pexels.com/license/" rel="noopener noreferrer"&gt;Pexels License&lt;/a&gt;) as the sample video.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;AI_COMPLETE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'gemini-3.1-pro'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'Summarize this video in about 70 words. Include what is shown, the mood, and the likely scene.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@media_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'pouring_coffee.mp4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The actual response looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A glass coffee server slowly pours freshly brewed coffee into a uniquely designed
small mug shaped like a blue character, sitting on a white table. The cute design
of the cup combined with the quiet motion of the cup gradually filling up evokes
a warm, relaxed atmosphere — exactly the kind of feeling that lets you take a
breather. It feels like a calm morning coffee at home or an afternoon break.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The same pattern works for audio. Hand an audio file of English narration to the model and ask for a summary, and you get an output that captures both the content and the speaker's tone:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;AI_COMPLETE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'gemini-3.1-pro'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'Summarize this audio in about 50 words. Take the speaker&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;s emotion and atmosphere into account.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@media_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'english_narration.m4a'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;For Sherlock Holmes, she (Irene Adler) is always "the woman" — a uniquely special
presence. The narrator, Watson, says he has rarely heard Holmes refer to her by
any other name. The calm, reminiscent delivery quietly conveys the deep respect
Holmes holds for her, and her overwhelming presence.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Japanese audio works the same way. The audio here was synthesized with the macOS &lt;code&gt;say&lt;/code&gt; command for reproducibility — you can also generate equivalent audio with &lt;a href="https://commonvoice.mozilla.org/ja/datasets" rel="noopener noreferrer"&gt;Mozilla Common Voice's Japanese dataset&lt;/a&gt; (CC0) or &lt;a href="https://voicevox.hiroshiba.jp/" rel="noopener noreferrer"&gt;VOICEVOX&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;AI_COMPLETE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'gemini-3.1-pro'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'Summarize this audio, and state the speaker&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;s request and emotional tone in one or two sentences.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@media_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'business_call_jp.m4a'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The speaker is reaching out to confirm the current status of a delayed delivery
of a recently purchased item. The emotional tone is highly polite and composed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Example 2: Going Beyond Words — Tone, Pitch, and Pace
&lt;/h3&gt;

&lt;p&gt;This is a significant difference from AI_TRANSCRIBE. With AI_COMPLETE, the model can evaluate &lt;strong&gt;the vocal delivery itself — pitch, pace, tone, volume, and pauses&lt;/strong&gt; (&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/ai-multimodal#audio-based-sentiment-analytics" rel="noopener noreferrer"&gt;the official docs&lt;/a&gt; explicitly demonstrate this in the call-center example). The phrase "Hello" can carry completely different meaning depending on whether it's said with a bright, upbeat tone or a heavy, somber one. That nuance is lost the moment you transcribe to text — and AI_COMPLETE can capture it.&lt;/p&gt;

&lt;p&gt;To verify, I synthesized the exact same Japanese phrase ("Hello, thank you for joining us today.") in two different tones — bright/fast vs. dark/slow — and passed each to AI_COMPLETE.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;AI_COMPLETE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'gemini-3.1-pro'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'You are an acoustic analyzer. Listen to the attached audio and evaluate the vocal delivery (pitch, pace, tone, volume). Return a short description of the vocal delivery only (do not transcribe content).'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@media_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'tone_bright.m4a'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;bright_analysis&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Output for the bright/fast version:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Spoken with a very high pitch and fast pace. The tone is bright and slightly
artificial (sounds sped-up or processed). Volume is moderate.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Output for the dark/slow version:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pitch is moderate and steady, and the pace is calm and easy to follow. The tone
is polite and composed, with consistent moderate volume.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The actual words are identical, but the model returned clearly different evaluations based on how the voice was delivered. This is information that transcription alone doesn't surface. For use cases where &lt;strong&gt;the way something is said matters as much as what is said&lt;/strong&gt; — call center quality scoring, interview evaluation, escalation detection — it's genuinely useful.&lt;/p&gt;
&lt;h3&gt;
  
  
  Example 3: Structured Analysis of a Video File
&lt;/h3&gt;

&lt;p&gt;Use a JSON Schema to get structured output that downstream pipelines can consume directly.&lt;/p&gt;

&lt;p&gt;Two extra arguments come into play here. The &lt;strong&gt;fourth argument holds model parameters&lt;/strong&gt; such as temperature; pass &lt;code&gt;{}&lt;/code&gt; when you don't need them. The &lt;strong&gt;fifth argument is the output schema&lt;/strong&gt;, where you set &lt;code&gt;'type': 'json'&lt;/code&gt; along with your JSON Schema.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;TO_JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AI_COMPLETE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'gemini-3.1-pro'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'Analyze this video and return scene summary, visible objects, and the overall mood as JSON.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@media_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'pouring_coffee.mp4'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'json'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'schema'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'object'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'properties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s1"&gt;'summary'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="s1"&gt;'objects'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'array'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'items'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
                &lt;span class="s1"&gt;'mood'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'summary'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'objects'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'mood'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Actual output:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mood"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Calm, relaxed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"objects"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Coffee pot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Coffee"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"summary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Coffee being poured from a black coffee pot into a unique mug featuring a blue bird's face design."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The keys and types defined in the schema are honored, which makes it trivial to forward the output into the next stage of a data pipeline.&lt;/p&gt;

&lt;p&gt;The same pattern applies to audio. Here it is against a recording of a meeting:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;TO_JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AI_COMPLETE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'gemini-3.1-pro'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'Analyze this audio and return a JSON object with a summary, the likely topic genre, and the overall tone.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@media_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'meeting_clip.mp3'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'json'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'schema'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'object'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'properties'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s1"&gt;'summary'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="s1"&gt;'genre'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="s1"&gt;'tone'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'summary'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'genre'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'tone'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"genre"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Business/Marketing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"summary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Monthly meeting for Nimbus Cloud highlighting a 32% improvement in paid search CPA, exceeding demo targets with 420 applications, and outlining future plans for LinkedIn targeting and CRM integration."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Professional"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Example 4: Conditional Analysis with Text Prompts
&lt;/h3&gt;

&lt;p&gt;When you want only a specific aspect extracted, that's a matter of prompt design. Including instructions like "if there are none, just return 'none'" helps keep the model from guessing when there's nothing to report.&lt;/p&gt;

&lt;p&gt;This article uses &lt;a href="https://www.pexels.com/video/person-having-a-interview-5442623/" rel="noopener noreferrer"&gt;Pexels: Person Having an Interview&lt;/a&gt; (&lt;a href="https://www.pexels.com/license/" rel="noopener noreferrer"&gt;Pexels License&lt;/a&gt;). The video doesn't contain any product names, so the expected output is "none".&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;AI_COMPLETE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'gemini-3.1-pro'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'Extract only the moments where product names (brand names) appear in this video, and list each name with its timing as bullet points. If there are none, just return "none".'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@media_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'interview.mp4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;extracted&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The model returned exactly &lt;code&gt;none&lt;/code&gt;, faithfully following the prompt.&lt;/p&gt;
&lt;h2&gt;
  
  
  Supported Models and Formats
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Supported Models
&lt;/h3&gt;

&lt;p&gt;According to &lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/ai-multimodal" rel="noopener noreferrer"&gt;the official documentation&lt;/a&gt;, the models listed as supporting direct video/audio input are &lt;strong&gt;&lt;code&gt;gemini-3.1-pro&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;gemini-3.1-flash-lite&lt;/code&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;code&gt;gemini-3.5-flash&lt;/code&gt;&lt;/strong&gt;. It started with &lt;code&gt;gemini-3.1-pro&lt;/code&gt; only, and lighter options were added over time, so you can now pick your balance between analysis quality and speed. All three have a context window of roughly one million tokens, with the same supported formats and file-size limits. Snowflake partners with multiple model providers, so the lineup of multimodal-capable models keeps growing.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Context window&lt;/th&gt;
&lt;th&gt;When to use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gemini-3.1-pro&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1,000,000 tokens&lt;/td&gt;
&lt;td&gt;When you prioritize higher analysis quality&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gemini-3.1-flash-lite&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1,048,576 tokens&lt;/td&gt;
&lt;td&gt;When you want a lighter model for higher volume&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gemini-3.5-flash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1,000,000 tokens&lt;/td&gt;
&lt;td&gt;When you want faster, lighter-weight processing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Another thing I appreciate about AI_COMPLETE is that &lt;strong&gt;the model you used stays visible in the query&lt;/strong&gt;. The function takes the model name as its first argument by design, so you always know which model produced a result, and you can tune the cost-versus-quality balance deliberately.&lt;/p&gt;
&lt;h3&gt;
  
  
  Supported Formats
&lt;/h3&gt;

&lt;p&gt;A broad set of mainstream formats is supported, so you can work with most video and audio files you'd find in the wild.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Supported formats&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Video&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;mp4, mpeg, mov, avi, flv, mpg, webm, wmv, 3gpp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Audio&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;wav, mp3, aiff, aac, ogg, flac, m4a, mp4, pcm, webm&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Per-Request Limits
&lt;/h3&gt;

&lt;p&gt;The per-request limits are as follows. They're comfortable for testing and proof-of-concept work, and are expected to be relaxed as the feature matures.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Limit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total size per request&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Video files per request&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Up to 10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Audio files per request&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Up to 10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Image files per request&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Up to 20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;File counts are tallied independently per type. For longer videos, splitting by scene or duration before sending lets you analyze plenty of content within current limits.&lt;/p&gt;
&lt;h3&gt;
  
  
  Passing Multiple Files in One Call
&lt;/h3&gt;

&lt;p&gt;Every example so far passed a single file as the third argument. When you want several files in the same request so the model can compare them, use the &lt;a href="https://docs.snowflake.com/en/sql-reference/functions/prompt" rel="noopener noreferrer"&gt;&lt;code&gt;PROMPT&lt;/code&gt; function&lt;/a&gt; and reference each file with &lt;code&gt;{0}&lt;/code&gt;, &lt;code&gt;{1}&lt;/code&gt;, and so on.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;AI_COMPLETE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'gemini-3.1-pro'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;PROMPT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Do video {0} and image {1} look like they belong to the same campaign? Answer in 30 words or fewer.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@media_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'promo_spot.mp4'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@media_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'creative.png'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;consistency_check&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Yes, they share the same visual identity, so they appear to belong to the same
campaign.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That makes it a single query to check whether a campaign video and its creative artwork look consistent.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;PROMPT&lt;/code&gt; function reference currently focuses on text plus images and documents. Before putting a combination that includes video into a production pipeline, it's worth confirming the behavior in your own environment.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Regional Availability
&lt;/h3&gt;

&lt;p&gt;Check the &lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/aisql#availability" rel="noopener noreferrer"&gt;Cortex LLM Regional availability&lt;/a&gt; page for the native regions of the video/audio-capable models. If your region isn't natively supported, you can enable &lt;strong&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cross-region-inference" rel="noopener noreferrer"&gt;cross-region inference&lt;/a&gt;&lt;/strong&gt; with a single SQL statement and use the same functionality.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="n"&gt;ACCOUNT&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;CORTEX_ENABLED_CROSS_REGION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ANY_REGION'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;There may be slightly higher latency when going via cross-region inference, but the functionality remains the same.&lt;/p&gt;
&lt;h2&gt;
  
  
  AI_TRANSCRIBE vs. AI_COMPLETE — Cost and Quality
&lt;/h2&gt;

&lt;p&gt;"Should I use AI_TRANSCRIBE or AI_COMPLETE for audio and video?" is a question many people run into.&lt;/p&gt;

&lt;p&gt;The fundamental thing to understand is that &lt;strong&gt;AI_TRANSCRIBE is a purpose-built, dedicated AI Function for converting media to text&lt;/strong&gt;. The output is text by default, with optional word-level or speaker-level timestamps. That gives you less flexibility — but in return, &lt;strong&gt;it's simple to use when your goal is clear and costs are predictable per second of audio&lt;/strong&gt;. AI_COMPLETE is a general-purpose LLM, so prompts can express anything you want, and the model can incorporate vocal delivery and visual information into its interpretation. The two aren't competitors — they're complementary: &lt;strong&gt;AI_TRANSCRIBE for clear, fixed goals; AI_COMPLETE for free-form interpretation&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  AI_TRANSCRIBE Accepts Video Files Directly Too
&lt;/h3&gt;

&lt;p&gt;When this article was first published, AI_TRANSCRIBE was audio-only. Today you can &lt;strong&gt;hand it a video file and have it transcribe the audio track&lt;/strong&gt;, which removes the preprocessing step when you're building minutes from a meeting recording or a webinar archive.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;AI_TRANSCRIBE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@media_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'meeting.mp4'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The response has the same shape as it does for audio:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"audio_duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;15.04&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Let's begin this month's regular review for Nimbus Cloud. This month, paid search CPA improved by 32%. Demo signups came in at 420, ahead of target."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Supported formats are as follows. A video file must contain at least one audio track, encoded with one of AAC, ALAC, FLAC, MP3, Opus, Vorbis, or PCM.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Supported formats&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Audio&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;aac, flac, m4a, mp3, mp4, ogg, wav, webm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Video&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;mkv, mov, mp4, ogv, webm&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note that these formats differ from AI_COMPLETE's.&lt;/strong&gt; An &lt;code&gt;.avi&lt;/code&gt; recording works with AI_COMPLETE, for example, but needs converting before AI_TRANSCRIBE will take it.&lt;/p&gt;

&lt;p&gt;With timestamps enabled, the maximum duration is 60 minutes; without them it's 120 minutes, and the file size limit is 700 MB. That's larger than AI_COMPLETE's limit of 100 MB combined per request, so &lt;strong&gt;AI_TRANSCRIBE is often the easier route for long recordings you want to process whole&lt;/strong&gt;. AI_TRANSCRIBE is also available in a limited set of regions, so check the &lt;a href="https://docs.snowflake.com/en/sql-reference/functions/ai_transcribe" rel="noopener noreferrer"&gt;official reference&lt;/a&gt; alongside the model availability page.&lt;/p&gt;
&lt;h3&gt;
  
  
  Timestamps and Speaker Labels Are Opt-In
&lt;/h3&gt;

&lt;p&gt;The example above returned only &lt;code&gt;audio_duration&lt;/code&gt; and &lt;code&gt;text&lt;/code&gt;. To get timestamps or speaker labels, pass &lt;code&gt;timestamp_granularity&lt;/code&gt; as the second argument — &lt;code&gt;word&lt;/code&gt; splits per word, &lt;code&gt;speaker&lt;/code&gt; splits at each change of speaker.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;AI_TRANSCRIBE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@media_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'meeting.mp4'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'timestamp_granularity'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'speaker'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"audio_duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;15.04&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"segments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"speaker_label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SPEAKER_00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.051&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;14.78&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Let's begin this month's regular review for Nimbus Cloud. ..."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Functional Differences
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;AI_TRANSCRIBE&lt;/th&gt;
&lt;th&gt;AI_COMPLETE (audio / video direct)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Primary purpose&lt;/td&gt;
&lt;td&gt;Structured media-to-text conversion&lt;/td&gt;
&lt;td&gt;Free-form analysis (summary, classification, extraction)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output&lt;/td&gt;
&lt;td&gt;Text, with optional timestamps and speaker labels&lt;/td&gt;
&lt;td&gt;Whatever you ask for in the prompt (incl. JSON)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speaker separation&lt;/td&gt;
&lt;td&gt;Set &lt;code&gt;timestamp_granularity&lt;/code&gt; to &lt;code&gt;speaker&lt;/code&gt; for labels (SPEAKER_00, etc.)&lt;/td&gt;
&lt;td&gt;Achieved by prompt instruction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Timestamps&lt;/td&gt;
&lt;td&gt;Word- or speaker-level&lt;/td&gt;
&lt;td&gt;Achievable via prompt + structured output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Visual content&lt;/td&gt;
&lt;td&gt;Audio track only&lt;/td&gt;
&lt;td&gt;Can interpret what's on screen&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vocal tone / emotion&lt;/td&gt;
&lt;td&gt;Text only&lt;/td&gt;
&lt;td&gt;Includes pitch, pace, tone, volume, pauses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input size limit&lt;/td&gt;
&lt;td&gt;Up to 700 MB&lt;/td&gt;
&lt;td&gt;100 MB combined per request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multilingual&lt;/td&gt;
&lt;td&gt;Broad coverage&lt;/td&gt;
&lt;td&gt;LLM-native flexibility&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Cost Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Pricing characteristic&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AI_TRANSCRIBE&lt;/td&gt;
&lt;td&gt;1 sec of audio = 50 tokens (flat). 180,000 tokens per hour. 10-second minimum billing duration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI_COMPLETE (audio / video direct)&lt;/td&gt;
&lt;td&gt;Standard LLM token pricing — varies by input size and output length&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;AI_TRANSCRIBE bills linearly with audio duration, so it shines when you want &lt;strong&gt;"just the transcript" or stable, predictable costs in big batch jobs&lt;/strong&gt;. Keep in mind that &lt;strong&gt;files shorter than 10 seconds are billed as 10 seconds&lt;/strong&gt;, so if you have a large number of short clips, batching them into one file and slicing by timestamp avoids waste. AI_COMPLETE varies with prompt and output size, which can swing costs depending on the task. In return, &lt;strong&gt;you explicitly choose the model in the first argument&lt;/strong&gt;, giving you direct control over the cost-vs-quality trade-off in your application.&lt;/p&gt;
&lt;h3&gt;
  
  
  Quality Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Meeting minutes drafting (need accurate transcript)&lt;/td&gt;
&lt;td&gt;AI_TRANSCRIBE → AI_COMPLETE chain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transcript only, straight from a meeting recording&lt;/td&gt;
&lt;td&gt;AI_TRANSCRIBE (pass the video as-is)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Call center sentiment analysis (with vocal tone)&lt;/td&gt;
&lt;td&gt;AI_COMPLETE direct&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Large-scale, fast batch transcription&lt;/td&gt;
&lt;td&gt;AI_TRANSCRIBE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video (visual + audio) summarization &amp;amp; moderation&lt;/td&gt;
&lt;td&gt;AI_COMPLETE direct&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON-structured extraction from audio&lt;/td&gt;
&lt;td&gt;AI_COMPLETE direct&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Finding a specific scene across a large video library&lt;/td&gt;
&lt;td&gt;AI_MULTI_EMBED (covered next)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Rule of thumb&lt;/strong&gt;: "Need text to keep on file" → AI_TRANSCRIBE. "Need the model to interpret content" → AI_COMPLETE. The "AI_TRANSCRIBE → AI_COMPLETE" pipeline is also a well-balanced option for cost and quality in many use cases.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Semantic Video Search with AI_MULTI_EMBED
&lt;/h2&gt;

&lt;p&gt;Everything so far has been about reading one piece of media deeply. In practice you also run into a different need: finding the right moment across a large library of videos. &lt;a href="https://docs.snowflake.com/en/sql-reference/functions/ai_multi_embed" rel="noopener noreferrer"&gt;AI_MULTI_EMBED&lt;/a&gt; is built for that.&lt;/p&gt;

&lt;p&gt;Where AI_EMBED returns a single vector, AI_MULTI_EMBED &lt;strong&gt;segments the video by scene and returns one vector per segment&lt;/strong&gt;. It also embeds three separate modalities — visual, audio, and the transcription of speech — so you can search for "scenes that look similar" separately from "scenes where similar things were said."&lt;/p&gt;

&lt;p&gt;A quick glossary: a &lt;strong&gt;vector&lt;/strong&gt; turns meaning into a list of numbers, so measuring the distance between two vectors tells you how similar their meanings are. A &lt;strong&gt;segment&lt;/strong&gt; is a slice of the video cut at a scene boundary, and a &lt;strong&gt;modality&lt;/strong&gt; is the kind of signal — visual, audio, or speech.&lt;/p&gt;

&lt;p&gt;The available model is Twelve Labs' &lt;strong&gt;&lt;code&gt;twelvelabs-marengo-embed-3-0&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;AI_MULTI_EMBED&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'twelvelabs-marengo-embed-3-0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@media_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'promo_spot.mp4'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;What comes back is an array with one element per segment-and-modality combination. Because each element carries &lt;code&gt;start_sec&lt;/code&gt; and &lt;code&gt;end_sec&lt;/code&gt;, you can jump straight to the playback position of whatever matched.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"embedding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;-0.0220&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0053&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0242&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"embedding_option"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"visual"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"embedding_scope"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"clip"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"start_sec"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"end_sec"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Flatten that into a table and you can search scenes with a natural-language query. The vectors are 512-dimensional, so cast them to &lt;code&gt;VECTOR(FLOAT, 512)&lt;/code&gt; before handing them to a similarity function. If your stage also holds audio or images, filter by extension first.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Build a catalog of scenes&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;video_embeddings&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;embedding_index&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt;
        &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@media_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RELATIVE_PATH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;video_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;AI_MULTI_EMBED&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'twelvelabs-marengo-embed-3-0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@media_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RELATIVE_PATH&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;embeddings&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;DIRECTORY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;media_stage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;-- Common video extensions; check the docs for the full supported list.&lt;/span&gt;
    &lt;span class="c1"&gt;-- Snowflake's RLIKE rejects the (?i) inline flag, so lower-case the path instead.&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;LOWER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RELATIVE_PATH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;RLIKE&lt;/span&gt; &lt;span class="s1"&gt;'.*&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;.(mp4|mov|avi|mkv|webm)'&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;video_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'embedding'&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;VECTOR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;FLOAT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;embedding_vec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'embedding_option'&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;STRING&lt;/span&gt;      &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;embedding_option&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'start_sec'&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="nb"&gt;FLOAT&lt;/span&gt;              &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;start_sec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'end_sec'&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="nb"&gt;FLOAT&lt;/span&gt;                &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;end_sec&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;embedding_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="k"&gt;LATERAL&lt;/span&gt; &lt;span class="n"&gt;FLATTEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;embedding_index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Search scenes with a natural-language query&lt;/span&gt;
&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AI_MULTI_EMBED&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'twelvelabs-marengo-embed-3-0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'a scene where coffee is being poured'&lt;/span&gt;
    &lt;span class="p"&gt;)):&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'embedding'&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;VECTOR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;FLOAT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;query_embedding&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;video_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_sec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end_sec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;VECTOR_COSINE_SIMILARITY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embedding_vec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query_embedding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;similarity&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;video_embeddings&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
&lt;span class="k"&gt;CROSS&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embedding_option&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'visual'&lt;/span&gt;   &lt;span class="c1"&gt;-- swap for 'transcription' to search what was said&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;similarity&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Filtering on &lt;code&gt;embedding_option&lt;/code&gt; is what lets you choose between searching how a scene looks and searching what was said in it. Without the filter, all three modalities compete in the same ranking.&lt;/p&gt;

&lt;p&gt;The size limits are generous too: up to 4 hours and 6 GB per video. Putting AI_MULTI_EMBED in front of AI_COMPLETE — narrowing down which scenes are worth looking at, then reading those in detail — is an efficient way to work through a large video library.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;twelvelabs-marengo-embed-3-0&lt;/code&gt; is natively available in a limited set of regions, but enabling cross-region inference (above) lets you use it the same way. AI_MULTI_EMBED also differs from the other multimodal functions in that it supports client-side encrypted (CSE) stages and stages protected by network policies.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Business Use Cases
&lt;/h2&gt;

&lt;p&gt;Here are some of the business scenarios that Cortex AI's video and audio support opens up.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Call Center Quality Scoring
&lt;/h3&gt;

&lt;p&gt;Hand call recordings directly to AI_COMPLETE and get a &lt;strong&gt;multi-dimensional quality score&lt;/strong&gt; — agent professionalism, customer anger level, escalation signals — that takes vocal delivery into account.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tone-aware sentiment analysis&lt;/strong&gt;: Catches subtle nuances that transcription would miss&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured output integration&lt;/strong&gt;: Returns each metric as JSON for dashboarding&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent training&lt;/strong&gt;: Identify improvement areas by comparing against high-performer recordings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2. Structured Meeting Minutes from Video
&lt;/h3&gt;

&lt;p&gt;Pass a long meeting recording and get summaries, decisions, and action items broken down by topic and participant.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Topic-aware structuring&lt;/strong&gt;: Prompt-driven chapter segmentation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action item extraction&lt;/strong&gt;: Get owner and due date as JSON&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-modal context&lt;/strong&gt;: Whiteboards and on-screen materials are also picked up&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verbatim record&lt;/strong&gt;: When you also need a word-for-word transcript, pass the same recording to AI_TRANSCRIBE&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  3. Compliance Checks for Promotional Videos
&lt;/h3&gt;

&lt;p&gt;Run pre-publication checks for marketing videos to catch potential regulatory issues or brand-guideline violations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Custom condition detection&lt;/strong&gt;: Define check criteria via prompt&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-modal consistency&lt;/strong&gt;: Spot inconsistencies between on-screen captions and spoken content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-language QA&lt;/strong&gt;: Verify localized versions in batch via SQL&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  4. Auto-Chaptering and Scene Search for Educational Content
&lt;/h3&gt;

&lt;p&gt;Analyze online learning content with AI_COMPLETE to generate chapter titles, summaries, and timestamped indexes for viewers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Topic-shift detection&lt;/strong&gt;: AI identifies content boundaries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audience-specific summaries&lt;/strong&gt;: Generate multiple versions per skill level&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scene search&lt;/strong&gt;: Embed the video itself with AI_MULTI_EMBED so learners can jump straight to "the part that explains this operation"&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  5. Social / UGC Moderation
&lt;/h3&gt;

&lt;p&gt;UGC (User Generated Content) refers to videos, audio, and images posted by general users on social media or video platforms. You can implement harmful or policy-violating content detection as part of your SQL workflow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Batch moderation&lt;/strong&gt;: Auto-process newly arriving videos via Streams + Tasks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reviewer notification&lt;/strong&gt;: Send results to moderators via Snowflake Notifications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-axis scoring&lt;/strong&gt;: Score for violence, discriminatory speech, copyright concerns in parallel&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Near-duplicate detection&lt;/strong&gt;: Use AI_MULTI_EMBED to measure similarity against videos previously flagged as violations&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Sample App: Video Analysis with Streamlit in Snowflake
&lt;/h2&gt;

&lt;p&gt;To give you an instant feel for AI_COMPLETE's video support, here's a simple Streamlit in Snowflake app that lets you upload a video and analyze it on the spot.&lt;/p&gt;
&lt;h3&gt;
  
  
  What the App Does
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Video upload&lt;/strong&gt;: Upload directly via browser; auto-saved to a stage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video preview&lt;/strong&gt;: Play the uploaded video in place&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI analysis&lt;/strong&gt;: Run AI_COMPLETE with video input for summarization, extraction, classification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model switching&lt;/strong&gt;: Pick the model used for analysis from the sidebar&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Editable prompt&lt;/strong&gt;: Tweak the analysis prompt freely from the sidebar&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A Snowflake account where &lt;strong&gt;Streamlit in Snowflake&lt;/strong&gt; is available&lt;/li&gt;
&lt;li&gt;A video-capable model available natively, or cross-region inference enabled&lt;/li&gt;
&lt;li&gt;Video files smaller than 100 MB&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streamlit version &lt;code&gt;1.52.2&lt;/code&gt;&lt;/strong&gt;. Streamlit in Snowflake can default to an older Streamlit release, so pin the version explicitly to get current widget behavior&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CREATE STAGE&lt;/code&gt; on the schema, plus the &lt;code&gt;SNOWFLAKE.CORTEX_USER&lt;/code&gt; database role to call Cortex AI Functions&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Specifying the Streamlit Version (Important)
&lt;/h3&gt;

&lt;p&gt;Streamlit in Snowflake's default version may be older than expected, so I recommend pinning the version explicitly. Just place an &lt;code&gt;environment.yml&lt;/code&gt; next to your app files in the stage:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# environment.yml&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app_environment&lt;/span&gt;
&lt;span class="na"&gt;channels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;snowflake&lt;/span&gt;
&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;streamlit=1.52.2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you create the SiS app from Snowsight, you can change the &lt;code&gt;streamlit&lt;/code&gt; version from the &lt;strong&gt;"Packages"&lt;/strong&gt; dropdown in the upper right of the editor — pick the newest version offered there.&lt;/p&gt;
&lt;h3&gt;
  
  
  How to Set It Up
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create a new SiS app&lt;/strong&gt; from the Snowsight left pane → "Streamlit" → "+ Streamlit App"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paste the sample code&lt;/strong&gt; below; the stage is created automatically on first run&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Click "Run"&lt;/strong&gt; in the upper right, upload a video, and click "Analyze with AI"&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Sample Code
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;streamlit&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;snowflake.snowpark.context&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_active_session&lt;/span&gt;

&lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_active_session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;STAGE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;VIDEO_ANALYSIS_STAGE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_current_database&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_current_schema&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;STAGE_FQN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;STAGE_NAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_page_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wide&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🎬 Video Analyzer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;caption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Analyze videos on the spot with AI_COMPLETE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s video input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# The model name has to be a string literal in SQL, so offer an allow-list.
# Add to this list as more models gain support.
&lt;/span&gt;&lt;span class="n"&gt;AVAILABLE_MODELS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-3.1-pro&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-3.1-flash-lite&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-3.5-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sidebar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;⚙️ Settings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sidebar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;selectbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🧠 Model for analysis&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AVAILABLE_MODELS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;prompt_template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sidebar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text_area&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;📝 Analysis prompt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Summarize this video in about 100 words. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Include the people involved, key scenes, and the emotion conveyed by the audio.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@st.cache_resource&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setup_stage&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DESC STAGE &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;STAGE_FQN&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
                CREATE STAGE IF NOT EXISTS &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;STAGE_FQN&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
                ENCRYPTION = (TYPE = &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SNOWFLAKE_SSE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)
                DIRECTORY = (ENABLE = TRUE)
            &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Couldn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t create the stage. Check your privileges: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;setup_stage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;clean_ai_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Strip wrapping double quotes and unescape newlines from AI response.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;


&lt;span class="n"&gt;uploaded_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;file_uploader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Upload a video file (under 100 MB)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mov&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;webm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avi&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mpeg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;flv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wmv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3gpp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;uploaded_file&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# AI_COMPLETE accepts up to 100 MB combined per request, so reject early
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;uploaded_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Please use a video under 100 MB.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subheader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;▶️ Video Preview&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;video&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uploaded_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🤖 Analyze with AI&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;use_container_width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;primary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uploaded_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;safe_ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fullmatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\.[a-z0-9]{2,5}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;video_filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;video_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%Y%m%d_%H%M%S&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;_&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nb"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}{&lt;/span&gt;&lt;span class="n"&gt;safe_ext&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spinner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Uploading video to stage...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;video_stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BytesIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uploaded_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getvalue&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;video_stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;STAGE_FQN&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;video_filename&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;auto_compress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;overwrite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spinner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI is analyzing the video...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="c1"&gt;# The model name must be a literal, so inject only allow-listed
&lt;/span&gt;                &lt;span class="c1"&gt;# values; the prompt and filename go through bind variables
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;AVAILABLE_MODELS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unsupported model selected.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
                    SELECT AI_COMPLETE(
                        &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;,
                        ?,
                        TO_FILE(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;@&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;STAGE_FQN&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, ?)
                    ) AS analysis
                &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
                &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;prompt_template&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;video_filename&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subheader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;📊 Analysis Result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ANALYSIS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;clean_ai_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ANALYSIS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Couldn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t get an analysis result. Try a different prompt or video.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Something went wrong: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;👆 Upload a video file to start analyzing.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Implementation Notes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No extra packages&lt;/strong&gt;: Works with default Streamlit in Snowflake packages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-created stage&lt;/strong&gt;: Created with server-side encryption and a directory table on first run&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model from an allow-list&lt;/strong&gt;: AI_COMPLETE needs the model name as a string literal, so the app uses a &lt;code&gt;selectbox&lt;/code&gt; with fixed choices rather than free text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Editable prompt&lt;/strong&gt;: Update analysis prompt instantly from the sidebar&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video preview&lt;/strong&gt;: Use &lt;code&gt;st.video&lt;/code&gt; to play the uploaded file in-browser&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The model name can't be a bind variable.&lt;/strong&gt; AI_COMPLETE's first argument must be a string literal; passing &lt;code&gt;?&lt;/code&gt; produces a &lt;code&gt;needs to be a string literal&lt;/code&gt; compilation error. If you let users choose a model, &lt;strong&gt;inject only values that came from an allow-list&lt;/strong&gt;, as above, and never pass free-form input straight through.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Verified Behavior
&lt;/h3&gt;

&lt;p&gt;The core of the app — sending the file to a stage with &lt;code&gt;session.file.put_stream&lt;/code&gt;, then analyzing it with &lt;code&gt;AI_COMPLETE&lt;/code&gt; — was verified on a live Snowpark Python session. Every model in the allow-list was also confirmed to accept video input. Paste the code into Streamlit in Snowflake and the same flow runs behind the UI.&lt;/p&gt;
&lt;h3&gt;
  
  
  App Screenshots
&lt;/h3&gt;

&lt;p&gt;The demo video shown is &lt;a href="https://pixabay.com/videos/meadow-grass-spring-meadow-wind-276646/" rel="noopener noreferrer"&gt;Pixabay: Meadow, Grass, Spring Meadow, Wind&lt;/a&gt; (&lt;a href="https://pixabay.com/service/license-summary/" rel="noopener noreferrer"&gt;Pixabay Content License&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyglnm9tg8z82z105bb6b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyglnm9tg8z82z105bb6b.png" alt="Right after uploading a video" width="800" height="568"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Right after uploading a video&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftey8xatrhptbkl7cgh39.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftey8xatrhptbkl7cgh39.png" alt="Right after running the AI analysis" width="800" height="163"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Right after running the AI analysis&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsayosqtpj6yg12m7re5e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsayosqtpj6yg12m7re5e.png" alt="The sidebar settings panel" width="554" height="326"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The sidebar settings panel&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Cost
&lt;/h2&gt;

&lt;p&gt;AI_COMPLETE billing follows token-based pricing, like other AI Functions. For direct video/audio input, factor in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input tokens&lt;/strong&gt;: Vary with file length and content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output tokens&lt;/strong&gt;: Vary with the requested output length&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model rate&lt;/strong&gt;: The credit rate of the model you selected applies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See the &lt;a href="https://www.snowflake.com/legal-files/CreditConsumptionTable.pdf" rel="noopener noreferrer"&gt;Snowflake Service Consumption Table&lt;/a&gt; for current pricing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Cost optimization tip&lt;/strong&gt;: When you only need transcription, use AI_TRANSCRIBE; when you need interpretation, use AI_COMPLETE. A two-stage pipeline that filters out clearly irrelevant videos with a simple prompt before deeper analysis works well too — as does narrowing candidates with AI_MULTI_EMBED before handing them to AI_COMPLETE.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Sample Materials Used in This Article
&lt;/h2&gt;

&lt;p&gt;All free assets used here are commercially licensed so you can reproduce the examples yourself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Video: &lt;a href="https://www.pexels.com/video/pouring-fresh-coffee-into-ceramic-mug-27938665/" rel="noopener noreferrer"&gt;Pexels: Pouring Fresh Coffee into Ceramic Mug&lt;/a&gt; (&lt;a href="https://www.pexels.com/license/" rel="noopener noreferrer"&gt;Pexels License&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Video: &lt;a href="https://www.pexels.com/video/person-having-a-interview-5442623/" rel="noopener noreferrer"&gt;Pexels: Person Having an Interview&lt;/a&gt; (&lt;a href="https://www.pexels.com/license/" rel="noopener noreferrer"&gt;Pexels License&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Video: &lt;a href="https://pixabay.com/videos/meadow-grass-spring-meadow-wind-276646/" rel="noopener noreferrer"&gt;Pixabay: Meadow, Grass, Spring Meadow, Wind&lt;/a&gt; (&lt;a href="https://pixabay.com/service/license-summary/" rel="noopener noreferrer"&gt;Pixabay Content License&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Audio: &lt;a href="https://librivox.org/the-adventures-of-sherlock-holmes-by-arthur-conan-doyle/" rel="noopener noreferrer"&gt;LibriVox: The Adventures of Sherlock Holmes (Arthur Conan Doyle)&lt;/a&gt; (Public Domain)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Japanese audio was synthesized with the macOS &lt;code&gt;say&lt;/code&gt; command. Note also that &lt;code&gt;meeting.mp4&lt;/code&gt;, &lt;code&gt;promo_spot.mp4&lt;/code&gt;, &lt;code&gt;creative.png&lt;/code&gt;, and &lt;code&gt;meeting_clip.mp3&lt;/code&gt; are placeholder filenames used to illustrate the syntax — substitute your own.&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;AI_COMPLETE's video and audio support is a meaningful step toward &lt;strong&gt;simpler multimodal analytics on Snowflake&lt;/strong&gt;. With video joining images, documents, and audio, nearly every major unstructured data format can now be queried straight from SQL. Add AI_TRANSCRIBE's video support and AI_MULTI_EMBED's video search, and all three modes — reading media, turning it into text, and searching it — are available from SQL.&lt;/p&gt;
&lt;h3&gt;
  
  
  Key Benefits
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pass media as-is&lt;/strong&gt;: Skip transcription — the model picks up vocal tone and visual context&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick the function that fits the goal&lt;/strong&gt;: AI_COMPLETE to interpret, AI_TRANSCRIBE to transcribe, AI_MULTI_EMBED to search scenes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Composes with other AI Functions&lt;/strong&gt;: Chain with AI_CLASSIFY / AI_SENTIMENT / AI_AGG for flexible pipelines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Governance preserved&lt;/strong&gt;: Your media data never leaves Snowflake&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQL-native&lt;/strong&gt;: Drops cleanly into your existing data pipelines&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Supported models and limits will keep expanding, opening up even more use cases over time. Whether it's call centers, meeting analysis, content moderation, education, or marketing, I hope you'll use Cortex AI's multimodal support to unlock new value from media that previously sat untouched!&lt;/p&gt;
&lt;h2&gt;
  
  
  Promotion
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Snowflake Japan's Official YouTube Channel
&lt;/h3&gt;

&lt;p&gt;The official Snowflake Japan YouTube channel has launched, and it already includes a walkthrough of Snowflake App Runtime. The video covers what App Runtime is and how to get an app deployed, with a live demo. It's in Japanese, but the demo sections should still be easy to follow.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/i_oA6QY8T8Y" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;h3&gt;
  
  
  Snowflake What's New Updates on X
&lt;/h3&gt;

&lt;p&gt;I share Snowflake What's New updates on X. Follow for the latest insights:&lt;/p&gt;
&lt;h4&gt;
  
  
  English Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_en" rel="noopener noreferrer"&gt;Snowflake What's New Bot (English Version)&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Japanese Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_jp" rel="noopener noreferrer"&gt;Snowflake's What's New Bot (Japanese Version)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Change Log
&lt;/h2&gt;

&lt;p&gt;(20260517) Initial post&lt;br&gt;
(20260606) Updated the supported-models section: &lt;code&gt;gemini-3.5-flash&lt;/code&gt; was added for video/audio input&lt;br&gt;
(20260923) &lt;strong&gt;Major revision.&lt;/strong&gt; Added &lt;code&gt;gemini-3.1-flash-lite&lt;/code&gt; to the models that accept video and audio directly. Rewrote the comparison section to reflect that AI_TRANSCRIBE now accepts video files as-is, and documented how to request speaker-level timestamps. Added a new section on semantic video search with AI_MULTI_EMBED. Broke per-request limits down by media type, and added sections on passing multiple files via the &lt;code&gt;PROMPT&lt;/code&gt; function and on creating a stage for media files. Noted AI_TRANSCRIBE's 10-second minimum billing duration and how its supported formats differ from AI_COMPLETE's. Made the sample app model-selectable and documented that the model name cannot be a bind variable&lt;/p&gt;
&lt;h2&gt;
  
  
  Original Japanese Article
&lt;/h2&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://zenn.dev/snowflakejp/articles/794ce748589765" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Fupload%2Fs--xe4l5Sfb--%2Fc_fit%252Cg_north_west%252Cl_text%3Anotosansjp-medium.otf_55%3ASnowflake%252520AI_COMPLETE%252520%2525E9%252596%2525A2%2525E6%252595%2525B0%2525E3%252581%2525A7%2525E5%25258B%252595%2525E7%252594%2525BB%2525E3%252581%2525A8%2525E9%25259F%2525B3%2525E5%2525A3%2525B0%2525E3%252582%252592%2525E7%25259B%2525B4%2525E6%25258E%2525A5%2525E5%252588%252586%2525E6%25259E%252590%252Cw_1010%252Cx_90%252Cy_100%2Fg_south_west%252Cl_text%3Anotosansjp-medium.otf_34%3Atsubasa%252Cx_220%252Cy_108%2Fbo_3px_solid_rgb%3Ad6e3ed%252Cg_south_west%252Ch_90%252Cl_fetch%3AaHR0cHM6Ly9zdGF0aWMuemVubi5zdHVkaW8vdXNlci11cGxvYWQvYXZhdGFyLzQ0ZmE2OGQyM2YuanBlZw%3D%3D%252Cr_20%252Cw_90%252Cx_92%252Cy_102%2Fco_rgb%3A6e7b85%252Cg_south_west%252Cl_text%3Anotosansjp-medium.otf_30%3ASnowflake%252520Japan%252Cx_220%252Cy_160%2Fbo_4px_solid_white%252Cg_south_west%252Ch_50%252Cl_fetch%3AaHR0cHM6Ly9zdGF0aWMuemVubi5zdHVkaW8vdXNlci11cGxvYWQvYXZhdGFyL2RkODMzYmYwZDcuanBlZw%3D%3D%252Cr_max%252Cw_50%252Cx_139%252Cy_84%2Fv1627283836%2Fdefault%2Fog-base-w1200-v2.png%3F_a%3DBACMTiAE" height="630" class="m-0" width="1200"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://zenn.dev/snowflakejp/articles/794ce748589765" rel="noopener noreferrer" class="c-link"&gt;
            Snowflake AI_COMPLETE 関数で動画と音声を直接分析
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstatic.zenn.studio%2Fimages%2Flogo-transparent.png" width="315" height="315"&gt;
          zenn.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>snowflake</category>
      <category>sql</category>
      <category>llm</category>
      <category>multimodal</category>
    </item>
    <item>
      <title>Supercharge Cortex Code CLI - A Practical Guide to Skills, SubAgents, Hooks and MCP</title>
      <dc:creator>Tsubasa Kanno</dc:creator>
      <pubDate>Tue, 31 Mar 2026 16:25:40 +0000</pubDate>
      <link>https://dev.to/tsubasa_tech/supercharge-cortex-code-cli-a-practical-guide-to-skills-subagents-hooks-and-mcp-lc8</link>
      <guid>https://dev.to/tsubasa_tech/supercharge-cortex-code-cli-a-practical-guide-to-skills-subagents-hooks-and-mcp-lc8</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I was originally a &lt;strong&gt;Cursor&lt;/strong&gt; user for AI-assisted coding. But as someone who works with Snowflake data and features daily, I realized how powerful it is to have an &lt;strong&gt;AI agent that natively connects to Snowflake's data, functions, and catalog — living right in your terminal&lt;/strong&gt;. That's when I made &lt;strong&gt;CoCo CLI&lt;/strong&gt; my primary tool. (At Snowflake Summit 2026, Cortex Code was officially renamed &lt;strong&gt;CoCo&lt;/strong&gt;. I'll use "CoCo CLI" throughout this article.)&lt;/p&gt;

&lt;p&gt;As I used CoCo CLI more, I wanted an agent that could work more autonomously. CoCo CLI offers extensive customization capabilities, and I've gone deep — defining 7 custom skills, 5 custom subagents, quality-check hooks with Slack notifications, and MCP integrations with external tools. The result has been a dramatic improvement in my day-to-day productivity.&lt;/p&gt;

&lt;p&gt;This article won't cover CoCo CLI basics or installation — for those, check out the &lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code-cli" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;. Instead, I'll dive into the &lt;strong&gt;4 extensibility features (Skills, SubAgents, Hooks, MCP)&lt;/strong&gt; and &lt;strong&gt;AGENTS.md&lt;/strong&gt;, sharing tips from the &lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/extensibility" rel="noopener noreferrer"&gt;official docs&lt;/a&gt; combined with practical insights from my own experience.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: This article contains many opinions based on my personal experience. This is not an official Snowflake statement, and customization methods or best practices may change with future updates.&lt;/p&gt;

&lt;p&gt;Update (2026/6/6): Following Snowflake Summit 2026, this article reflects the latest naming and feature set. "Cortex Code" is now &lt;strong&gt;CoCo&lt;/strong&gt;, and the lineup has grown to include &lt;strong&gt;Plugins&lt;/strong&gt; (bundle and share skills, subagents, hooks, and MCP servers as a package) and &lt;strong&gt;CoCo Desktop&lt;/strong&gt; (a GUI version, currently in Public Preview).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Big Picture of CoCo CLI Extensibility
&lt;/h2&gt;

&lt;p&gt;CoCo CLI customization breaks down into two categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AGENTS.md&lt;/strong&gt; — A Markdown file placed at the project root that communicates project-specific rules and constraints to the agent (&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code" rel="noopener noreferrer"&gt;Official docs: Cortex Code&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4 Extensibility Features&lt;/strong&gt; — Mechanisms documented on the &lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/extensibility" rel="noopener noreferrer"&gt;official Extensibility page&lt;/a&gt; that extend the agent's capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffe69xvm5sx8szxnoenl5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffe69xvm5sx8szxnoenl5.png" alt="CoCo CLI Extensibility Overview" width="799" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's a summary of each feature's role:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AGENTS.md&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Communicate project-specific rules &amp;amp; constraints&lt;/td&gt;
&lt;td&gt;Project&lt;/td&gt;
&lt;td&gt;Markdown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Skills&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Inject domain-specific expertise &amp;amp; workflows&lt;/td&gt;
&lt;td&gt;Project / Global&lt;/td&gt;
&lt;td&gt;YAML frontmatter + Markdown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SubAgents&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Delegate tasks to independent specialized agents&lt;/td&gt;
&lt;td&gt;Project / Global&lt;/td&gt;
&lt;td&gt;YAML frontmatter + Markdown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hooks&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intercept lifecycle events for custom control&lt;/td&gt;
&lt;td&gt;Project / Global&lt;/td&gt;
&lt;td&gt;JSON + Shell scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MCP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Add external tool &amp;amp; service integrations&lt;/td&gt;
&lt;td&gt;Global&lt;/td&gt;
&lt;td&gt;JSON&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Let's explore each feature in detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  AGENTS.md — Injecting Project Rules
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;AGENTS.md&lt;/strong&gt; is a Markdown file placed at the project root that communicates project-specific rules and coding conventions to the CoCo CLI agent. (&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code" rel="noopener noreferrer"&gt;Official docs: Cortex Code&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;AGENTS.md is separate from the 4 extensibility features (Skills, SubAgents, Hooks, MCP) on the &lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/extensibility" rel="noopener noreferrer"&gt;Extensibility page&lt;/a&gt;. While extensibility features extend the agent's &lt;strong&gt;capabilities&lt;/strong&gt;, AGENTS.md defines the agent's &lt;strong&gt;behavioral guidelines&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Location&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Project root directory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Format&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free-form Markdown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Loading&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Auto-loaded at session start&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Effect&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Improves agent response quality &amp;amp; consistency&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Basic Usage
&lt;/h3&gt;

&lt;p&gt;Simply create an &lt;code&gt;AGENTS.md&lt;/code&gt; file in your project root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Project Rules&lt;/span&gt;

&lt;span class="gu"&gt;## Coding Standards&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Follow Black formatter for Python code style
&lt;span class="p"&gt;-&lt;/span&gt; Always include type hints
&lt;span class="p"&gt;-&lt;/span&gt; Use Google-style docstrings

&lt;span class="gu"&gt;## Snowflake-Specific Rules&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Write SQL in uppercase
&lt;span class="p"&gt;-&lt;/span&gt; Use full paths for table names: &lt;span class="sb"&gt;`DB.SCHEMA.TABLE`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Use &lt;span class="sb"&gt;`MY_WH`&lt;/span&gt; warehouse

&lt;span class="gu"&gt;## Testing&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Run tests with pytest: &lt;span class="sb"&gt;`pytest tests/ -v`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Maintain 80%+ coverage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: Adding AGENTS.md dramatically improves agent responses. For team development, documenting coding standards and project rules in AGENTS.md ensures consistent AI-assisted quality across all team members.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Effective AGENTS.md Structure
&lt;/h3&gt;

&lt;p&gt;Here's the structure pattern I use in practice:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Project Overview&lt;/span&gt;
(Brief description of purpose and architecture)

&lt;span class="gh"&gt;# Directory Structure&lt;/span&gt;
(Key directories and file roles)

&lt;span class="gh"&gt;# Tech Stack&lt;/span&gt;
(Languages, frameworks, tools)

&lt;span class="gh"&gt;# Coding Standards (Do)&lt;/span&gt;
(Style guide, naming conventions, comment policy)

&lt;span class="gh"&gt;# Don'ts&lt;/span&gt;
(Secrets handling, destructive SQL prohibition, direct production access ban)

&lt;span class="gh"&gt;# Snowflake-Specific Settings&lt;/span&gt;
(Connection info, default warehouse/role, naming conventions)

&lt;span class="gh"&gt;# Testing &amp;amp; Quality&lt;/span&gt;
(Test commands, lint commands, CI/CD notes)

&lt;span class="gh"&gt;# Custom Skills &amp;amp; SubAgents Guide&lt;/span&gt;
(Names and purposes of custom skills/subagents used in the project)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  TIPS: Making AGENTS.md Work Effectively
&lt;/h3&gt;

&lt;p&gt;AGENTS.md can also be placed at &lt;code&gt;.cortex/AGENTS.md&lt;/code&gt; or in subdirectories, and you can use multiple files. However, keep these points in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AGENTS.md is an Instruction at the start of task execution.&lt;/strong&gt; Writing too many rules tends to dilute compliance. &lt;strong&gt;Focus on high-priority items and keep it concise.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicit Do / Don't sections are effective.&lt;/strong&gt; Clearly separating "what to do" from "what not to do" improves the agent's decision accuracy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Include directory structure.&lt;/strong&gt; Documenting your project's folder structure helps the agent choose appropriate file locations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a custom skills/subagents guide.&lt;/strong&gt; Listing names, purposes, and invocation methods of your custom skills/subagents helps the agent use them at the right time.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: AGENTS.md is just an Instruction — there's no guarantee the agent will always follow it. For higher compliance rates, clear and concise writing is key. To &lt;strong&gt;enforce&lt;/strong&gt; rules, consider using &lt;strong&gt;Hooks&lt;/strong&gt; (e.g., PreToolUse to block dangerous operations).&lt;/p&gt;

&lt;p&gt;Since CoCo CLI is natively integrated with Snowflake, leveraging &lt;strong&gt;Snowflake governance features&lt;/strong&gt; like RBAC (roles), masking policies, and Row Access Policies for data access control is highly effective. Rather than writing "don't directly modify production tables" in AGENTS.md, simply restricting write permissions via roles is far more reliable. Soft guidelines in AGENTS.md, hard enforcement via Hooks and Snowflake governance — this separation is another strength of CoCo CLI.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Skills — Injecting Domain Knowledge
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/extensibility" rel="noopener noreferrer"&gt;Official docs: Extensibility - Skills&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Skills&lt;/strong&gt; are Markdown files that define domain-specific expertise and workflows, injected into the agent's context when needed. For example, "demo environment setup procedures," "periodic report creation workflows," or "PoC documentation templates" — by defining frequently-used business workflows as skills, you eliminate the need to instruct from scratch every time.&lt;/p&gt;

&lt;p&gt;There are &lt;strong&gt;2 ways&lt;/strong&gt; to invoke skills:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Explicit invocation&lt;/strong&gt; — Use the &lt;code&gt;$skill-name&lt;/code&gt; prefix to directly specify a skill&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic activation&lt;/strong&gt; — The agent matches your question against skill &lt;code&gt;description&lt;/code&gt; fields and auto-loads relevant skills&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Many built-in skills have a &lt;code&gt;[REQUIRED]&lt;/code&gt; tag, causing them to activate automatically when questions hit their domain. For instance, simply typing "I want to create a Dynamic Table pipeline" automatically loads the &lt;code&gt;dynamic-tables&lt;/code&gt; skill with specialized guidance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feppzqn3wxv8i44g0df2y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feppzqn3wxv8i44g0df2y.png" alt="Skills Invocation Flow" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Skill Locations
&lt;/h3&gt;

&lt;p&gt;Skills are loaded from multiple locations (highest to lowest priority). (&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/extensibility" rel="noopener noreferrer"&gt;Official docs: Extensibility&lt;/a&gt;)&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Project&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.cortex/skills/&lt;/code&gt; or &lt;code&gt;.claude/skills/&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Project-specific&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;User&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/.snowflake/cortex/skills/&lt;/code&gt; or &lt;code&gt;~/.claude/skills/&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;User-specific&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Global&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.snowflake/cortex/skills/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shared across all projects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Session&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Added temporarily during session&lt;/td&gt;
&lt;td&gt;Disappears when session ends&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Remote&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloned from Git repository&lt;/td&gt;
&lt;td&gt;Cached&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bundled&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built into CoCo CLI&lt;/td&gt;
&lt;td&gt;Official Snowflake skills&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Custom skill creation directories are also documented as &lt;code&gt;.cortex/commands/&lt;/code&gt; or &lt;code&gt;.claude/commands/&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating SKILL.md
&lt;/h3&gt;

&lt;p&gt;Skills are Markdown files named &lt;code&gt;SKILL.md&lt;/code&gt; with YAML frontmatter at the top:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-custom-skill&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Description&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;this&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;skill&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(shown&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;skill&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;listings)"&lt;/span&gt;
&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;snowflake_sql_execute&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;snowflake_object_search&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;web_search&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="c1"&gt;# Purpose&lt;/span&gt;
&lt;span class="s"&gt;(What this skill does)&lt;/span&gt;

&lt;span class="c1"&gt;# Prerequisites&lt;/span&gt;
&lt;span class="s"&gt;(Required environment/data for execution)&lt;/span&gt;

&lt;span class="c1"&gt;# Workflow&lt;/span&gt;
&lt;span class="na"&gt;1. Step 1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;
&lt;span class="na"&gt;2. Step 2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;
&lt;span class="na"&gt;3. Step 3&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;# Output&lt;/span&gt;
&lt;span class="s"&gt;(Expected deliverables)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Frontmatter&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Unique identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Skill description (shown in &lt;code&gt;/skill list&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tools&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Tools to enable when skill is active&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  CLI Commands
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cortex skill list
cortex skill add /path/to/.cortex/skills/my-skill
cortex skill add https://github.com/org/my-skills.git
cortex skill remove /path/to/.cortex/skills/my-skill
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Invoking Skills in a Session
&lt;/h3&gt;

&lt;p&gt;There are two main approaches — &lt;strong&gt;explicit invocation&lt;/strong&gt; and &lt;strong&gt;automatic activation&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Skill listing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Type &lt;code&gt;/skill&lt;/code&gt; or &lt;code&gt;$&lt;/code&gt; in session&lt;/td&gt;
&lt;td&gt;Shows available skill candidates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Explicit invocation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;$skill-name instruction&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Loads the specified skill and executes the task&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auto-activation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Just ask your question normally&lt;/td&gt;
&lt;td&gt;Agent auto-selects skills matching the &lt;code&gt;description&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$demo&lt;/span&gt;&lt;span class="nt"&gt;-builder&lt;/span&gt; Set up a demo environment
&lt;span class="nv"&gt;$code&lt;/span&gt;&lt;span class="nt"&gt;-review&lt;/span&gt; Review @src/app.py following &lt;span class="nv"&gt;$security&lt;/span&gt;&lt;span class="nt"&gt;-guidelines&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For auto-activation, you don't need to specify skill names. Many built-in skills have &lt;code&gt;[REQUIRED]&lt;/code&gt; tags and automatically load when relevant domain questions are asked.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; I want to create a Streamlit app
→ developing-with-streamlit skill auto-activates

&amp;gt; Build a web app that runs on Snowflake (App Runtime)
→ snowflake-apps skill auto-activates

&amp;gt; Analyze my costs
→ cost-intelligence skill auto-activates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: Use &lt;code&gt;cortex skill list&lt;/code&gt; from outside a session to check available skills. Before creating custom skills, explore what's already built-in.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Built-in Skills
&lt;/h3&gt;

&lt;p&gt;CoCo CLI ships with &lt;strong&gt;dozens of built-in skills&lt;/strong&gt; covering major Snowflake capabilities, and the count keeps growing with each release. From data engineering to governance, ML, and cost analysis — everything is ready out of the box, making it one of CoCo CLI's biggest strengths.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Skills&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Foundation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;dynamic-tables&lt;/code&gt;, &lt;code&gt;iceberg&lt;/code&gt;, &lt;code&gt;lineage&lt;/code&gt;, &lt;code&gt;data-quality&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Development&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;developing-with-streamlit&lt;/code&gt;, &lt;code&gt;build-app&lt;/code&gt;, &lt;code&gt;snowflake-apps&lt;/code&gt;, &lt;code&gt;snowpark-python&lt;/code&gt;, &lt;code&gt;snowpark-connect&lt;/code&gt;, &lt;code&gt;snowflake-notebooks&lt;/code&gt;, &lt;code&gt;dbt-projects-on-snowflake&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AI / ML&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;cortex-agent&lt;/code&gt;, &lt;code&gt;cortex-ai-functions&lt;/code&gt;, &lt;code&gt;semantic-view&lt;/code&gt;, &lt;code&gt;machine-learning&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Governance / Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;data-governance&lt;/code&gt;, &lt;code&gt;trust-center&lt;/code&gt;, &lt;code&gt;network-security&lt;/code&gt;, &lt;code&gt;key-and-secret-management&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Operations / Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;cost-intelligence&lt;/code&gt;, &lt;code&gt;workload-performance-analysis&lt;/code&gt;, &lt;code&gt;organization-management&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Sharing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;data-cleanrooms&lt;/code&gt;, &lt;code&gt;declarative-sharing&lt;/code&gt;, &lt;code&gt;internal-marketplace-org-listing&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Infrastructure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;deploy-to-spcs&lt;/code&gt;, &lt;code&gt;integrations&lt;/code&gt;, &lt;code&gt;openflow&lt;/code&gt;, &lt;code&gt;snowflake-postgres&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Migration / Admin&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;snowconvert-assessment&lt;/code&gt;, &lt;code&gt;dcm&lt;/code&gt;, &lt;code&gt;dashboard&lt;/code&gt;, &lt;code&gt;skill-development&lt;/code&gt;, &lt;code&gt;cortex-code-guide&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Built-in skills change with CoCo CLI version updates and new ones are added regularly. The table above is a snapshot — always check the latest with &lt;code&gt;cortex skill list&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Practical Example: Demo Environment Builder Skill
&lt;/h3&gt;

&lt;p&gt;Here's an example skill for building customer demo environments:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;demo-builder&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Build&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;clean&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;up&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Snowflake&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;demo&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;environments"&lt;/span&gt;
&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;snowflake_sql_execute&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;snowflake_object_search&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;web_search&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="c1"&gt;# Demo Builder Skill&lt;/span&gt;

&lt;span class="c1"&gt;## Goal&lt;/span&gt;
&lt;span class="s"&gt;Build and manage Snowflake demo environments tailored to&lt;/span&gt;
&lt;span class="s"&gt;customer use cases, in a reproducible manner.&lt;/span&gt;

&lt;span class="c1"&gt;## Workflow&lt;/span&gt;
&lt;span class="c1"&gt;### Phase 1: Requirements&lt;/span&gt;
&lt;span class="s"&gt;Confirm demo theme, target features, and required datasets.&lt;/span&gt;

&lt;span class="c1"&gt;### Phase 2: Environment Setup&lt;/span&gt;
&lt;span class="s"&gt;Create DB/schema/warehouse, load sample data,&lt;/span&gt;
&lt;span class="s"&gt;deploy Streamlit apps as needed.&lt;/span&gt;

&lt;span class="c1"&gt;### Phase 3: Verification&lt;/span&gt;
&lt;span class="s"&gt;Test all queries/apps and create demo scenarios.&lt;/span&gt;

&lt;span class="c1"&gt;### Phase 4: Cleanup&lt;/span&gt;
&lt;span class="s"&gt;Generate scripts to safely tear down the environment post-demo.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;With this skill defined, simply invoking &lt;code&gt;$demo-builder Set up a Cortex AI demo&lt;/code&gt; kicks off the entire workflow automatically.&lt;/p&gt;
&lt;h2&gt;
  
  
  SubAgents — Specialized Agent Delegation
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/extensibility" rel="noopener noreferrer"&gt;Official docs: Extensibility - Subagents&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;SubAgents&lt;/strong&gt; are independent, specialized AI agents that operate separately from the main agent. Each can have its own model, tools, and prompts, with parallel execution support.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Independence&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Operates in separate context from main agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Specialization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Specify optimal model and tools per task&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Parallel execution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Up to 50 concurrent agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Worktree Isolation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Isolate changes using Git worktrees&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Built-in SubAgents
&lt;/h3&gt;

&lt;p&gt;CoCo CLI includes these built-in subagent types: (&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/extensibility" rel="noopener noreferrer"&gt;Official docs: Extensibility&lt;/a&gt;)&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;general-purpose&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full tool access, general-purpose agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;explore&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Codebase exploration specialist (&lt;code&gt;quick&lt;/code&gt; / &lt;code&gt;medium&lt;/code&gt; / &lt;code&gt;very thorough&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;plan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Implementation planning &amp;amp; design&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;feedback&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Structured feedback collection&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Creating Custom SubAgents
&lt;/h3&gt;

&lt;p&gt;SubAgents are defined as &lt;code&gt;.md&lt;/code&gt; files:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Project&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.cortex/agents/&amp;lt;name&amp;gt;.md&lt;/code&gt; or &lt;code&gt;.claude/agents/&amp;lt;name&amp;gt;.md&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Global&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.snowflake/cortex/agents/&amp;lt;name&amp;gt;.md&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;User&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.claude/agents/&amp;lt;name&amp;gt;.md&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Agent Definition Example
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;critic-reviewer&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Performs&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;critical&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;review&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;from&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;quality&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;best&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;practices&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;perspective"&lt;/span&gt;
&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Read&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Grep&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Glob&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Bash&lt;/span&gt;
&lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openai-gpt-5.2&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="c1"&gt;# Critic Reviewer Agent&lt;/span&gt;

&lt;span class="s"&gt;You are a senior software engineer performing code reviews.&lt;/span&gt;

&lt;span class="c1"&gt;## Review Criteria&lt;/span&gt;
&lt;span class="s"&gt;1. Code readability &amp;amp; maintainability&lt;/span&gt;
&lt;span class="s"&gt;2. Performance bottlenecks&lt;/span&gt;
&lt;span class="s"&gt;3. Security concerns&lt;/span&gt;
&lt;span class="s"&gt;4. Error handling adequacy&lt;/span&gt;

&lt;span class="c1"&gt;## Output Format&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;🔴 Critical&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Must fix&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;🟡 Warning&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Recommended fix&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;🟢 Info&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Room for improvement&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Model Selection — The Greatest Strength of SubAgents
&lt;/h3&gt;

&lt;p&gt;Custom subagents let you specify a model per agent via the &lt;code&gt;model&lt;/code&gt; field. This is SubAgents' greatest strength.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;claude-opus-4-6&lt;/span&gt;     &lt;span class="c1"&gt;# For high-accuracy tasks&lt;/span&gt;
&lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;claude-sonnet-4-6&lt;/span&gt;   &lt;span class="c1"&gt;# For lightweight, fast tasks&lt;/span&gt;
&lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openai-gpt-5.2&lt;/span&gt;      &lt;span class="c1"&gt;# Leverage different model perspectives&lt;/span&gt;
&lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;auto&lt;/span&gt;                &lt;span class="c1"&gt;# Cost-optimized auto-selection&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;TIPS: Cross-model diversity improves quality&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When your main agent uses &lt;code&gt;claude-opus-4-6&lt;/code&gt;, deliberately assigning &lt;code&gt;openai-gpt-5.2&lt;/code&gt; to your review subagent enables critical review from a different model's perspective. A different model family can catch blind spots and mistakes that the same model tends to miss.&lt;/p&gt;

&lt;p&gt;Meanwhile, for simpler tasks like knowledge curation or log summarization, assigning a lightweight model like &lt;code&gt;claude-sonnet-4-6&lt;/code&gt; keeps costs down while boosting overall throughput.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Model Selection Strategy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Main agent&lt;/td&gt;
&lt;td&gt;High-accuracy model (&lt;code&gt;claude-opus-4-6&lt;/code&gt;, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Critical review&lt;/td&gt;
&lt;td&gt;Deliberately use a different model family (&lt;code&gt;openai-gpt-5.2&lt;/code&gt;, etc.) for diverse perspectives&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Knowledge curation / summarization&lt;/td&gt;
&lt;td&gt;Lightweight model (&lt;code&gt;claude-sonnet-4-6&lt;/code&gt;, etc.) for cost efficiency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exploration / research&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;auto&lt;/code&gt; for cost optimization&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Session-wide model can also be overridden via the &lt;code&gt;CORTEX_AGENT_MODEL&lt;/code&gt; environment variable. (&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/settings" rel="noopener noreferrer"&gt;Official docs: Settings&lt;/a&gt;)&lt;/p&gt;
&lt;h3&gt;
  
  
  Invocation
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Auto-delegation (agent decides)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Search all &lt;span class="nb"&gt;test &lt;/span&gt;files under src/

&lt;span class="c"&gt;# Explicit specification&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Use the Explore agent to find all SQL files

&lt;span class="c"&gt;# Parallel execution&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; In parallel, search &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="nb"&gt;test &lt;/span&gt;files and check config files

&lt;span class="c"&gt;# Background execution&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Run a background agent to refactor the code

&lt;span class="c"&gt;# Worktree Isolation (runs in an isolated git branch)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Implement feature X with worktree isolation

&lt;span class="c"&gt;# Agent management&lt;/span&gt;
/agents                    &lt;span class="c"&gt;# Agent list (Ctrl-B also works)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Get the output from agent abc1234
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;kill &lt;/span&gt;agent abc1234
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; Resume agent abc1234 and &lt;span class="k"&gt;continue &lt;/span&gt;from where it left off
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Practical Example: Specialized Agent Configuration
&lt;/h3&gt;

&lt;p&gt;Here's my setup with purpose-specific agents:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;critic-reviewer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;openai-gpt-5.2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Critical review using a different model from main&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;research-analyst&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;auto&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Web research &amp;amp; document analysis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;code-implementer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;claude-opus-4-6&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Complex code implementation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;qa-validator&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;claude-opus-4-6&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Test design &amp;amp; execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;knowledge-curator&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;claude-sonnet-4-6&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Knowledge organization &amp;amp; documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Hooks — Lifecycle Control
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/extensibility" rel="noopener noreferrer"&gt;Official docs: Extensibility - Hooks&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Hooks&lt;/strong&gt; execute custom logic at key lifecycle points in CoCo CLI.&lt;/p&gt;

&lt;p&gt;Personally, I consider Hooks the most important of the four extensibility features. As AI agents evolve, we'll increasingly delegate tasks asynchronously. But this creates common pain points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unaware&lt;/strong&gt; — The agent finishes work, but the user doesn't notice and leaves it idle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stuck&lt;/strong&gt; — The agent is waiting for user input, but the user doesn't realize it's blocked&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Settling&lt;/strong&gt; — The agent produces low-quality output and completes without improvement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hooks address these challenges. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send &lt;strong&gt;Slack notifications&lt;/strong&gt; on &lt;code&gt;Notification&lt;/code&gt; events so you never miss an input request or completion&lt;/li&gt;
&lt;li&gt;Run &lt;strong&gt;quality checks&lt;/strong&gt; on &lt;code&gt;Stop&lt;/code&gt; events and force the agent to continue if results don't meet standards&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Hooks have many configuration options and may require some trial-and-error to get the behavior you want. But they're incredibly powerful — I personally receive Slack notifications to issue next instructions and use quality-check hooks to force the agent to self-review and elevate output quality, achieving a truly "set it and forget it" workflow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6v0wef5mm7k05axu147q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6v0wef5mm7k05axu147q.png" alt="Hooks Lifecycle Sequence" width="800" height="752"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Configuration File Locations
&lt;/h3&gt;

&lt;p&gt;Hooks are configured in the following locations (highest to lowest priority):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Local&lt;/strong&gt; (highest)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.cortex/settings.local.json&lt;/code&gt; or &lt;code&gt;.claude/settings.local.json&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Project&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.cortex/settings.json&lt;/code&gt; or &lt;code&gt;.claude/settings.json&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;User&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.claude/settings.json&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Global&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.snowflake/cortex/hooks.json&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Available Events
&lt;/h3&gt;

&lt;p&gt;The 11 hook events defined in official docs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Timing&lt;/th&gt;
&lt;th&gt;Can Block?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PreToolUse&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Before tool execution&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PostToolUse&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;After successful tool execution&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PermissionRequest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;When permission is needed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UserPromptSubmit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;When user submits prompt&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SessionStart&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;When session starts&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SessionEnd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;When session ends&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PreCompact&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Before context compaction&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Stop&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;When agent response completes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SubagentStop&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;When subagent completes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Notification&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;On notification (e.g., waiting for user input)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Setup&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;During initialization&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Hook Types
&lt;/h3&gt;

&lt;p&gt;Two types of hooks are available: (&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/extensibility" rel="noopener noreferrer"&gt;Official docs: Extensibility&lt;/a&gt;)&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;command&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Execute shell commands&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bash /path/to/script.sh&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;prompt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Evaluate natural language prompt via LLM&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Is this command safe? $ARGUMENTS&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Exit Code Semantics
&lt;/h3&gt;

&lt;p&gt;Hook script exit codes control CoCo CLI behavior:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Exit Code&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Success&lt;/td&gt;
&lt;td&gt;Process stdout JSON and continue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Block&lt;/td&gt;
&lt;td&gt;stderr / JSON &lt;code&gt;reason&lt;/code&gt; sent to agent; operation blocked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Other&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Error&lt;/td&gt;
&lt;td&gt;Non-blocking. stderr shown only in verbose mode; execution continues&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Configuration Format
&lt;/h3&gt;

&lt;p&gt;Example &lt;code&gt;hooks.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Stop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bash /path/to/hooks/quality_review.sh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"timeout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"PreToolUse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"matcher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bash /path/to/hooks/validate_bash.sh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"timeout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Matcher Patterns
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;matcher&lt;/code&gt; field narrows which tools trigger hooks. Regex is supported.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Bash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Bash only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Edit|Write&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Edit or Write&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mcp__.*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All MCP tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Notebook.*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;NotebookEdit, NotebookExecute, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Hook Input (stdin)
&lt;/h3&gt;

&lt;p&gt;Hook scripts receive JSON via stdin:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"session_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"abc123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hook_event_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Stop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/Users/my-project"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"transcript_path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/path/to/transcript.jsonl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tool_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tool_input"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ls -la"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Available Environment Variables
&lt;/h3&gt;

&lt;p&gt;These environment variables are available within hook scripts:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variable&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CORTEX_PROJECT_DIR&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Project directory path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CORTEX_CODE_REMOTE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;"true"&lt;/code&gt; in web context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CORTEX_ENV_FILE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Persistent environment file path&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Example 1: Quality Review Hook (Stop Event)
&lt;/h3&gt;

&lt;p&gt;A hook that performs LLM-based quality checks when the agent tries to complete a task, blocking and continuing work if quality is insufficient:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# quality_review_on_stop.sh&lt;/span&gt;

&lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Infinite loop prevention (critical!)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$INPUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.stop_hook_active'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nv"&gt;TRANSCRIPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$INPUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.transcript_path'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Get recent interactions and run LLM quality check&lt;/span&gt;
&lt;span class="nv"&gt;REVIEW_RESULT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;snow sql &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"
  SELECT SNOWFLAKE.CORTEX.COMPLETE(
    'claude-sonnet-4-6',
    'Rate the task completion from 1-10: ...'
  )
"&lt;/span&gt; &lt;span class="nt"&gt;--connection&lt;/span&gt; MY_CONN&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;SCORE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$REVIEW_RESULT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.score'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SCORE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-lt&lt;/span&gt; 7 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Quality score below threshold (&lt;/span&gt;&lt;span class="nv"&gt;$SCORE&lt;/span&gt;&lt;span class="s2"&gt;/10). Please improve."&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
  &lt;span class="nb"&gt;exit &lt;/span&gt;2  &lt;span class="c"&gt;# Block → agent continues working&lt;/span&gt;
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;0  &lt;span class="c"&gt;# Allow → agent stops&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Critical: Infinite loop prevention in Stop Hooks is mandatory.&lt;/strong&gt; When a Stop Hook returns block (exit 2), the agent continues working and the Stop event fires again. Always pass through with &lt;code&gt;exit 0&lt;/code&gt; when the &lt;code&gt;stop_hook_active&lt;/code&gt; flag is &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Example 2: Slack Notification Hook (Notification Event)
&lt;/h3&gt;

&lt;p&gt;A hook that sends Slack notifications when the agent is waiting for user input:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# notify_slack_on_notification.sh&lt;/span&gt;

&lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;MESSAGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$INPUT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.message // "Waiting for input"'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SLACK_WEBHOOK_URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;🔔 CoCo: &lt;/span&gt;&lt;span class="nv"&gt;$MESSAGE&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}"&lt;/span&gt;

&lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  MCP — External Tool Integration
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/extensibility" rel="noopener noreferrer"&gt;Official docs: Extensibility - MCP&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;MCP (Model Context Protocol)&lt;/strong&gt; is an open standard protocol for connecting external tools and services to AI agents. The key point here is that &lt;strong&gt;CoCo CLI itself functions as an MCP client&lt;/strong&gt;. This means you can add any publicly available MCP server to give your agent new capabilities.&lt;/p&gt;

&lt;p&gt;For example, draw.io MCP for diagrams, GitHub MCP for PR operations, Context7 MCP for latest library documentation — the possibilities are vast. MCP servers are growing daily, so definitely explore &lt;a href="https://github.com/modelcontextprotocol/servers" rel="noopener noreferrer"&gt;MCP servers&lt;/a&gt; and &lt;a href="https://mcp.so/" rel="noopener noreferrer"&gt;mcp.so&lt;/a&gt; to find servers that fit your workflow.&lt;/p&gt;
&lt;h3&gt;
  
  
  Transport Types
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Communication&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stdio&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Local tools, CLI wrappers&lt;/td&gt;
&lt;td&gt;Subprocess (stdin/stdout)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Web services, APIs&lt;/td&gt;
&lt;td&gt;HTTP requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sse&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Real-time services&lt;/td&gt;
&lt;td&gt;Server-Sent Events&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;OAuth authentication is supported for HTTP servers. Tokens are stored in &lt;code&gt;~/.snowflake/cortex/mcp_oauth/&lt;/code&gt; and auto-refreshed.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configuration File
&lt;/h3&gt;

&lt;p&gt;MCP server configuration goes in &lt;code&gt;~/.snowflake/cortex/mcp.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"drawio"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stdio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@drawio/mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"github"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stdio"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@modelcontextprotocol/server-github"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"GITHUB_PERSONAL_ACCESS_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${GITHUB_TOKEN}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Environment Variable Expansion
&lt;/h3&gt;

&lt;p&gt;Both &lt;code&gt;${VAR}&lt;/code&gt; and &lt;code&gt;$VAR&lt;/code&gt; syntax are supported for environment variable expansion in configuration files. (&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/extensibility" rel="noopener noreferrer"&gt;Official docs: Extensibility&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer ${MY_API_TOKEN}"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Never hardcode API keys in &lt;code&gt;mcp.json&lt;/code&gt;. Set them as environment variables in &lt;code&gt;~/.bashrc&lt;/code&gt; or &lt;code&gt;~/.zshrc&lt;/code&gt; like &lt;code&gt;export MY_API_TOKEN="your_token_here"&lt;/code&gt; — this is the officially recommended approach.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  CLI Commands
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cortex mcp add drawio npx &lt;span class="nt"&gt;-y&lt;/span&gt; @drawio/mcp
cortex mcp add my-api https://api.example.com &lt;span class="nt"&gt;--type&lt;/span&gt; http
cortex mcp add my-server npx my-mcp-server &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;secret
cortex mcp add my-server https://api.example.com &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer token"&lt;/span&gt;
cortex mcp list
cortex mcp get drawio
cortex mcp remove drawio
cortex mcp start drawio    &lt;span class="c"&gt;# Connection test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Tool Naming Convention
&lt;/h3&gt;

&lt;p&gt;MCP tools are namespaced for agent access:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mcp__{server-name}__{tool-name}

e.g.: mcp__drawio__open_drawio_xml
      mcp__github__create_pull_request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Session Management
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/mcp    &lt;span class="c"&gt;# Open MCP status viewer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Practical Example: draw.io MCP
&lt;/h3&gt;

&lt;p&gt;Adding the draw.io MCP server lets you instruct the agent to "create an architecture diagram for this design" and it generates the diagram in the draw.io editor.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cortex mcp add drawio npx &lt;span class="nt"&gt;-y&lt;/span&gt; @drawio/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Usage in session:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; Create an architecture diagram for this system in draw.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Putting It All Together
&lt;/h2&gt;

&lt;p&gt;The AGENTS.md and 4 extensibility features become even more powerful when combined. Here's a workflow pattern I use daily.&lt;/p&gt;
&lt;h3&gt;
  
  
  Pattern: AI-Assisted Development Workflow
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgeil468rpbnmpjz5aibd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgeil468rpbnmpjz5aibd.png" alt="AI-Assisted Development Workflow" width="800" height="885"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By combining these features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;AGENTS.md&lt;/strong&gt; always applies project-specific rules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skills&lt;/strong&gt; standardize repetitive workflows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SubAgents&lt;/strong&gt; process specialized tasks in parallel&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP&lt;/strong&gt; connects to external tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hooks&lt;/strong&gt; automate quality checks and notifications on task completion&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This creates a truly integrated workflow.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configuration File Overview
&lt;/h3&gt;

&lt;p&gt;Here's a partial extract of my CoCo CLI configuration structure — the actual setup has many more files, but these are the key ones. (&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/settings" rel="noopener noreferrer"&gt;Official docs: Settings&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.snowflake/cortex/
├── settings.json           # Main settings (theme, env vars, hooks)
├── mcp.json                # MCP server config
├── hooks.json              # Global hooks
├── permissions.json        # Permission settings
├── hooks/                  # Hook scripts
│   ├── quality_review_on_stop.sh
│   ├── notify_slack_on_stop.sh
│   └── ...
├── agents/                 # Custom SubAgents
│   ├── critic-reviewer.md
│   ├── research-analyst.md
│   └── ...
├── skills/                 # Global Skills
│   ├── demo-builder/SKILL.md
│   ├── competitive-analysis/SKILL.md
│   └── ...
├── memory/                 # Persistent memory
└── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;CoCo CLI is not just an AI coding assistant — by leveraging &lt;strong&gt;AGENTS.md&lt;/strong&gt; for project rules and the &lt;strong&gt;4 extensibility features (Skills, SubAgents, Hooks, MCP)&lt;/strong&gt;, you can build a powerful AI development environment tailored to your workflow.&lt;/p&gt;

&lt;p&gt;Personally, shifting from Cursor to CoCo CLI has been transformative. Being able to use customized agents while natively connected to Snowflake data and functions has dramatically improved my daily productivity. Here's what I find most valuable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Skills for workflow standardization&lt;/strong&gt;: Defining repetitive workflows like demo setup and documentation as skills eliminates starting from scratch every time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SubAgents for parallel execution&lt;/strong&gt;: Running research tasks in parallel dramatically reduces processing time for complex tasks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hooks for quality gates &amp;amp; notifications&lt;/strong&gt;: Auto-executing quality checks on task completion via Stop Hook and forcing continued work when quality is insufficient has been incredibly effective for raising output quality&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP for external tool integration&lt;/strong&gt;: Calling external tools like draw.io and GitHub directly from the agent dramatically reduces context-switching overhead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CoCo CLI's customization features will continue to evolve. I encourage you to dive into customization and build your own AI development environment!&lt;/p&gt;
&lt;h3&gt;
  
  
  Reference Links
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Document&lt;/th&gt;
&lt;th&gt;URL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CoCo CLI official&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code-cli" rel="noopener noreferrer"&gt;https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code-cli&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extensibility (Skills, SubAgents, Hooks, MCP)&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/extensibility" rel="noopener noreferrer"&gt;https://docs.snowflake.com/en/user-guide/cortex-code/extensibility&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Settings (Configuration &amp;amp; Priority)&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/settings" rel="noopener noreferrer"&gt;https://docs.snowflake.com/en/user-guide/cortex-code/settings&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/cortex-code/security" rel="noopener noreferrer"&gt;https://docs.snowflake.com/en/user-guide/cortex-code/security&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Promotion
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Snowflake What's New Updates on X
&lt;/h3&gt;

&lt;p&gt;I share Snowflake What's New updates on X. Follow for the latest insights:&lt;/p&gt;
&lt;h4&gt;
  
  
  English Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_en" rel="noopener noreferrer"&gt;Snowflake What's New Bot (English Version)&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Japanese Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_jp" rel="noopener noreferrer"&gt;Snowflake's What's New Bot (Japanese Version)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Change Log
&lt;/h2&gt;

&lt;p&gt;(20260606) Reflected Snowflake Summit 2026 updates: renamed Cortex Code to CoCo, noted Plugins and CoCo Desktop (Public Preview), generalized the built-in skill count, updated &lt;code&gt;build-react-app&lt;/code&gt; to &lt;code&gt;build-app&lt;/code&gt;, and added the &lt;code&gt;snowflake-apps&lt;/code&gt; skill&lt;br&gt;
(20260401) Initial post&lt;/p&gt;
&lt;h2&gt;
  
  
  Original Japanese Article
&lt;/h2&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://zenn.dev/snowflakejp/articles/46369359327022" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Fupload%2Fs--S1pmLNfi--%2Fc_fit%252Cg_north_west%252Cl_text%3Anotosansjp-medium.otf_55%3ACortex%252520Code%252520CLI%252520%2525E5%2525AE%25259F%2525E8%2525B7%2525B5%2525E3%252582%2525AB%2525E3%252582%2525B9%2525E3%252582%2525BF%2525E3%252583%25259E%2525E3%252582%2525A4%2525E3%252582%2525BA%2525E3%252582%2525AC%2525E3%252582%2525A4%2525E3%252583%252589%252Cw_1010%252Cx_90%252Cy_100%2Fg_south_west%252Cl_text%3Anotosansjp-medium.otf_34%3Atsubasa%252Cx_220%252Cy_108%2Fbo_3px_solid_rgb%3Ad6e3ed%252Cg_south_west%252Ch_90%252Cl_fetch%3AaHR0cHM6Ly9zdGF0aWMuemVubi5zdHVkaW8vdXNlci11cGxvYWQvYXZhdGFyLzQ0ZmE2OGQyM2YuanBlZw%3D%3D%252Cr_20%252Cw_90%252Cx_92%252Cy_102%2Fco_rgb%3A6e7b85%252Cg_south_west%252Cl_text%3Anotosansjp-medium.otf_30%3ASnowflake%252520Japan%252Cx_220%252Cy_160%2Fbo_4px_solid_white%252Cg_south_west%252Ch_50%252Cl_fetch%3AaHR0cHM6Ly9zdGF0aWMuemVubi5zdHVkaW8vdXNlci11cGxvYWQvYXZhdGFyL2RkODMzYmYwZDcuanBlZw%3D%3D%252Cr_max%252Cw_50%252Cx_139%252Cy_84%2Fv1627283836%2Fdefault%2Fog-base-w1200-v2.png%3F_a%3DBACMTiAE" height="630" class="m-0" width="1200"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://zenn.dev/snowflakejp/articles/46369359327022" rel="noopener noreferrer" class="c-link"&gt;
            Cortex Code CLI 実践カスタマイズガイド
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstatic.zenn.studio%2Fimages%2Flogo-transparent.png" width="315" height="315"&gt;
          zenn.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>snowflake</category>
      <category>agents</category>
      <category>llm</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Snowflake Data UI Guide - Choose the Right Tool for Every Analytics Use Case</title>
      <dc:creator>Tsubasa Kanno</dc:creator>
      <pubDate>Sun, 15 Feb 2026 05:54:49 +0000</pubDate>
      <link>https://dev.to/tsubasa_tech/snowflake-data-ui-guide-choose-the-right-tool-for-every-analytics-use-case-1n8d</link>
      <guid>https://dev.to/tsubasa_tech/snowflake-data-ui-guide-choose-the-right-tool-for-every-analytics-use-case-1n8d</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;It's been about two years since I joined Snowflake, and the transformation I've witnessed in data analytics UI has been nothing short of remarkable. Back in early 2024, when it came to working with data in Snowflake, your options were essentially &lt;strong&gt;Snowsight worksheets and dashboards&lt;/strong&gt;, plus &lt;strong&gt;third-party BI tools&lt;/strong&gt;. Streamlit in Snowflake (hereafter referred to as SiS) and Snowpark Container Services (hereafter referred to as SPCS) had just launched but weren't yet mainstream.&lt;/p&gt;

&lt;p&gt;Fast forward to today, and the landscape looks completely different. &lt;strong&gt;Snowflake CoWork&lt;/strong&gt;, &lt;strong&gt;Snowflake Workspaces&lt;/strong&gt;, &lt;strong&gt;Snowflake Notebooks&lt;/strong&gt;, &lt;strong&gt;Snowflake Managed MCP Server&lt;/strong&gt;, &lt;strong&gt;CoCo&lt;/strong&gt;, &lt;strong&gt;Vercel v0 integration&lt;/strong&gt; - the list of new options keeps growing. In my daily conversations with customers, one question has become increasingly common: &lt;em&gt;"With all these tools available, which one should we use?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's exactly what this article aims to answer. I'll provide a &lt;strong&gt;comprehensive overview of every UI option&lt;/strong&gt; for working with data in Snowflake, covering their strengths, limitations, target users, and ideal use cases. Whether you're a business user, data analyst, data scientist, or developer, I hope this guide helps you find the right tool for your needs!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note (2026/2/5)&lt;/strong&gt;: Some features mentioned in this article are still in development or Public Preview. They may be significantly updated in the future.&lt;/p&gt;

&lt;p&gt;Note: This article represents my personal views and not those of Snowflake. The tool evaluations and use case classifications are based on my personal experience and may vary depending on your organization and project requirements. Please treat this as one perspective.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update (2026/6/6)&lt;/strong&gt;: This article has been updated following Snowflake Summit 2026. At Summit 2026, &lt;strong&gt;Cortex Code was renamed CoCo&lt;/strong&gt; and &lt;strong&gt;Snowflake Intelligence was renamed Snowflake CoWork&lt;/strong&gt;, so this article uses &lt;strong&gt;CoCo&lt;/strong&gt; / &lt;strong&gt;Snowflake CoWork&lt;/strong&gt; from here on. I also added &lt;strong&gt;Snowflake App Runtime&lt;/strong&gt; and &lt;strong&gt;CoCo Desktop&lt;/strong&gt;, and refreshed release statuses. (Where the original name is the correct historical reference — past event names, external article titles, etc. — I've kept it as-is.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Evolution of Snowflake's Data UI
&lt;/h2&gt;

&lt;p&gt;As I mentioned, in early 2024, worksheets, dashboards, and BI tools were the primary ways to interact with Snowflake data. In just two years, this has diversified dramatically. &lt;strong&gt;Workspaces&lt;/strong&gt; has evolved worksheets into a full IDE experience. &lt;strong&gt;CoWork&lt;/strong&gt; enables business users to query data using natural language without writing SQL. &lt;strong&gt;Notebooks&lt;/strong&gt; brings data science workflows entirely within Snowflake. And with &lt;strong&gt;SiS Container Runtime&lt;/strong&gt;, you can now run lightweight dashboards at a fraction of the cost. On the AI front, Copilot has evolved into &lt;strong&gt;CoCo&lt;/strong&gt;, and &lt;strong&gt;MCP Server&lt;/strong&gt; enables AI Agent integration with Snowflake data.&lt;/p&gt;

&lt;p&gt;Behind this evolution are two major trends: &lt;strong&gt;democratization of data access&lt;/strong&gt; and &lt;strong&gt;AI-native analytics experiences&lt;/strong&gt;. Data utilization, once dominated by data engineers and analysts, is now extending to business users - with AI serving as the bridge.&lt;/p&gt;

&lt;h2&gt;
  
  
  UI Options at a Glance
&lt;/h2&gt;

&lt;p&gt;Here's a categorized overview of every UI option available for working with data in Snowflake.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Primary Users&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Snowflake Native UI (Analytics)&lt;/td&gt;
&lt;td&gt;Snowflake Workspaces&lt;/td&gt;
&lt;td&gt;Data Engineers, Data Analysts, Data Scientists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Snowflake CoWork&lt;/td&gt;
&lt;td&gt;Business Users, Data Analysts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Snowflake Notebooks&lt;/td&gt;
&lt;td&gt;Data Scientists, ML Engineers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Snowflake Native UI (Apps)&lt;/td&gt;
&lt;td&gt;SiS&lt;/td&gt;
&lt;td&gt;Data Analysts, Data Scientists → Business Users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Snowflake App Runtime&lt;/td&gt;
&lt;td&gt;Full-stack / Frontend Developers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Native Apps&lt;/td&gt;
&lt;td&gt;App Developers, ISVs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;SPCS&lt;/td&gt;
&lt;td&gt;ML Engineers, App Developers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI-Assisted Development&lt;/td&gt;
&lt;td&gt;CoCo in Snowsight&lt;/td&gt;
&lt;td&gt;Data Engineers, Data Analysts, Data Scientists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;CoCo CLI&lt;/td&gt;
&lt;td&gt;Developers, Data Engineers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;CoCo Desktop&lt;/td&gt;
&lt;td&gt;Developers, Data Engineers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Vercel v0 Integration&lt;/td&gt;
&lt;td&gt;Developers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI Agent / MCP Integration&lt;/td&gt;
&lt;td&gt;Snowflake Managed MCP Server&lt;/td&gt;
&lt;td&gt;Developers, AI Agent Users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;OSS Snowflake MCP Server&lt;/td&gt;
&lt;td&gt;Developers, AI Agent Users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Programmatic Access&lt;/td&gt;
&lt;td&gt;Snowflake CLI&lt;/td&gt;
&lt;td&gt;Developers, DevOps Engineers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Snowpark Python SDK&lt;/td&gt;
&lt;td&gt;Data Engineers, Data Scientists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;SQL API and Connectors&lt;/td&gt;
&lt;td&gt;Developers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Third-Party Integration&lt;/td&gt;
&lt;td&gt;BI Tools (Tableau, Power BI, etc.)&lt;/td&gt;
&lt;td&gt;Data Analysts, Business Users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Custom Applications&lt;/td&gt;
&lt;td&gt;Developers → Business Users&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Let's dive into each category in detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Snowflake Native UI (Analytics)
&lt;/h2&gt;

&lt;p&gt;Tools available within Snowsight for analyzing and exploring data using SQL or natural language.&lt;/p&gt;

&lt;h3&gt;
  
  
  Snowflake Workspaces
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
Snowflake Workspaces is an &lt;strong&gt;integrated development environment (IDE)&lt;/strong&gt; available within Snowsight. GA since September 2025, it represents a significant evolution from the traditional worksheet experience. Originally focused on SQL editing, Workspaces now supports &lt;strong&gt;Notebooks running directly within the environment&lt;/strong&gt;, unifying SQL and Python/Notebook development. &lt;strong&gt;Shared Workspaces&lt;/strong&gt; became GA in January 2026 for team collaboration, and &lt;strong&gt;Notebooks in Workspaces&lt;/strong&gt; went GA in February 2026.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SQL execution, Notebooks, dbt projects, data preview, object management, Git integration, CoCo AI assistance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Data Engineers, Data Analysts, Data Scientists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Status&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Workspaces: GA (2025/9), Shared Workspaces: GA (2026/1), Notebooks in Workspaces: GA (2026/2)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zero-setup: start working immediately&lt;/li&gt;
&lt;li&gt;Unified environment for SQL, Python (Notebooks), and dbt&lt;/li&gt;
&lt;li&gt;CoCo AI assistance for natural language code generation and editing&lt;/li&gt;
&lt;li&gt;Git integration for version control&lt;/li&gt;
&lt;li&gt;Shared Workspaces for team collaboration&lt;/li&gt;
&lt;li&gt;Role-based access control (RBAC) for easy permission management&lt;/li&gt;
&lt;li&gt;Parallel query execution from a single file&lt;/li&gt;
&lt;li&gt;Share pre-built queries with your team so anyone can run them anytime and view the latest data in tabular format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons / Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not suited for advanced visualizations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ad-hoc SQL / Python analysis&lt;/li&gt;
&lt;li&gt;Data pipeline development and debugging&lt;/li&gt;
&lt;li&gt;dbt project development and execution&lt;/li&gt;
&lt;li&gt;ML model prototyping (via Notebooks)&lt;/li&gt;
&lt;li&gt;Schema design and data modeling&lt;/li&gt;
&lt;li&gt;Team collaboration&lt;/li&gt;
&lt;li&gt;Sharing standardized queries for day-to-day data monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8i351571976x7kqf5nz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8i351571976x7kqf5nz.png" alt="Snowflake Workspaces" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Snowflake CoWork
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
Snowflake CoWork (formerly Snowflake Intelligence) is an &lt;strong&gt;AI-native analytics platform that lets you ask questions about your data in natural language&lt;/strong&gt;. Business users can perform data analysis directly without specialized SQL knowledge. Under the hood, &lt;strong&gt;Cortex Agents serve as the core AI orchestrator&lt;/strong&gt;, combining the following tools to fulfill requests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cortex Analyst&lt;/strong&gt;: Text2SQL analysis on structured data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cortex Search&lt;/strong&gt;: Hybrid search (vector search + keyword search + semantic reranking) on unstructured data (documents, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom Tools&lt;/strong&gt;: User-defined Stored Procedures and UDFs (User Defined Functions)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cortex Agents interpret user requests, select the appropriate tools, execute them, and generate responses - delivering an agentic analytics experience.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Natural language Q&amp;amp;A, automatic chart generation, insight surfacing, custom tool execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Business Users, Data Analysts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Status&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GA (2025/11)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Highlight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Semantic Models / Semantic Views for high-accuracy answers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No SQL required - analyze data with natural language&lt;/li&gt;
&lt;li&gt;Fully contained within Snowflake for security&lt;/li&gt;
&lt;li&gt;Easy to scale across the entire organization&lt;/li&gt;
&lt;li&gt;Semantic Models unify business terminology and data lineage&lt;/li&gt;
&lt;li&gt;Cross-analyze structured and unstructured data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons / Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires upfront preparation of Semantic Models / Semantic Views&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;KPI reporting for executives&lt;/li&gt;
&lt;li&gt;Self-service analytics for sales/marketing teams&lt;/li&gt;
&lt;li&gt;Instant answers to recurring business questions&lt;/li&gt;
&lt;li&gt;Analysis combining internal documents and data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7z24hdpdhr0n0mszet1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7z24hdpdhr0n0mszet1.png" alt="Snowflake CoWork" width="799" height="408"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Snowflake Notebooks
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
Snowflake Notebooks is a &lt;strong&gt;Jupyter-style notebook environment available within Snowsight&lt;/strong&gt;. It supports interactive analysis combining Python, SQL, and Markdown, and you can create Streamlit-powered visualizations directly within cells. GA since November 2024.&lt;/p&gt;

&lt;p&gt;Two runtime options are available:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Runtime&lt;/th&gt;
&lt;th&gt;Characteristics&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Warehouse Runtime&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Runs kernels on a warehouse. Fast startup, ideal for standard SQL analysis and Python processing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Container Runtime&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Runs on Snowpark Container Services (SPCS). GPU support and flexible package management via &lt;code&gt;pip&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Python/SQL execution, Streamlit visualizations, collaborative editing, Git integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Data Scientists, ML Engineers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Status&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GA (2024/11)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complete data science environment within Snowflake&lt;/li&gt;
&lt;li&gt;Python libraries (pandas, matplotlib, scikit-learn, etc.) available&lt;/li&gt;
&lt;li&gt;Create interactive Streamlit visualizations directly in cells&lt;/li&gt;
&lt;li&gt;CoCo AI assistance for natural language code generation and editing&lt;/li&gt;
&lt;li&gt;Easy documentation of analysis processes&lt;/li&gt;
&lt;li&gt;Built for team collaboration&lt;/li&gt;
&lt;li&gt;Snowpark ML integration for ML workflows&lt;/li&gt;
&lt;li&gt;Container Runtime enables deep learning and large-scale ML with GPU (PyTorch, TensorFlow pre-installed)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons / Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some feature differences compared to local Jupyter Notebooks&lt;/li&gt;
&lt;li&gt;Container Runtime requires External Access Integration setup for external packages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exploratory Data Analysis (EDA)&lt;/li&gt;
&lt;li&gt;ML model prototyping&lt;/li&gt;
&lt;li&gt;Deep learning model training and inference with GPU (Container Runtime)&lt;/li&gt;
&lt;li&gt;Creating and sharing analysis reports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs96cyeak55vl3ciziclv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs96cyeak55vl3ciziclv.png" alt="Snowflake Notebooks" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Snowflake Native UI (Apps)
&lt;/h2&gt;

&lt;p&gt;Tools for building and running business-user-facing applications, accessible from Snowsight. Typically, developers build the apps and business users consume them.&lt;/p&gt;
&lt;h3&gt;
  
  
  Streamlit in Snowflake (SiS)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
SiS is a &lt;strong&gt;service for developing and deploying web applications using Python&lt;/strong&gt;. You can rapidly build data apps without any frontend knowledge. Apps are created, edited, and run directly from Snowsight, with full integration into Snowflake's authentication and authorization.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Python web app development, Snowflake auth integration, Cortex AI integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Data Analysts, Data Scientists → Business Users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Status&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GA (AWS/Azure: 2024/1, GCP: 2024/5)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Highlight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Streamlit's simplicity + Snowflake's security&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;End-to-end app development using only Python&lt;/li&gt;
&lt;li&gt;Full integration with Snowflake authentication and authorization&lt;/li&gt;
&lt;li&gt;Rapidly build custom analytics tools for business users&lt;/li&gt;
&lt;li&gt;Easy to integrate AI capabilities (chat, summarization, classification, etc.) via Cortex AI&lt;/li&gt;
&lt;li&gt;CoCo AI-assisted coding in the Snowsight editor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons / Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limited flexibility for highly custom UI designs&lt;/li&gt;
&lt;li&gt;For cost optimization or flexible package management, consider Container Runtime below&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom analytics dashboards and visualization apps for teams&lt;/li&gt;
&lt;li&gt;Data entry and update applications&lt;/li&gt;
&lt;li&gt;AI/ML model demo apps&lt;/li&gt;
&lt;li&gt;Internal self-service analytics tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fskppba4u6kc5hvymc14o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fskppba4u6kc5hvymc14o.png" alt="Streamlit in Snowflake" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  SiS Container Runtime (GA)
&lt;/h4&gt;

&lt;p&gt;Traditional SiS uses Warehouse Runtime, but a &lt;strong&gt;Container Runtime&lt;/strong&gt; option is now also available (GA since March 2026). Container Runtime executes app code on SPCS while queries run on a separate warehouse.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The development experience is identical to standard SiS&lt;/strong&gt;. You write and deploy code in the same Snowsight SiS editor, and CoCo AI-assisted coding is fully available. You can create, edit, and run apps without worrying about the underlying runtime differences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Benefits of Container Runtime&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Separated App and Query Execution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;App code runs on a compute pool, queries on a warehouse. Optimize each resource independently&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lightweight Resource Options&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Run on compute pools cheaper than warehouses (e.g., &lt;code&gt;CPU_X64_XS&lt;/code&gt; at 0.06 credits/hour)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Shared Instance Efficiency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;All users share a single instance. Second user onward connects instantly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Full Cache Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;@st.cache_data&lt;/code&gt; caches are shared across users, reducing query execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flexible Package Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Install any package from PyPI, use the latest Streamlit version&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is especially impactful for always-on dashboards and lightweight visualization apps from a cost perspective. If you need &lt;strong&gt;a team dashboard that runs continuously within Snowflake&lt;/strong&gt;, SiS Container Runtime is a compelling choice - low cost and built entirely in Python.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For a deep dive into SiS Container Runtime, check out my previous article: &lt;a href="https://dev.to/tsubasa_tech/sis-container-runtime-run-streamlit-apps-at-a-fraction-of-the-cost-2mn8"&gt;SiS Container Runtime - Run Streamlit Apps at a Fraction of the Cost&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Snowflake App Runtime
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
Snowflake App Runtime is a new platform that lets you &lt;strong&gt;deploy full-stack web apps like Next.js directly inside Snowflake&lt;/strong&gt; (introduced at Snowflake Summit 2026 as Public Preview). While SiS is Python-centric, App Runtime lets you leverage the &lt;strong&gt;JavaScript / TypeScript (React / Next.js) ecosystem&lt;/strong&gt;. Apps run as a dedicated &lt;code&gt;APPLICATION SERVICE&lt;/code&gt; object on SPCS, inheriting Snowflake's SSO, RBAC, and governance. There's no Docker or infrastructure to set up, and authentication is automatic.&lt;/p&gt;

&lt;p&gt;Combined with CoCo's &lt;code&gt;snowflake-apps&lt;/code&gt; skill, you can go from &lt;strong&gt;prompt to scaffold, local preview, and deployment&lt;/strong&gt; in one continuous flow.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Build/deploy full-stack web apps, direct access to Snowflake data, automatic SSO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full-stack / Frontend Developers, internal app developers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Status&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Public Preview (Node.js / Next.js-centric; Python support planned)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Highlight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full web expressiveness — custom UI, multi-step business flows&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Highly customizable UI with React / Next.js&lt;/li&gt;
&lt;li&gt;Publish apps without moving data outside Snowflake (governance inherited)&lt;/li&gt;
&lt;li&gt;An authenticated URL is issued automatically — no need to build your own login layer&lt;/li&gt;
&lt;li&gt;End-to-end from a CoCo prompt to deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons / Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In Public Preview, so the spec may change (Trial accounts are not eligible)&lt;/li&gt;
&lt;li&gt;The supported stack is currently Node.js / Next.js-centric&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;SiS vs. App Runtime&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quickly visualize data in Python → &lt;strong&gt;SiS&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Build a rich web app with custom UI or business flows → &lt;strong&gt;App Runtime&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Internal business web apps (input forms, approval workflows, etc.)&lt;/li&gt;
&lt;li&gt;Custom-UI data visualization dashboards&lt;/li&gt;
&lt;li&gt;Per-user reference tools with row-level security applied&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0x7mpvjopeh7ze7u85qo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0x7mpvjopeh7ze7u85qo.png" alt=" " width="800" height="578"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I cover Snowflake App Runtime in depth in a dedicated article: &lt;a href="https://dev.to/tsubasa_tech/snowflake-app-runtime-deploy-full-stack-web-apps-right-next-to-your-data-from-a-single-prompt-1a29"&gt;Snowflake App Runtime - Deploy Full-Stack Web Apps Right Next to Your Data from a Single Prompt&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Snowflake Native Apps
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
Snowflake Native Apps is a &lt;strong&gt;framework for developing and distributing packaged applications on Snowflake&lt;/strong&gt;. Multiple distribution methods are available: public distribution via Snowflake Marketplace, direct distribution to specific accounts via Private Listing, and distribution to non-Snowflake customers via Reader Accounts. Apps can use SiS for the UI or build custom frontends with SPCS.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;App packaging, Marketplace / Private Listing / Reader Account distribution, version management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;App Developers, ISVs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Status&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GA (2024/1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Highlight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Combine data sharing and apps for distribution&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Distribute apps and data as a package&lt;/li&gt;
&lt;li&gt;Consumers use apps + data without copying data&lt;/li&gt;
&lt;li&gt;Continuous update delivery&lt;/li&gt;
&lt;li&gt;Monetization via Marketplace&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons / Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Relatively steep learning curve&lt;/li&gt;
&lt;li&gt;Primarily for ISVs and data providers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Commercial application distribution&lt;/li&gt;
&lt;li&gt;Data Product offerings&lt;/li&gt;
&lt;li&gt;Cross-organization solution sharing&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Snowpark Container Services (SPCS)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
SPCS is a &lt;strong&gt;fully managed service for running containerized applications on Snowflake&lt;/strong&gt;. The core value proposition is &lt;strong&gt;"bringing compute to the data, rather than moving data to the compute."&lt;/strong&gt; Deploy Docker images and run ML inference or custom applications with GPU/CPU resources - all within Snowflake. Available on AWS, Azure, and GCP.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Container execution, GPU support, ML model serving, batch jobs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ML Engineers, App Developers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Status&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GA (AWS: 2024/8, Azure: 2025/2, GCP: 2025/8)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Highlight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Any programming language or framework&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data never leaves Snowflake&lt;/strong&gt;: Meets security and compliance requirements&lt;/li&gt;
&lt;li&gt;Any programming language or library (Docker-compatible)&lt;/li&gt;
&lt;li&gt;GPU support for ML model inference and private LLM execution&lt;/li&gt;
&lt;li&gt;No Kubernetes knowledge required for container operations&lt;/li&gt;
&lt;li&gt;Inherits Snowflake's security, governance, and access controls&lt;/li&gt;
&lt;li&gt;Can serve as the backend for Native Apps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons / Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires containerization knowledge&lt;/li&gt;
&lt;li&gt;More setup effort compared to SiS&lt;/li&gt;
&lt;li&gt;External internet access disabled by default (requires External Access Integration)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to choose SiS vs. SPCS&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple dashboards and visualization apps → &lt;strong&gt;SiS&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Custom apps, ML inference, batch processing, non-Python languages → &lt;strong&gt;SPCS&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ML model inference endpoints (including private LLM execution)&lt;/li&gt;
&lt;li&gt;Batch data processing with sensitive data&lt;/li&gt;
&lt;li&gt;Applications requiring custom runtimes&lt;/li&gt;
&lt;li&gt;Migrating existing Docker apps to Snowflake&lt;/li&gt;
&lt;li&gt;Native Apps backend&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  AI-Assisted Development
&lt;/h2&gt;

&lt;p&gt;Tools that leverage AI to accelerate data and app development.&lt;/p&gt;
&lt;h3&gt;
  
  
  CoCo
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
CoCo, released in February 2026 as the successor to Snowflake Copilot, is a &lt;strong&gt;Snowflake-native AI coding agent&lt;/strong&gt;. It significantly expands and evolves Copilot's capabilities, so if you've been using Copilot, CoCo is your upgrade path.&lt;/p&gt;

&lt;p&gt;It enables complex tasks in data engineering, analytics, machine learning, and agent development through natural language. What sets it apart is its deep understanding of Snowflake's data, compute, governance, and operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Available in multiple forms&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Form&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CoCo in Snowsight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AI coding assistance within Snowsight&lt;/td&gt;
&lt;td&gt;GA (2026/3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CoCo CLI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use from your local terminal, VS Code, Cursor, and other editors&lt;/td&gt;
&lt;td&gt;GA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CoCo Desktop&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native IDE app for Mac / Windows, integrating editor, terminal, agent, browser, and notebooks&lt;/td&gt;
&lt;td&gt;Public Preview&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code generation with awareness of your Snowflake data context&lt;/li&gt;
&lt;li&gt;Accelerates data pipeline, analytics, and AI app development&lt;/li&gt;
&lt;li&gt;Enterprise-grade security and governance&lt;/li&gt;
&lt;li&gt;Integrates into existing development workflows (local IDE)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons / Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is a developer-oriented tool - generated code should be reviewed by technical users before use&lt;/li&gt;
&lt;li&gt;CoCo CLI requires environment setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SQL query authoring and optimization&lt;/li&gt;
&lt;li&gt;Data pipeline construction&lt;/li&gt;
&lt;li&gt;Cortex Agents development and tuning&lt;/li&gt;
&lt;li&gt;Day-to-day data development task acceleration&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;
  
  
  CoCo Desktop (Public Preview)
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;CoCo Desktop&lt;/strong&gt; delivers CoCo's capabilities as a dedicated, IDE-like app (Mac / Windows, Public Preview). It includes a file editor, integrated terminal, agentic execution loop, agentic browser, and notebooks, assisting development with deep Snowflake awareness. A standout feature is that you can &lt;strong&gt;create Streamlit / Snowflake App Runtime apps from a prompt in the App Gallery, preview them locally, and deploy them directly&lt;/strong&gt; - making it a natural entry point to the various app-development paths covered in this article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy284m3ubobcfobexuchh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy284m3ubobcfobexuchh.png" alt="CoCo" width="800" height="816"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Vercel v0 Integration
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The Vercel v0 integration is a &lt;strong&gt;partner integration&lt;/strong&gt; announced in November 2025. For a &lt;strong&gt;Snowflake-native&lt;/strong&gt; way to build and deploy React / Next.js apps, &lt;strong&gt;Snowflake App Runtime&lt;/strong&gt; has since become available (see Snowflake App Runtime above) - consider App Runtime first when building full-stack web apps inside Snowflake. The integration is still rolling out; the information below is based on the announcement and specifications may change.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
The &lt;strong&gt;Vercel v0 integration&lt;/strong&gt;, announced in November 2025, will enable generating and deploying Next.js applications powered by Snowflake data using natural language. v0 is Vercel's AI assistant for full-stack application development. Generated apps are deployed on SPCS. Unlike the Snowflake-native App Runtime, this is positioned as &lt;strong&gt;an option used in combination with the Vercel platform&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Natural language data querying, app generation, deployment to Snowflake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Developers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Status&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Under Development (Coming Soon)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;SiS vs. Vercel v0 Integration&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Streamlit in Snowflake (SiS)&lt;/th&gt;
&lt;th&gt;Vercel v0 Integration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Language&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;TypeScript / JavaScript (Next.js)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Target Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Data Analysts, Data Scientists&lt;/td&gt;
&lt;td&gt;Frontend / Full-stack Developers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;App Nature&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dynamic web apps from data analysis (Python-first)&lt;/td&gt;
&lt;td&gt;Production-grade native web apps from the start&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;UI Flexibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Streamlit components&lt;/td&gt;
&lt;td&gt;React-based, highly customizable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deploy Target&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Snowflake (Warehouse / Container Runtime)&lt;/td&gt;
&lt;td&gt;SPCS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;SiS is ideal for data analysts and scientists who want to quickly turn their analyses into interactive apps using Python. Vercel v0 integration is for frontend developers who want to build production-quality native web apps from the start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Capabilities&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ask questions about data&lt;/strong&gt;: Query schemas, table structures, and data content in natural language&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate applications&lt;/strong&gt;: Create Next.js apps for data visualization, dashboards, internal tools, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy to Snowflake&lt;/strong&gt;: Deploy generated apps on SPCS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Architecture&lt;/strong&gt;:&lt;br&gt;
Vercel's "Secure Vibe Coding Architecture" ensures application and auth layers are managed by Vercel while compute and data stay within Snowflake. Data never leaves Snowflake, and existing security policies and access controls apply.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sales pipeline dashboards&lt;/li&gt;
&lt;li&gt;Inventory monitoring tools&lt;/li&gt;
&lt;li&gt;Customer analytics applications&lt;/li&gt;
&lt;li&gt;Financial reporting interfaces&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Official blog: &lt;a href="https://vercel.com/blog/build-and-deploy-data-applications-on-snowflake-with-v0" rel="noopener noreferrer"&gt;Build and deploy data applications on Snowflake with v0&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  AI Agent / MCP Integration
&lt;/h2&gt;

&lt;p&gt;Interfaces for accessing Snowflake data and capabilities from AI Agents.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Who should consider MCP?&lt;/strong&gt; If you're already using AI Agents like Claude Desktop, Cursor, or GitHub Copilot and want to &lt;strong&gt;add Snowflake to your AI ecosystem&lt;/strong&gt;, this is for you. MCP (Model Context Protocol) - often called the "USB-C for AI" - provides unified access to Snowflake data from multiple AI tools with a single configuration.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Key Value of MCP Integration&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reduced Integration Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No need for individual connectors per AI tool - unified access via MCP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Less Context Switching&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Access Snowflake data directly within your AI assistant without interrupting workflow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Existing Governance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Leverage Snowflake's RBAC and security model as-is&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Future Investment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;MCP is becoming the de facto standard for agent communication&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Snowflake Managed MCP Server
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
Snowflake Managed MCP Server is an &lt;strong&gt;MCP server hosted and managed by Snowflake&lt;/strong&gt;. Configure it from Snowsight and connect MCP Clients like Claude Desktop or Cursor to Snowflake capabilities. GA since November 2025.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cortex Search / Analyst / Agents connectivity, SQL execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Developers, AI Agent Users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Status&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GA (2025/11)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy setup (configure from Snowsight, ~15-25 minutes)&lt;/li&gt;
&lt;li&gt;Operates within Snowflake's security model&lt;/li&gt;
&lt;li&gt;Seamless integration with Cortex features (Analyst / Search / Agents)&lt;/li&gt;
&lt;li&gt;Officially supported, no infrastructure management required&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons / Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires separate MCP Client setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access Snowflake data from Claude Desktop / Cursor and other MCP Clients&lt;/li&gt;
&lt;li&gt;Automated data analysis via AI Agents&lt;/li&gt;
&lt;li&gt;RAG application backends&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  OSS Snowflake MCP Server
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
An &lt;strong&gt;open-source MCP Server&lt;/strong&gt; published by Snowflake Labs on &lt;a href="https://github.com/Snowflake-Labs/mcp" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. Runs locally and connects with MCP Clients.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cortex Search / Analyst / Agents, SQL execution, object management, Semantic View queries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Developers, AI Agent Users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Highlight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fine-grained permission control, local execution, early access to new features&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fine-grained SQL execution permissions (e.g., allow SELECT only)&lt;/li&gt;
&lt;li&gt;Flexible customization in local environments&lt;/li&gt;
&lt;li&gt;Early access to the latest features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons / Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires local setup and management&lt;/li&gt;
&lt;li&gt;Community support (not officially supported)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Snowflake data analysis in development environments&lt;/li&gt;
&lt;li&gt;Ad-hoc analysis from IDEs like Cursor&lt;/li&gt;
&lt;li&gt;AI Agent integration PoCs&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;For a deep dive into using the Snowflake MCP Server with Cursor, check out my previous article: &lt;a href="https://dev.to/tsubasa_tech/unlock-advanced-data-analytics-in-cursor-with-snowflake-mcp-server-2flb"&gt;Unlock Advanced Data Analytics in Cursor with Snowflake MCP Server&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Programmatic Access
&lt;/h2&gt;

&lt;p&gt;Tools for connecting to Snowflake via command line or code for development and operations.&lt;/p&gt;
&lt;h3&gt;
  
  
  Snowflake CLI
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
Snowflake CLI is &lt;strong&gt;Snowflake's official open-source command-line interface&lt;/strong&gt;. Positioned as the successor to SnowSQL, it includes SnowSQL's capabilities plus integrated development and deployment features for Snowpark apps, Streamlit apps, Native Apps, and more. Snowflake recommends migrating from SnowSQL to Snowflake CLI.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SQL execution, Snowpark / Streamlit / Native Apps deployment, Git integration, automation scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Developers, DevOps Engineers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Highlight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Open source, modern development workflow support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CI/CD pipeline integration&lt;/li&gt;
&lt;li&gt;Deploy Snowpark, Streamlit, and Native Apps from the command line&lt;/li&gt;
&lt;li&gt;Open source with community-driven extensions&lt;/li&gt;
&lt;li&gt;Usable from SSH-connected servers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons / Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No GUI - not ideal for visual data exploration&lt;/li&gt;
&lt;li&gt;Some command syntax differences when migrating from SnowSQL&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're currently using SnowSQL, refer to the &lt;a href="https://docs.snowflake.com/en/user-guide/snowsql-migrate" rel="noopener noreferrer"&gt;official migration guide&lt;/a&gt; to plan your transition to Snowflake CLI.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Snowpark Python SDK
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
A Python SDK for natively interacting with Snowflake. Provides intuitive data manipulation through the DataFrame API.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DataFrame API, UDF/UDTF/UDAF creation, ML integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Data Engineers, Data Scientists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Highlight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Write in Python, execute server-side (pushdown)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pandas-like interface&lt;/li&gt;
&lt;li&gt;Performance gains through Snowflake-side pushdown execution&lt;/li&gt;
&lt;li&gt;Snowpark ML integration for machine learning workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons / Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some advanced SQL features require direct SQL&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  SQL API and Connectors
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
Snowflake provides a REST API and drivers/connectors for various programming languages, enabling applications to connect to Snowflake for data operations.&lt;/p&gt;
&lt;h4&gt;
  
  
  SQL REST API
&lt;/h4&gt;

&lt;p&gt;The Snowflake SQL REST API (&lt;code&gt;/api/v2/statements&lt;/code&gt;) enables SQL execution via HTTP requests.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST /api/v2/statements&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Execute SQL statements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GET /api/v2/statements/&amp;lt;handle&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Check execution status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;POST /api/v2/statements/&amp;lt;handle&amp;gt;/cancel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cancel execution&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Authentication supports OAuth and JWT (key-pair authentication).&lt;/p&gt;
&lt;h4&gt;
  
  
  Drivers / Connectors
&lt;/h4&gt;

&lt;p&gt;A comprehensive set of drivers and connectors for various programming languages:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Drivers / Connectors&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Database Drivers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;JDBC, ODBC, Go, .NET, Node.js, PHP PDO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Python Ecosystem&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Snowflake Connector for Python, Snowpark, Snowpark ML, SQLAlchemy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Snowflake Connector for Kafka, Snowflake Connector for Spark&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SQL execution, data operations, multi-language support, system integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Developers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Highlight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Broad language support: Java, Python, Node.js, Go, .NET, ODBC, JDBC, and more&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;REST API vs. Connectors&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;SQL REST API&lt;/th&gt;
&lt;th&gt;Drivers / Connectors&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Access Method&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;HTTP requests&lt;/td&gt;
&lt;td&gt;Library-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lightweight integrations, async processing, serverless environments&lt;/td&gt;
&lt;td&gt;High-volume data processing, complex workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Session Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Stateless&lt;/td&gt;
&lt;td&gt;Auto-managed by connector&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy integration into existing applications&lt;/li&gt;
&lt;li&gt;Fits microservice architectures well&lt;/li&gt;
&lt;li&gt;Broad programming language support&lt;/li&gt;
&lt;li&gt;REST API works in serverless environments (AWS Lambda, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons / Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;REST API is best for lightweight operations; connectors recommended for high-volume data processing&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Third-Party Integration
&lt;/h2&gt;

&lt;p&gt;Methods for connecting to Snowflake from external tools and applications.&lt;/p&gt;
&lt;h3&gt;
  
  
  BI Tools
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
Connect to Snowflake from existing BI tools like Tableau, Power BI, Looker, Sigma, ThoughtSpot, and others for visualization.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Representative Tools&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tableau, Power BI, Looker, Sigma, ThoughtSpot, Metabase, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Data Analysts, Business Users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Highlight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rich visualizations, leverage existing skills&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extensive visualization capabilities&lt;/li&gt;
&lt;li&gt;Leverage existing BI skills and expertise&lt;/li&gt;
&lt;li&gt;Integrate with tools already in your organization&lt;/li&gt;
&lt;li&gt;Enterprise-grade features (scheduling, permissions, distribution, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons / Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Additional BI tool licensing costs&lt;/li&gt;
&lt;li&gt;Data freshness concerns with extract mode&lt;/li&gt;
&lt;li&gt;Some tools may lag in supporting latest Snowflake features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Executive dashboards&lt;/li&gt;
&lt;li&gt;Scheduled report distribution&lt;/li&gt;
&lt;li&gt;Complex visualizations&lt;/li&gt;
&lt;li&gt;Large-scale BI deployments&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Custom Applications
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;br&gt;
Build custom applications using Snowflake Connectors or SQL API.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tech Stack&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;React, Vue.js, Flask, Django, or any framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Developers → Business Users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Highlight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Complete customization control&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full control over UI/UX&lt;/li&gt;
&lt;li&gt;Deep integration with existing systems&lt;/li&gt;
&lt;li&gt;Custom business logic implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons / Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security design is your responsibility&lt;/li&gt;
&lt;li&gt;Authentication and authorization must be implemented&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Use Case-Based Selection Guide
&lt;/h2&gt;

&lt;p&gt;For those asking &lt;em&gt;"So which one should I actually use?"&lt;/em&gt; - here's a practical selection guide.&lt;/p&gt;
&lt;h3&gt;
  
  
  Recommended Tools by User Type
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;User Type&lt;/th&gt;
&lt;th&gt;Recommended Tool&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Business User&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Snowflake CoWork&lt;/td&gt;
&lt;td&gt;No SQL required - analyze with natural language. Cortex Agents combine tools to answer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Analyst&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Workspaces&lt;/td&gt;
&lt;td&gt;Flexible analysis with SQL / Python&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Scientist&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Snowflake Notebooks&lt;/td&gt;
&lt;td&gt;Interactive analysis with Python + SQL + Streamlit. GPU via Container Runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Engineer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Workspaces + Snowflake CLI&lt;/td&gt;
&lt;td&gt;SQL / Notebooks / dbt development, CI/CD integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;App Developer (Python)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SiS&lt;/td&gt;
&lt;td&gt;Rapid app development in Python. Container Runtime for cost optimization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;App Developer (Custom)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SPCS&lt;/td&gt;
&lt;td&gt;Any language/framework, GPU, data stays in Snowflake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AI Agent User&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Snowflake Managed MCP Server&lt;/td&gt;
&lt;td&gt;Connect existing AI Agents (Claude Desktop, Cursor, etc.) to Snowflake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Full-Stack Developer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Snowflake App Runtime&lt;/td&gt;
&lt;td&gt;Deploy React / Next.js full-stack web apps inside Snowflake. Can be created from a CoCo prompt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Full-Stack Developer (Vercel)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Vercel v0 Integration&lt;/td&gt;
&lt;td&gt;Generate Next.js apps in combination with the Vercel platform&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Recommended Tools by Use Case
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Recommended Tool&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ad-hoc SQL / Python analysis&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Workspaces&lt;/td&gt;
&lt;td&gt;Notebooks also available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Natural language analytics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CoWork&lt;/td&gt;
&lt;td&gt;Cortex Agents + Analyst / Search / Custom Tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Exploratory Data Analysis (EDA)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Notebooks (Warehouse Runtime)&lt;/td&gt;
&lt;td&gt;Python + SQL + Streamlit visualizations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deep learning / Large-scale ML&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Notebooks (Container Runtime)&lt;/td&gt;
&lt;td&gt;GPU available, PyTorch / TensorFlow pre-installed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Team dashboards / KPI monitoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SiS (Container Runtime)&lt;/td&gt;
&lt;td&gt;Low-cost always-on, shared caching, Python-only development&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custom app development&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SiS (Warehouse Runtime)&lt;/td&gt;
&lt;td&gt;Rapid development, Snowflake auth integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custom web app development (React / Next.js)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Snowflake App Runtime&lt;/td&gt;
&lt;td&gt;Deploy web apps with custom UI / business flows inside Snowflake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ML model inference / LLM execution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SPCS&lt;/td&gt;
&lt;td&gt;GPU support, data stays in Snowflake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;App distribution / monetization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native Apps&lt;/td&gt;
&lt;td&gt;Marketplace / Private Listing / Reader Account distribution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AI Agent integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Snowflake Managed MCP Server&lt;/td&gt;
&lt;td&gt;Easy setup, officially supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AI Agent integration (custom)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;OSS Snowflake MCP Server&lt;/td&gt;
&lt;td&gt;Fine-grained permissions, local execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Advanced visualizations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;BI Tools (Tableau, Power BI, etc.)&lt;/td&gt;
&lt;td&gt;Proven enterprise features&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;dbt project development&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Workspaces&lt;/td&gt;
&lt;td&gt;dbt Projects on Snowflake integration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CI/CD / automation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Snowflake CLI&lt;/td&gt;
&lt;td&gt;Automate Snowpark / SiS / Native Apps deployment&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;CoCo AI Assistance&lt;/strong&gt;: Workspaces, Notebooks, and SiS all support CoCo for AI-assisted coding. Generate and edit code with natural language to dramatically boost development productivity. For local IDEs (VS Code, Cursor, etc.), CoCo CLI is also available.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Key Decision Factors
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;SQL / Python skills&lt;/strong&gt;: Proficient → Workspaces / Notebooks. Not proficient → CoWork&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Need dashboards / visualizations?&lt;/strong&gt; Simple ones → SiS (Container Runtime) at low cost. Advanced → BI tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customization needs&lt;/strong&gt;: High → SiS / SPCS / custom development&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GPU required?&lt;/strong&gt; → Notebooks (Container Runtime) or SPCS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can data leave Snowflake?&lt;/strong&gt; No → Snowflake native UI (SiS / SPCS / Notebooks)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Existing tools&lt;/strong&gt;: Already have BI tools → connect them to Snowflake. Already using AI Agents → connect via MCP Server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale of deployment&lt;/strong&gt;: Organization-wide → CoWork. Team-level → CoWork / SiS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI strategy&lt;/strong&gt;: Heavy AI Agent use → MCP Server. Development assistance → CoCo. App generation → App Runtime (or Vercel v0 in combination with Vercel)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Snowflake's data UI has diversified remarkably in just two years. While the abundance of options can feel overwhelming, it also means &lt;strong&gt;you can now choose the tool that's truly optimal for your organization and use case&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Personally, I find the most value in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Snowflake CoWork for data democratization&lt;/strong&gt;: Business users who can't write SQL can now query data directly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snowflake Managed MCP Server for AI Agent integration&lt;/strong&gt;: Analyze data without leaving your development tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SiS simplicity with Container Runtime&lt;/strong&gt;: Build custom dashboards and analytics tools in Python alone, with Container Runtime enabling low-cost always-on operation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CoCo / Vercel v0 integration potential&lt;/strong&gt;: AI-assisted development dramatically accelerating data and app development&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The analytics experience is evolving from static reports to &lt;strong&gt;interactive conversations with data, gaining insights alongside AI&lt;/strong&gt;. I hope this guide helps you find the right tools to accelerate your data journey!&lt;/p&gt;
&lt;h2&gt;
  
  
  Promotion
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Snowflake What's New Updates on X
&lt;/h3&gt;

&lt;p&gt;I share Snowflake What's New updates on X. Follow for the latest insights:&lt;/p&gt;
&lt;h4&gt;
  
  
  English Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_en" rel="noopener noreferrer"&gt;Snowflake What's New Bot (English Version)&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Japanese Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_jp" rel="noopener noreferrer"&gt;Snowflake's What's New Bot (Japanese Version)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Change Log
&lt;/h2&gt;

&lt;p&gt;(20260606) Major update following Snowflake Summit 2026: added Snowflake App Runtime and CoCo Desktop, reflected the Cortex Code → CoCo and Snowflake Intelligence → Snowflake CoWork renames, updated statuses (CoCo in Snowsight GA, SiS Container Runtime GA), and refreshed the Vercel v0 section&lt;br&gt;
(20260205) Initial post&lt;/p&gt;
&lt;h2&gt;
  
  
  Original Japanese Article
&lt;/h2&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://zenn.dev/snowflakejp/articles/be0c2053116787" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Fupload%2Fs--pwmg4BX---%2Fc_fit%252Cg_north_west%252Cl_text%3Anotosansjp-medium.otf_55%3ASnowflake%252520%2525E3%252583%252587%2525E3%252583%2525BC%2525E3%252582%2525BF%2525E6%2525B4%2525BB%2525E7%252594%2525A8%252520UI%252520%2525E3%252582%2525AC%2525E3%252582%2525A4%2525E3%252583%252589%252520-%252520%2525E6%25259C%252580%2525E9%252581%2525A9%2525E3%252581%2525AA%2525E3%252583%252584%2525E3%252583%2525BC%2525E3%252583%2525AB%2525E9%252581%2525B8%2525E6%25258A%25259E%2525E3%252581%2525A7%2525E5%252588%252586%2525E6%25259E%252590%2525E4%2525BD%252593%2525E9%2525A8%252593%2525E3%252582%252592%2525E5%252590%252591%2525E4%2525B8%25258A%2525E3%252581%252595%2525E3%252581%25259B%2525E3%252582%25258B%252Cw_1010%252Cx_90%252Cy_100%2Fg_south_west%252Cl_text%3Anotosansjp-medium.otf_34%3Atsubasa%252Cx_220%252Cy_108%2Fbo_3px_solid_rgb%3Ad6e3ed%252Cg_south_west%252Ch_90%252Cl_fetch%3AaHR0cHM6Ly9zdGF0aWMuemVubi5zdHVkaW8vdXNlci11cGxvYWQvYXZhdGFyLzQ0ZmE2OGQyM2YuanBlZw%3D%3D%252Cr_20%252Cw_90%252Cx_92%252Cy_102%2Fco_rgb%3A6e7b85%252Cg_south_west%252Cl_text%3Anotosansjp-medium.otf_30%3ASnowflake%252520Japan%252Cx_220%252Cy_160%2Fbo_4px_solid_white%252Cg_south_west%252Ch_50%252Cl_fetch%3AaHR0cHM6Ly9zdGF0aWMuemVubi5zdHVkaW8vdXNlci11cGxvYWQvYXZhdGFyL2RkODMzYmYwZDcuanBlZw%3D%3D%252Cr_max%252Cw_50%252Cx_139%252Cy_84%2Fv1627283836%2Fdefault%2Fog-base-w1200-v2.png%3F_a%3DBACMTiAE" height="630" class="m-0" width="1200"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://zenn.dev/snowflakejp/articles/be0c2053116787" rel="noopener noreferrer" class="c-link"&gt;
            Snowflake データ活用 UI ガイド - 最適なツール選択で分析体験を向上させる
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstatic.zenn.studio%2Fimages%2Flogo-transparent.png" width="315" height="315"&gt;
          zenn.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>snowflake</category>
      <category>ai</category>
      <category>sql</category>
      <category>python</category>
    </item>
    <item>
      <title>Revolutionize Your Search with Snowflake Cortex Search Multi-Index and Index-Specific Boosts</title>
      <dc:creator>Tsubasa Kanno</dc:creator>
      <pubDate>Mon, 12 Jan 2026 03:52:54 +0000</pubDate>
      <link>https://dev.to/tsubasa_tech/revolutionize-your-search-with-snowflake-cortex-search-multi-index-and-index-specific-boosts-4ogn</link>
      <guid>https://dev.to/tsubasa_tech/revolutionize-your-search-with-snowflake-cortex-search-multi-index-and-index-specific-boosts-4ogn</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Snowflake's Cortex Search just received a major upgrade with &lt;strong&gt;Multi-Index&lt;/strong&gt; and &lt;strong&gt;Index-Specific Boosts&lt;/strong&gt;! These powerful features dramatically enhance search flexibility and precision, enabling scenarios like "exact match on product codes while semantic search on descriptions."&lt;/p&gt;

&lt;p&gt;In this article, I'll walk you through these new features using hands-on examples with dummy data in Snowsight, demonstrating their value and practical implementation.&lt;/p&gt;

&lt;p&gt;For a comprehensive overview of Cortex Search fundamentals, check out the &lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-search/cortex-search-overview" rel="noopener noreferrer"&gt;official Snowflake documentation&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note (2026/1/12)&lt;/strong&gt;: Cortex Search Multi-Index is currently in Public Preview. Features may be significantly updated in the future.&lt;/p&gt;

&lt;p&gt;Note: A &lt;strong&gt;Custom Embedding (BYO Embed: Bring Your Own Embedding)&lt;/strong&gt; feature was also released alongside these features, but is not covered in this article.&lt;/p&gt;

&lt;p&gt;Note: This article represents my personal views and not those of Snowflake.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Cortex Search Quick Recap
&lt;/h2&gt;

&lt;p&gt;Let me briefly explain what &lt;strong&gt;Cortex Search&lt;/strong&gt; is. Cortex Search is a &lt;strong&gt;fully-managed enterprise search service&lt;/strong&gt; provided by Snowflake.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid Search&lt;/strong&gt;: Combines vector search (semantic similarity) with keyword search (lexical similarity) for high-precision results&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Embedding Generation&lt;/strong&gt;: Automatically and regularly vectorizes text data to enable semantic search capabilities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fully Managed&lt;/strong&gt;: No infrastructure management or tuning required - ready to use immediately&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snowflake Native&lt;/strong&gt;: Complete integration with Snowflake's data governance and security features&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is Multi-Index?
&lt;/h2&gt;

&lt;p&gt;Multi-Index enables you to &lt;strong&gt;create separate indexes for multiple columns with different characteristics, and combine them during search&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Previously, Cortex Search was primarily designed for searching a single column. However, real-world business scenarios often require searching across multiple fields like "product code," "product name," and "product description." With Multi-Index, you can integrate these into a single search service and apply the most appropriate search method for each field's characteristics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Index Use Cases
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cross-field Search&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Search across product codes, names, and descriptions with different characteristics simultaneously&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Field-specific Search Logic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Apply strict keyword matching to product codes while using semantic search for descriptions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Precise Result Control&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Adjust the importance of each field to achieve optimal search results for your business requirements&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What are Index-Specific Boosts?
&lt;/h2&gt;

&lt;p&gt;Index-Specific Boosts enable you to &lt;strong&gt;adjust the weights of individual columns within the same index type in Multi-Index searches&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, if you have &lt;code&gt;product_code&lt;/code&gt; and &lt;code&gt;product_name&lt;/code&gt; as TEXT INDEXes, even when searching with the same keyword, the optimal results differ depending on whether you want to prioritize "matches in product code" or "matches in product name." Index-Specific Boosts let you flexibly control this balance per search query.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;weights&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Search type weighting&lt;/td&gt;
&lt;td&gt;Adjusts the overall balance between keyword search (texts), vector search (vectors), and reranker scores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;text_boosts&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;TEXT INDEX weighting&lt;/td&gt;
&lt;td&gt;Adjusts individual column weights within TEXT INDEXes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;vector_boosts&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;VECTOR INDEX weighting&lt;/td&gt;
&lt;td&gt;Adjusts individual column weights within VECTOR INDEXes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Official documentation: &lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-search/cortex-search-customize-scoring#index-specific-boosts" rel="noopener noreferrer"&gt;Customizing Cortex Search scoring - Index-specific boosts&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Business Value and Benefits
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Transforming Search Experience
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Previous Limitation&lt;/th&gt;
&lt;th&gt;Multi-Index &amp;amp; Index-Specific Boosts Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Limited to single-field search&lt;/td&gt;
&lt;td&gt;Cross-field integrated search now possible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same search logic applied to all fields&lt;/td&gt;
&lt;td&gt;Apply optimal search methods (keyword/semantic) per field&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Difficult to customize search results&lt;/td&gt;
&lt;td&gt;Flexible ranking adjustments with Index-Specific Boosts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hybrid search balance was automatic&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Customize each field's contribution per search query&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Expected Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;E-commerce Product Search&lt;/strong&gt; — Prioritize exact matches on SKUs and product codes while supporting semantic search on product descriptions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internal Knowledge Search&lt;/strong&gt; — Balance strict matching on document titles with semantic search on document bodies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer Support&lt;/strong&gt; — Apply different weights to FAQ titles and bodies to deliver results that better match user intent&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cortex Search Integration Scenarios
&lt;/h3&gt;

&lt;p&gt;Cortex Search maximizes its value when combined with various Snowflake features beyond standalone use.&lt;/p&gt;

&lt;h4&gt;
  
  
  AI Agent Context
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Snowflake Managed MCP Server&lt;/strong&gt; — When AI Agents access data within Snowflake, they can search and retrieve enterprise-specific domain knowledge through Cortex Search. Multi-Index enables flexible searching across both structured and unstructured data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snowflake Intelligence&lt;/strong&gt; — Cortex Search serves as the foundation for searching relevant documents and knowledge to generate more accurate responses to natural language queries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Data App Context
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Streamlit in Snowflake&lt;/strong&gt; — Easily build user-friendly search interfaces by calling Cortex Search within Streamlit apps. With Index-Specific Boosts, you can dynamically control search weighting from the application layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Biggest Value I See
&lt;/h3&gt;

&lt;p&gt;Personally, I find tremendous value in &lt;strong&gt;"being able to flexibly control the balance between exact match and fuzzy search for multiple fields per search query."&lt;/strong&gt; Previously, you could only search with a uniform balance across the entire search service, but by combining Multi-Index with Index-Specific Boosts, you can now dynamically change search behavior based on user intent and business requirements.&lt;/p&gt;

&lt;p&gt;Furthermore, I believe enterprise search will serve as a &lt;strong&gt;core component for complementing enterprise-specific domain knowledge in RAG and AI Agent applications&lt;/strong&gt;. In other words, improvements in search flexibility and precision directly translate to improvements in RAG response quality and AI Agent decision accuracy. In this sense, Multi-Index and Index-Specific Boosts represent a significant update that contributes to elevating enterprise AI adoption overall, not just a mere search feature improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important Considerations
&lt;/h2&gt;

&lt;p&gt;Please keep the following points in mind when using Multi-Index:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Consideration&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Creating and maintaining multiple indexes may increase compute and storage costs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Search performance may be affected by the number and configuration of indexes, so proper design is important&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Query results under 1 million rows are recommended for optimal performance (contact Snowflake if exceeding 1 million rows)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Official documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-search/cortex-search-overview#label-cortex-multi-index-search" rel="noopener noreferrer"&gt;Cortex Search Multi-index Search&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-search/query-cortex-search-service#multi-index-queries" rel="noopener noreferrer"&gt;Query Multi-index Cortex Search Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-search/cortex-search-customize-scoring#label-cortex-search-index-boosts" rel="noopener noreferrer"&gt;Index-specific Boosts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Hands-on Tutorial
&lt;/h2&gt;

&lt;p&gt;Let's try out Multi-Index and Index-Specific Boosts! We'll use dummy product catalog data to create a Cortex Search service in Snowsight and verify the behavior with SQL queries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Demo Scenario
&lt;/h3&gt;

&lt;p&gt;For this demo, we'll simulate an e-commerce product search scenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;product_code&lt;/strong&gt;: Product code (exact match is critical, like SKUs)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;product_name&lt;/strong&gt;: Product name (balance between exact match and keyword matching)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;description&lt;/strong&gt;: Product description (semantic fuzzy search is effective)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll create a Multi-Index on these three fields and experience how search results change when we adjust each field's importance based on the search context.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Prepare Demo Data
&lt;/h3&gt;

&lt;p&gt;First, let's create a table and insert sample data in Snowsight's SQL Worksheets. Run the following query (feel free to use your own data if available):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Create demo database and schema&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;cortex_search_demo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;cortex_search_demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;multi_index_demo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;USE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;cortex_search_demo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;USE&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;multi_index_demo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Create warehouse (you can use your existing warehouse)&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;WAREHOUSE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;cortex_search_wh&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt;
   &lt;span class="n"&gt;WAREHOUSE_SIZE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'X-SMALL'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Create product catalog table&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;product_catalog&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;product_id&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;product_code&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;product_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Insert sample data (fictional products)&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;product_catalog&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'CBP-16-X9-PRO'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'CloudBook Pro 16 X9'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'The latest 16-inch professional laptop featuring the X9 processor. Known for high-performance graphics processing and extended battery life. Ideal for video editing and CAD work.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Laptop'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3988&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'CBP-14-X7'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'CloudBook Pro 14 X7'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Compact 14-inch model with X7 processor. Lightweight 1.2kg design perfect for mobile workers.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Laptop'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2488&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'CBA-15-X5'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'CloudBook Air 15 X5'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Amazingly thin and light 15-inch large-screen laptop. Handles everything from daily use to creative work.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Laptop'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1988&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'PPD-13-Z4'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'PixelPad Pro 13 Z4'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Top-tier tablet with Z4 chip. Perfect for illustration and design work when paired with a stylus pen.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Tablet'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2188&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'ODK-24-X9'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'OmniDesk 24 X9'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Beautiful all-in-one desktop with 4.5K display. Ideal for home and office use. Quiet design for comfortable extended work sessions.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Desktop'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1988&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'TNB-X1-G12'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'TechNova Business X1 Gen12'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Lightweight business laptop. A proven model that balances durability and portability. Packed with security features.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Laptop'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2980&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'FXP-11-HYBRID'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'FlexPad 11 Hybrid'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'The definitive 2-in-1 device. Flexible enough to use as both a tablet and laptop. Recommended for frequent travelers.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Tablet'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1768&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'VNS-15-CREATOR'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'VisionStudio 15 Creator Edition'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'High-performance laptop for creators. 4K OLED display ideal for video production. Runs video editing software smoothly.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Laptop'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3298&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Verify data&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;product_catalog&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh04lgeuekmeyagcmpic5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh04lgeuekmeyagcmpic5.png" alt=" " width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Verify that the table is created and data is inserted in Snowsight.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create Cortex Search Service with Multi-Index
&lt;/h3&gt;

&lt;p&gt;Next, let's create a Cortex Search service with indexes on multiple columns.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: As of January 2026, &lt;strong&gt;Snowsight's GUI does not support creating Multi-Index Cortex Search services&lt;/strong&gt;. You must use SQL to create Multi-Index services.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Run the following query in Snowflake SQL Worksheets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Create Cortex Search Service with Multi-Index&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="n"&gt;CORTEX&lt;/span&gt; &lt;span class="k"&gt;SEARCH&lt;/span&gt; &lt;span class="n"&gt;SERVICE&lt;/span&gt; &lt;span class="n"&gt;product_multi_search&lt;/span&gt;
    &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="n"&gt;INDEXES&lt;/span&gt; &lt;span class="n"&gt;product_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product_name&lt;/span&gt;
    &lt;span class="n"&gt;VECTOR&lt;/span&gt; &lt;span class="n"&gt;INDEXES&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'voyage-multilingual-2'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ATTRIBUTES&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;
    &lt;span class="n"&gt;WAREHOUSE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cortex_search_wh&lt;/span&gt;
    &lt;span class="n"&gt;TARGET_LAG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'1 hour'&lt;/span&gt;
    &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;SELECT&lt;/span&gt;
            &lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;product_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;product_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;price&lt;/span&gt;
        &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;product_catalog&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Multi-Index uses &lt;code&gt;TEXT INDEXES&lt;/code&gt; and &lt;code&gt;VECTOR INDEXES&lt;/code&gt; to create indexes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TEXT INDEXES&lt;/strong&gt;: Indexes for keyword (lexical) search. Suitable for fields like &lt;code&gt;product_code&lt;/code&gt; or &lt;code&gt;product_name&lt;/code&gt; where exact match or keyword matching is important.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VECTOR INDEXES&lt;/strong&gt;: Indexes for vector (semantic) search. Suitable for fields like &lt;code&gt;description&lt;/code&gt; where semantic similarity search is important. We explicitly specify the &lt;code&gt;voyage-multilingual-2&lt;/code&gt; model for better multilingual performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: When creating a Multi-Index service, &lt;strong&gt;you must specify at least one column in VECTOR INDEXES&lt;/strong&gt;. Omitting VECTOR INDEXES will result in an error.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;SQL Reference: &lt;a href="https://docs.snowflake.com/en/sql-reference/sql/create-cortex-search" rel="noopener noreferrer"&gt;CREATE CORTEX SEARCH SERVICE&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6e63v20y33vua7nzzvkf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6e63v20y33vua7nzzvkf.png" alt=" " width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Verify that the service is created in AI Studio's Cortex Search list view or via &lt;code&gt;SHOW CORTEX SEARCH SERVICES;&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Testing Multi-Index Search and Index-Specific Boosts
&lt;/h3&gt;

&lt;p&gt;This is where Multi-Index and Index-Specific Boosts really shine!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: As of January 2026, the Playground does not support Index-Specific Boosts, so &lt;strong&gt;we'll execute searches via SQL queries&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When querying a Multi-Index service, you can use the &lt;code&gt;multi_index_query&lt;/code&gt; parameter to &lt;strong&gt;explicitly specify which index receives which query&lt;/strong&gt;. Additionally, the &lt;code&gt;scoring_config&lt;/code&gt; &lt;code&gt;weights&lt;/code&gt; parameter lets you &lt;strong&gt;adjust the weight balance between keyword search (texts) and vector search (vectors)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Official documentation: &lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-search/query-cortex-search-service#multi-index-queries" rel="noopener noreferrer"&gt;Query a Cortex Search Service - Multi-index queries&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Demo Scenario Explanation
&lt;/h4&gt;

&lt;p&gt;The key point of Multi-Index is that you can &lt;strong&gt;send different appropriate queries to each index&lt;/strong&gt;. Similar to the official documentation examples, you send keyword-matching strings to TEXT INDEX and semantic queries to VECTOR INDEX.&lt;/p&gt;

&lt;p&gt;For this demo, we'll verify the following scenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TEXT INDEX (product_name)&lt;/strong&gt; receives the keyword "CloudBook" → Products with "CloudBook" in the name get keyword matches&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VECTOR INDEX (description)&lt;/strong&gt; receives the semantic query "a PC that's safe to use while traveling" → Products with semantically related descriptions get matches&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Product Name&lt;/th&gt;
&lt;th&gt;TEXT Match&lt;/th&gt;
&lt;th&gt;VECTOR Match&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CloudBook Air 15 X5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓ (contains "CloudBook" in name)&lt;/td&gt;
&lt;td&gt;△ (no mention of security)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CloudBook Pro 14 X7&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓ (contains "CloudBook" in name)&lt;/td&gt;
&lt;td&gt;△ (no mention of security)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TechNova Business X1 Gen12&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;td&gt;✓ ("Packed with security features" → semantically related to "safe")&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;By changing &lt;code&gt;weights&lt;/code&gt;, you can control which type of match is prioritized.&lt;/p&gt;

&lt;h4&gt;
  
  
  Case 1: Prioritize Keyword Search (texts)
&lt;/h4&gt;

&lt;p&gt;By increasing the &lt;code&gt;texts&lt;/code&gt; weight, &lt;strong&gt;products with "CloudBook" in their names appear at the top&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Prioritize keyword search: set texts weight high&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'product_name'&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;product_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FLATTEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PARSE_JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;SNOWFLAKE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CORTEX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SEARCH_PREVIEW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'cortex_search_demo.multi_index_demo.product_multi_search'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'{
            "multi_index_query": {
                "product_name": [{"text": "CloudBook"}],
                "description": [{"text": "a PC that is safe to use while traveling"}]
            },
            "scoring_config": {
                "weights": {
                    "texts": 5,
                    "vectors": 1,
                    "reranker": 1
                }
            },
            "columns": ["product_name", "description"],
            "limit": 5
        }'&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="s1"&gt;'results'&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd1073lvw2889ds5kwpsm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd1073lvw2889ds5kwpsm.png" alt=" " width="800" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Verify that CloudBook series products appear at the top. This is because the product names contain the keyword "CloudBook." Of course, vector search results are also factored in, albeit with lower weight.&lt;/p&gt;

&lt;h4&gt;
  
  
  Case 2: Prioritize Vector Search (vectors)
&lt;/h4&gt;

&lt;p&gt;By increasing the &lt;code&gt;vectors&lt;/code&gt; weight, &lt;strong&gt;products with descriptions semantically related to "a PC that's safe to use while traveling" appear at the top&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Prioritize vector search: set vectors weight high&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'product_name'&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;product_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FLATTEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PARSE_JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;SNOWFLAKE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CORTEX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SEARCH_PREVIEW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'cortex_search_demo.multi_index_demo.product_multi_search'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'{
            "multi_index_query": {
                "product_name": [{"text": "CloudBook"}],
                "description": [{"text": "a PC that is safe to use while traveling"}]
            },
            "scoring_config": {
                "weights": {
                    "texts": 1,
                    "vectors": 5,
                    "reranker": 1
                }
            },
            "columns": ["product_name", "description"],
            "limit": 5
        }'&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="s1"&gt;'results'&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93l7nnbxv44l1q9ooyxz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93l7nnbxv44l1q9ooyxz.png" alt=" " width="798" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Verify that "TechNova Business X1 Gen12" appears at the top. Its description mentions "Packed with security features," which semantically matches the query "safe to use while traveling."&lt;/p&gt;

&lt;h4&gt;
  
  
  Case 3: Query Only VECTOR INDEX
&lt;/h4&gt;

&lt;p&gt;With &lt;code&gt;multi_index_query&lt;/code&gt;, you can also &lt;strong&gt;target only specific indexes&lt;/strong&gt;. When searching only the VECTOR INDEX without TEXT INDEX, you get results based purely on semantic relevance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Query only VECTOR INDEX (description)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'product_name'&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;product_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FLATTEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PARSE_JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;SNOWFLAKE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CORTEX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SEARCH_PREVIEW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'cortex_search_demo.multi_index_demo.product_multi_search'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'{
            "multi_index_query": {
                "description": [{"text": "high-spec PC ideal for creative video production"}]
            },
            "columns": ["product_name", "description"],
            "limit": 3
        }'&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="s1"&gt;'results'&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiskivfqqg5vdrrlsamo4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiskivfqqg5vdrrlsamo4.png" alt=" " width="799" height="115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Verify that products with descriptions mentioning "video editing," "video production," or "creator" (like VisionStudio 15 Creator Edition) appear at the top.&lt;/p&gt;

&lt;h4&gt;
  
  
  Case 4: Using Index-Specific Boosts (text_boosts)
&lt;/h4&gt;

&lt;p&gt;With &lt;code&gt;text_boosts&lt;/code&gt;, you can &lt;strong&gt;adjust the weight of each column within TEXT INDEXes individually&lt;/strong&gt;. In this demo, we have &lt;code&gt;product_code&lt;/code&gt; and &lt;code&gt;product_name&lt;/code&gt; defined as TEXT INDEXes, so even when searching with the same keyword "Pro," you can control whether to prioritize matches in product code or product name.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;code&gt;multi_index_query&lt;/code&gt; &lt;strong&gt;requires at least one VECTOR INDEX to be specified&lt;/strong&gt;. TEXT INDEX-only queries will result in an error.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- text_boosts: prioritize product_name matches over product_code&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'product_code'&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;product_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'product_name'&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;product_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="nb"&gt;VARCHAR&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FLATTEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PARSE_JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;SNOWFLAKE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CORTEX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SEARCH_PREVIEW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'cortex_search_demo.multi_index_demo.product_multi_search'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'{
            "multi_index_query": {
                "product_code": [{"text": "Pro"}],
                "product_name": [{"text": "Pro"}],
                "description": [{"text": "high-performance laptop"}]
            },
            "scoring_config": {
                "weights": {
                    "texts": 5,
                    "vectors": 1,
                    "reranker": 1
                },
                "functions": {
                    "text_boosts": [
                        {"column": "product_code", "weight": 1},
                        {"column": "product_name", "weight": 3}
                    ]
                }
            },
            "columns": ["product_code", "product_name", "description"],
            "limit": 5
        }'&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="s1"&gt;'results'&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1l8s99u64l4o9javm5wt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1l8s99u64l4o9javm5wt.png" alt=" " width="798" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The keyword "Pro" appears in both product codes (CBP-16-X9-&lt;strong&gt;PRO&lt;/strong&gt;) and product names (CloudBook &lt;strong&gt;Pro&lt;/strong&gt; 16 X9, PixelPad &lt;strong&gt;Pro&lt;/strong&gt; 13 Z4, etc.), but since we've weighted &lt;code&gt;product_name&lt;/code&gt; higher, products with "Pro" in their names are prioritized.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: When using &lt;code&gt;text_boosts&lt;/code&gt;, you &lt;strong&gt;must specify weights for all columns defined as TEXT INDEXes&lt;/strong&gt;. Specifying only some columns will result in an error. The same applies to &lt;code&gt;vector_boosts&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Search Results Comparison Summary
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Case&lt;/th&gt;
&lt;th&gt;Configuration&lt;/th&gt;
&lt;th&gt;Expected Top Products&lt;/th&gt;
&lt;th&gt;Reason&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Case 1&lt;/td&gt;
&lt;td&gt;Prioritize texts&lt;/td&gt;
&lt;td&gt;CloudBook series&lt;/td&gt;
&lt;td&gt;"CloudBook" keyword matches in product name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Case 2&lt;/td&gt;
&lt;td&gt;Prioritize vectors&lt;/td&gt;
&lt;td&gt;TechNova Business X1 Gen12&lt;/td&gt;
&lt;td&gt;"security features" semantically matches "safe to use while traveling"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Case 3&lt;/td&gt;
&lt;td&gt;description only&lt;/td&gt;
&lt;td&gt;VisionStudio 15 Creator Edition&lt;/td&gt;
&lt;td&gt;"video production" related descriptions semantically match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Case 4&lt;/td&gt;
&lt;td&gt;text_boosts with product_name priority&lt;/td&gt;
&lt;td&gt;Products with "Pro" in name&lt;/td&gt;
&lt;td&gt;text_boosts sets product_name weight higher&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As you can see, &lt;strong&gt;by sending different queries to TEXT INDEX and VECTOR INDEX, adjusting the weight balance with &lt;code&gt;weights&lt;/code&gt;, fine-tuning individual column weights with &lt;code&gt;text_boosts&lt;/code&gt;/&lt;code&gt;vector_boosts&lt;/code&gt;, and targeting specific indexes, you can flexibly control search results&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;How was it? Cortex Search's &lt;strong&gt;Multi-Index&lt;/strong&gt; and &lt;strong&gt;Index-Specific Boosts&lt;/strong&gt; enable flexible cross-field search and fine-grained weight adjustments based on search context.&lt;/p&gt;

&lt;p&gt;I see significant value in the following points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Search Flexibility&lt;/strong&gt;: Integrate and search across fields with different characteristics like product codes, names, and descriptions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Search Control&lt;/strong&gt;: Change boost values per search to switch between exact-match focus ↔ fuzzy-search focus&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Business Requirement Alignment&lt;/strong&gt;: Deliver optimal search experiences across various scenarios including e-commerce, internal knowledge bases, and customer support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Agent Accuracy Improvement&lt;/strong&gt;: Enhanced search flexibility and precision directly improves RAG response quality and AI Agent decision accuracy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In an era where AI Agents are increasingly adopted within enterprises, &lt;strong&gt;enterprise search becomes a core component for complementing domain knowledge&lt;/strong&gt;. Multi-Index and Index-Specific Boosts represent a significant update that contributes to elevating enterprise AI adoption overall, not just a mere search feature improvement.&lt;/p&gt;

&lt;p&gt;If you're considering RAG application development or enterprise search system implementation, I highly encourage you to leverage this Multi-Index feature. Snowflake's AI capabilities continue to evolve as the &lt;strong&gt;"AI platform for enterprise data"&lt;/strong&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Promotion
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Snowflake What's New Updates on X
&lt;/h3&gt;

&lt;p&gt;I share Snowflake What's New updates on X. Follow for the latest insights:&lt;/p&gt;

&lt;h4&gt;
  
  
  English Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_en" rel="noopener noreferrer"&gt;Snowflake What's New Bot (English Version)&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Japanese Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_jp" rel="noopener noreferrer"&gt;Snowflake's What's New Bot (Japanese Version)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Change Log
&lt;/h2&gt;

&lt;p&gt;(20260112) Initial post&lt;/p&gt;

&lt;h2&gt;
  
  
  Original Japanese Article
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://zenn.dev/snowflakejp/articles/334e112057725c" rel="noopener noreferrer"&gt;https://zenn.dev/snowflakejp/articles/334e112057725c&lt;/a&gt;&lt;/p&gt;

</description>
      <category>snowflake</category>
      <category>vectordatabase</category>
      <category>rag</category>
      <category>agents</category>
    </item>
    <item>
      <title>SiS Container Runtime - Run Streamlit Apps at a Fraction of the Cost</title>
      <dc:creator>Tsubasa Kanno</dc:creator>
      <pubDate>Tue, 23 Dec 2025 12:09:04 +0000</pubDate>
      <link>https://dev.to/tsubasa_tech/sis-container-runtime-run-streamlit-apps-at-a-fraction-of-the-cost-2mn8</link>
      <guid>https://dev.to/tsubasa_tech/sis-container-runtime-run-streamlit-apps-at-a-fraction-of-the-cost-2mn8</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hey everyone! Quick off-topic confession: I've recently gotten into collecting Topps trading cards - MLB and NBA mostly. There's something incredibly satisfying about pulling a rare rookie card after opening a bunch of packs. It's become my new stress-relief hobby and honestly, my happiness levels are through the roof! 🏀⚾ Anyway, back to the tech stuff...&lt;/p&gt;

&lt;p&gt;It's finally here! &lt;strong&gt;Container Runtime&lt;/strong&gt; for Streamlit in Snowflake (SiS) launched in Public Preview! (It subsequently reached GA in March 2026.)&lt;/p&gt;

&lt;p&gt;Previously, SiS used warehouses as the runtime environment. While warehouses are optimized for query execution and work great for data-heavy analytical apps, they were often overkill for many applications. Running a simple visualization app shouldn't require spinning up a full warehouse - and I know many of you felt the same way about the cost implications.&lt;/p&gt;

&lt;p&gt;Container Runtime changes everything. It allows you to allocate smaller, more appropriate resources and separates app execution from query execution. This is a game-changer for cost optimization.&lt;/p&gt;

&lt;p&gt;In this article, I'll walk you through SiS Container Runtime - from its core concepts and differences from Warehouse Runtime, to costs, considerations, package management, and a hands-on tutorial building a simple data visualization app.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note (2025/12/23)&lt;/strong&gt;: SiS Container Runtime is currently in Public Preview. Features may be significantly updated in the future. (It subsequently reached GA in March 2026.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update (2026/6/6)&lt;/strong&gt;: Following Snowflake Summit 2026, I added a pointer to the related &lt;strong&gt;Snowflake App Runtime&lt;/strong&gt;. Note that SiS Container Runtime &lt;strong&gt;reached GA in March 2026&lt;/strong&gt;, and along with it, &lt;strong&gt;secret references via &lt;code&gt;st.secrets&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;sharing via the app-viewer URL (no Snowsight UI required)&lt;/strong&gt;, and &lt;strong&gt;logging/tracing&lt;/strong&gt; also became generally available. (Any "Preview" wording in the body reflects the state at the time of writing.)&lt;/p&gt;

&lt;p&gt;Note: This article represents my personal views and not those of Snowflake.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is SiS Container Runtime?
&lt;/h2&gt;

&lt;p&gt;SiS Container Runtime is a &lt;strong&gt;new runtime environment&lt;/strong&gt; for running Streamlit apps on Snowflake. Unlike the traditional Warehouse Runtime, it takes a container-based approach, executing app code on a &lt;strong&gt;compute pool&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Long-running Service&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Apps run as persistent services where all users accessing the same app share a single instance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fast Startup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Users connect to an already-running app, resulting in faster access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PyPI Package Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Install packages from PyPI using &lt;code&gt;pyproject.toml&lt;/code&gt; or &lt;code&gt;requirements.txt&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Latest Streamlit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use Streamlit 1.49+ (including &lt;code&gt;streamlit-nightly&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Full Cache Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Leverage Streamlit's caching features across user sessions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/developer-guide/streamlit/app-development/runtime-environments" rel="noopener noreferrer"&gt;Runtime environments for Streamlit apps (Snowflake Documentation)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Warehouse Runtime vs Container Runtime
&lt;/h2&gt;

&lt;p&gt;Here's a comprehensive comparison of the two runtime environments:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Warehouse Runtime&lt;/th&gt;
&lt;th&gt;Container Runtime&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compute&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;App code and internal queries run on warehouse&lt;/td&gt;
&lt;td&gt;App code runs on compute pool node, internal queries run on warehouse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Base Image&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Linux in Python stored procedure&lt;/td&gt;
&lt;td&gt;Linux in Snowpark container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Python Version&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3.9, 3.10, 3.11&lt;/td&gt;
&lt;td&gt;3.11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Streamlit Version&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.22+ (select from Snowflake-provided versions)&lt;/td&gt;
&lt;td&gt;1.49+ (any PyPI version, including &lt;code&gt;streamlit-nightly&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dependency Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;environment.yml&lt;/code&gt; from Snowflake Conda channel&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;pyproject.toml&lt;/code&gt; or &lt;code&gt;requirements.txt&lt;/code&gt; from PyPI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Version Pinning&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;=&lt;/code&gt; operator, &lt;code&gt;*&lt;/code&gt; wildcard&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;==&lt;/code&gt; operator, &lt;code&gt;&amp;lt;, &amp;lt;=, &amp;gt;=, &amp;gt;&lt;/code&gt; with comma-separated lists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Entry Point Location&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Root of source directory&lt;/td&gt;
&lt;td&gt;Root or subdirectory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Streamlit Server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Temporary individual instance per user session&lt;/td&gt;
&lt;td&gt;Persistent shared instance for all user sessions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Caching&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No cross-session caching&lt;/td&gt;
&lt;td&gt;Full Streamlit caching support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Startup Time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slower (on-demand app creation per user)&lt;/td&gt;
&lt;td&gt;Faster per user (but slower initial deployment)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The Value of Container Runtime
&lt;/h2&gt;

&lt;p&gt;The true value of Container Runtime lies in &lt;strong&gt;resource optimization&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Separation of App and Query Execution
&lt;/h3&gt;

&lt;p&gt;With Warehouse Runtime, both app code and queries ran on the same warehouse. This meant warehouse resources were consumed even for simple UI rendering.&lt;/p&gt;

&lt;p&gt;Container Runtime separates these concerns: &lt;strong&gt;app code runs on a compute pool&lt;/strong&gt; while &lt;strong&gt;queries run on a warehouse&lt;/strong&gt;. You can now allocate minimal compute pool resources for app execution and appropriately-sized warehouses for query execution.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Lightweight Resource Options
&lt;/h3&gt;

&lt;p&gt;Compute pools offer &lt;strong&gt;more affordable options&lt;/strong&gt; than warehouses. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gen1 XS Warehouse: &lt;strong&gt;1 credit/hour&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Compute Pool &lt;code&gt;CPU_X64_XS&lt;/code&gt;: &lt;strong&gt;0.06 credits/hour&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's approximately &lt;strong&gt;1/16th the cost&lt;/strong&gt;! For lightweight visualization apps, this difference is significant.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Shared Instance Efficiency
&lt;/h3&gt;

&lt;p&gt;With Warehouse Runtime, each user got their own app instance. Container Runtime &lt;strong&gt;shares a single instance across all users&lt;/strong&gt;. The second user onward connects instantly to an already-running app, improving perceived performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Cross-Session Caching
&lt;/h3&gt;

&lt;p&gt;With Warehouse Runtime, Streamlit's &lt;code&gt;@st.cache_data&lt;/code&gt; and &lt;code&gt;@st.cache_resource&lt;/code&gt; decorators only cached within individual sessions. If User A cached a query result, User B would still execute the query again.&lt;/p&gt;

&lt;p&gt;With Container Runtime, &lt;strong&gt;caches are shared across users&lt;/strong&gt;. When User A caches a query result, User B can reuse that cache, reducing query execution and improving both performance and cost efficiency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost Considerations
&lt;/h2&gt;

&lt;p&gt;Container Runtime involves two types of resources:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Compute Pool
&lt;/h3&gt;

&lt;p&gt;Compute pools are &lt;strong&gt;billed per node&lt;/strong&gt;. Costs vary by node size (Instance Family), but options cheaper than the smallest warehouse (XS) are available.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: Streamlit runs as a single process, so multiple CPUs don't provide much benefit. Choose the smallest node size that meets your memory requirements to optimize costs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Recommended compute pool settings:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;th&gt;Reason&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INSTANCE_FAMILY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Small sizes like &lt;code&gt;CPU_X64_XS&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Streamlit is single-process, start small&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MIN_NODES&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Number of different apps to run simultaneously&lt;/td&gt;
&lt;td&gt;Each app uses one node&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MAX_NODES&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Higher than &lt;code&gt;MIN_NODES&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Prevent node shortages when adding new apps&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  2. Query Warehouse
&lt;/h3&gt;

&lt;p&gt;The warehouse for internal queries uses traditional &lt;strong&gt;credit-based billing&lt;/strong&gt;. Choose an appropriate size based on query complexity and data volume.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/developer-guide/snowpark-container-services/working-with-compute-pool" rel="noopener noreferrer"&gt;Working with compute pools (Snowflake Documentation)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Important Considerations
&lt;/h2&gt;

&lt;p&gt;Here are some things to keep in mind when using Container Runtime.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Python Version Compatibility
&lt;/h3&gt;

&lt;p&gt;Container Runtime currently supports &lt;strong&gt;Python 3.11 only&lt;/strong&gt;. Ensure your app and all dependencies are compatible with Python 3.11.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;code&gt;_snowflake&lt;/code&gt; Module Not Supported
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;_snowflake&lt;/code&gt; module available in Warehouse Runtime is &lt;strong&gt;not available&lt;/strong&gt; in Container Runtime. Use native Python libraries like Snowflake Python Connector instead.&lt;/p&gt;

&lt;p&gt;For example, to get the active session (commonly used in SiS), change your import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# NG: Not available in Container Runtime
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;_snowflake&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_active_session&lt;/span&gt;

&lt;span class="c1"&gt;# OK: Use this instead
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;snowflake.snowpark.context&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_active_session&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Shared Resources
&lt;/h3&gt;

&lt;p&gt;All users share disk, compute, and memory resources in Container Runtime. Design your app with &lt;strong&gt;efficient resource usage&lt;/strong&gt; in mind.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Deployment Time
&lt;/h3&gt;

&lt;p&gt;Container Runtime requires container startup during initial deployment, which may take &lt;strong&gt;longer than Warehouse Runtime&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. External Access Integration
&lt;/h3&gt;

&lt;p&gt;Installing packages from external package indexes like PyPI requires &lt;strong&gt;External Access Integration&lt;/strong&gt; configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/developer-guide/streamlit/features/external-access" rel="noopener noreferrer"&gt;External access integrations (Snowflake Documentation)&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Sleep Timer and Compute Pool Auto-Stop
&lt;/h3&gt;

&lt;p&gt;Warehouse Runtime includes a &lt;strong&gt;sleep timer&lt;/strong&gt; feature that automatically stops apps after a period of inactivity. Container Runtime doesn't have an equivalent sleep timer, but &lt;strong&gt;an app (service) is automatically suspended after 3 days with no viewer access&lt;/strong&gt; (as of GA). That said, note that &lt;strong&gt;the compute pool itself does not stop immediately&lt;/strong&gt; when an app session ends.&lt;/p&gt;

&lt;p&gt;To minimize costs, consider setting up a Task to stop compute pools during off-hours:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Example: Stop compute pool daily at 10 PM&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="n"&gt;TASK&lt;/span&gt; &lt;span class="n"&gt;STOP_STREAMLIT_POOL_TASK&lt;/span&gt;
    &lt;span class="n"&gt;WAREHOUSE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SIS_QUERY_WH&lt;/span&gt;
    &lt;span class="n"&gt;SCHEDULE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'USING CRON 0 22 * * * America/New_York'&lt;/span&gt;
&lt;span class="k"&gt;AS&lt;/span&gt;
    &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="n"&gt;COMPUTE&lt;/span&gt; &lt;span class="n"&gt;POOL&lt;/span&gt; &lt;span class="n"&gt;STREAMLIT_POOL&lt;/span&gt; &lt;span class="n"&gt;STOP&lt;/span&gt; &lt;span class="k"&gt;ALL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That said, compute pools are very affordable, so running them continuously has limited cost impact. Choose the approach that fits your operational style.&lt;/p&gt;

&lt;h2&gt;
  
  
  Managing Dependencies
&lt;/h2&gt;

&lt;p&gt;Container Runtime uses &lt;strong&gt;&lt;code&gt;pyproject.toml&lt;/code&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;requirements.txt&lt;/code&gt;&lt;/strong&gt; instead of &lt;code&gt;environment.yml&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  requirements.txt Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;streamlit==1.41.0
pandas&amp;gt;=2.0.0
plotly&amp;gt;=5.18.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  pyproject.toml Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[project]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"my-streamlit-app"&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1.0.0"&lt;/span&gt;

&lt;span class="nn"&gt;[project.dependencies]&lt;/span&gt;
&lt;span class="py"&gt;streamlit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"=&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.41&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="py"&gt;pandas&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="py"&gt;plotly&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;5.18&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Warehouse Runtime uses &lt;code&gt;=&lt;/code&gt; for version pinning, while Container Runtime uses &lt;code&gt;==&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Warehouse Runtime&lt;/th&gt;
&lt;th&gt;Container Runtime&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Config File&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;environment.yml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;pyproject.toml&lt;/code&gt; or &lt;code&gt;requirements.txt&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Package Source&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Snowflake Conda channel&lt;/td&gt;
&lt;td&gt;PyPI or other external indexes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Version Pinning&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;==&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Range Specification&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;*&lt;/code&gt; wildcard&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;, &amp;lt;=, &amp;gt;=, &amp;gt;, !=&lt;/code&gt; with comma-separated lists&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/developer-guide/streamlit/app-development/dependency-management" rel="noopener noreferrer"&gt;Dependency management for Streamlit apps (Snowflake Documentation)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hands-on: Building a Sales Dashboard
&lt;/h2&gt;

&lt;p&gt;Let's build a simple data visualization app using SiS Container Runtime!&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Snowflake account (AWS, Azure, or GCP commercial region)&lt;/li&gt;
&lt;li&gt;Role with the following privileges:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Privilege&lt;/th&gt;
&lt;th&gt;Object&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;USAGE&lt;/td&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;Database where you create the app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CREATE STREAMLIT, USAGE&lt;/td&gt;
&lt;td&gt;Schema&lt;/td&gt;
&lt;td&gt;Schema where you create the app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;USAGE&lt;/td&gt;
&lt;td&gt;Warehouse&lt;/td&gt;
&lt;td&gt;Warehouse for query execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;USAGE&lt;/td&gt;
&lt;td&gt;Compute pool&lt;/td&gt;
&lt;td&gt;Compute pool for app execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CREATE COMPUTE POOL&lt;/td&gt;
&lt;td&gt;Account&lt;/td&gt;
&lt;td&gt;If creating a new compute pool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CREATE INTEGRATION&lt;/td&gt;
&lt;td&gt;Account&lt;/td&gt;
&lt;td&gt;If creating a new External Access Integration&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/developer-guide/streamlit/getting-started/overview#label-streamlit-prereqs" rel="noopener noreferrer"&gt;Privileges required to create and use a Streamlit app (Snowflake Documentation)&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Set Up the Environment
&lt;/h3&gt;

&lt;p&gt;Let's run the following SQL in Snowsight SQL Worksheets to set up our demo environment!&lt;/p&gt;

&lt;p&gt;First, create the database, schema, and stage for source code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Create database and schema&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;SIS_CONTAINER_DB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;SIS_CONTAINER_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Create stage for source code&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="n"&gt;STAGE&lt;/span&gt; &lt;span class="n"&gt;SIS_CONTAINER_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP_STAGE&lt;/span&gt;
  &lt;span class="n"&gt;ENCRYPTION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'SNOWFLAKE_SSE'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;DIRECTORY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ENABLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;TRUE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Create sample data table&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;SIS_CONTAINER_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SALES_DATA&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;SALE_DATE&lt;/span&gt; &lt;span class="nb"&gt;DATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;PRODUCT&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;REGION&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;SALES_AMOUNT&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Insert sample data&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;SIS_CONTAINER_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SALES_DATA&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2024-01-01'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Product A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'East'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2024-01-01'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Product B'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'East'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2024-01-01'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Product A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'West'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2024-01-02'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Product B'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'West'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2024-01-02'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Product A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'East'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2024-01-03'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Product B'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'East'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1800&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2024-01-03'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Product A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'West'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;950&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2024-01-04'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Product B'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'West'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1400&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2024-01-04'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Product A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'East'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1050&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2024-01-05'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Product B'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'East'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1600&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Create Compute Pool
&lt;/h3&gt;

&lt;p&gt;Create a compute pool to run app code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Create compute pool&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;COMPUTE&lt;/span&gt; &lt;span class="n"&gt;POOL&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;STREAMLIT_POOL&lt;/span&gt;
    &lt;span class="n"&gt;MIN_NODES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;MAX_NODES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="n"&gt;INSTANCE_FAMILY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CPU_X64_XS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Check compute pool status&lt;/span&gt;
&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;COMPUTE&lt;/span&gt; &lt;span class="n"&gt;POOLS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;DESCRIBE&lt;/span&gt; &lt;span class="n"&gt;COMPUTE&lt;/span&gt; &lt;span class="n"&gt;POOL&lt;/span&gt; &lt;span class="n"&gt;STREAMLIT_POOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Compute pool startup may take a few minutes. Wait until &lt;code&gt;SHOW COMPUTE POOLS&lt;/code&gt; shows &lt;code&gt;state&lt;/code&gt; as &lt;code&gt;ACTIVE&lt;/code&gt; or &lt;code&gt;IDLE&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1pwyu6eag6sg43hxe3wq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1pwyu6eag6sg43hxe3wq.png" alt=" " width="799" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Create External Access Integration
&lt;/h3&gt;

&lt;p&gt;Create an External Access Integration to allow package installation from PyPI.&lt;/p&gt;

&lt;p&gt;Snowflake provides a default network rule &lt;strong&gt;&lt;code&gt;snowflake.external_access.pypi_rule&lt;/code&gt;&lt;/strong&gt; for PyPI access, so you don't need to create your own:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Create External Access Integration (using Snowflake-managed PyPI network rule)&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;EXTERNAL&lt;/span&gt; &lt;span class="k"&gt;ACCESS&lt;/span&gt; &lt;span class="n"&gt;INTEGRATION&lt;/span&gt; &lt;span class="n"&gt;PYPI_ACCESS_INTEGRATION&lt;/span&gt;
    &lt;span class="n"&gt;ALLOWED_NETWORK_RULES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snowflake&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;external_access&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pypi_rule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ENABLED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;TRUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/developer-guide/external-network-access/external-network-access-examples" rel="noopener noreferrer"&gt;External network access examples (Snowflake Documentation)&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Prepare Application Files
&lt;/h3&gt;

&lt;p&gt;Create these two files and upload them to the stage.&lt;/p&gt;

&lt;h4&gt;
  
  
  streamlit_app.py
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;streamlit&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;snowflake.snowpark.context&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_active_session&lt;/span&gt;

&lt;span class="c1"&gt;# Page configuration
&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_page_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wide&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Get Snowflake session
&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_active_session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Title
&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;📊 Sales Dashboard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A simple sales visualization app running on Container Runtime.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Load data
&lt;/span&gt;&lt;span class="nd"&gt;@st.cache_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_data&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT * FROM SALES_DATA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_pandas&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;load_data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Sidebar filters
&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sidebar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Filter Settings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;selected_products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sidebar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;multiselect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Select Products&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PRODUCT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PRODUCT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;selected_regions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sidebar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;multiselect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Select Regions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;REGION&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;REGION&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Filter data
&lt;/span&gt;&lt;span class="n"&gt;filtered_df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PRODUCT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;isin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;selected_products&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;REGION&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;isin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;selected_regions&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Display metrics
&lt;/span&gt;&lt;span class="n"&gt;col1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;col2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;col3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;col1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Total Sales&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;filtered_df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SALES_AMOUNT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;col2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Transaction Count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filtered_df&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;col3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Average Sale&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;filtered_df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SALES_AMOUNT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Charts
&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subheader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Daily Sales Trend&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;daily_sales&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filtered_df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SALE_DATE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SALES_AMOUNT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;line_chart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;daily_sales&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SALE_DATE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SALES_AMOUNT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subheader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sales by Product&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;product_sales&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filtered_df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PRODUCT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SALES_AMOUNT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bar_chart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_sales&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PRODUCT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SALES_AMOUNT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Data table
&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subheader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Detailed Data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dataframe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filtered_df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;use_container_width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Footer
&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;---&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🚀 Powered by Streamlit in Snowflake Container Runtime&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  requirements.txt
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;streamlit&amp;gt;=1.41.0
pandas&amp;gt;=2.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Upload Files to Stage
&lt;/h3&gt;

&lt;p&gt;Upload the files via Snowsight UI or use PUT commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Upload via SnowSQL or local environment&lt;/span&gt;
&lt;span class="n"&gt;PUT&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;///&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;streamlit_app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;SIS_CONTAINER_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP_STAGE&lt;/span&gt; &lt;span class="n"&gt;AUTO_COMPRESS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;FALSE&lt;/span&gt; &lt;span class="n"&gt;OVERWRITE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;TRUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;PUT&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;///&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;requirements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;SIS_CONTAINER_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP_STAGE&lt;/span&gt; &lt;span class="n"&gt;AUTO_COMPRESS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;FALSE&lt;/span&gt; &lt;span class="n"&gt;OVERWRITE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;TRUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Verify stage contents&lt;/span&gt;
&lt;span class="n"&gt;LIST&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;SIS_CONTAINER_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP_STAGE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fait6028vmjfendqfu92s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fait6028vmjfendqfu92s.png" alt=" " width="799" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Create Streamlit App
&lt;/h3&gt;

&lt;p&gt;Create the Streamlit app with Container Runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Create query warehouse (skip if using existing warehouse)&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;WAREHOUSE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;SIS_QUERY_WH&lt;/span&gt;
    &lt;span class="n"&gt;WAREHOUSE_SIZE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'XSMALL'&lt;/span&gt;
    &lt;span class="n"&gt;AUTO_SUSPEND&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;
    &lt;span class="n"&gt;AUTO_RESUME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;TRUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Create Streamlit app&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="n"&gt;STREAMLIT&lt;/span&gt; &lt;span class="n"&gt;SIS_CONTAINER_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APP_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SALES_DASHBOARD_APP&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="s1"&gt;'@SIS_CONTAINER_DB.APP_SCHEMA.APP_STAGE'&lt;/span&gt;
    &lt;span class="n"&gt;MAIN_FILE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'streamlit_app.py'&lt;/span&gt;
    &lt;span class="n"&gt;QUERY_WAREHOUSE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SIS_QUERY_WH&lt;/span&gt;
    &lt;span class="n"&gt;RUNTIME_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'SYSTEM$ST_CONTAINER_RUNTIME_PY3_11'&lt;/span&gt;
    &lt;span class="n"&gt;COMPUTE_POOL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;STREAMLIT_POOL&lt;/span&gt;
    &lt;span class="n"&gt;EXTERNAL_ACCESS_INTEGRATIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PYPI_ACCESS_INTEGRATION&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key CREATE STREAMLIT Parameters
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FROM&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stage path containing source code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MAIN_FILE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Entry point Python file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;QUERY_WAREHOUSE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Warehouse for query execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RUNTIME_NAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Specify &lt;code&gt;SYSTEM$ST_CONTAINER_RUNTIME_PY3_11&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;COMPUTE_POOL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Compute pool for app code execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EXTERNAL_ACCESS_INTEGRATIONS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;External access integration (for PyPI access)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Step 7: Run the App
&lt;/h3&gt;

&lt;p&gt;In Snowsight, click 'Streamlit' in the left pane and select your &lt;code&gt;SALES_DASHBOARD_APP&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6k25fj10kreebhmbvujb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6k25fj10kreebhmbvujb.png" alt=" " width="800" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fey3xs6ia3xselddl5ltq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fey3xs6ia3xselddl5ltq.png" alt=" " width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffa3b1vnhqwfzjdklejpl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffa3b1vnhqwfzjdklejpl.png" alt=" " width="736" height="649"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your app is running! 🎉 You've successfully deployed a Streamlit app on Container Runtime!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Initial startup may take a few minutes for container initialization and package installation. Subsequent startups will be faster due to caching.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Migration Checklist
&lt;/h2&gt;

&lt;p&gt;When migrating existing Warehouse Runtime apps to Container Runtime, use this checklist:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Python 3.11 Compatibility&lt;/td&gt;
&lt;td&gt;Verify app and all dependencies work with Python 3.11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;_snowflake&lt;/code&gt; Module Usage&lt;/td&gt;
&lt;td&gt;Replace with &lt;code&gt;snowflake.snowpark.context&lt;/code&gt; etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;environment.yml&lt;/code&gt; Conversion&lt;/td&gt;
&lt;td&gt;Convert to &lt;code&gt;requirements.txt&lt;/code&gt; or &lt;code&gt;pyproject.toml&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Version Specification Syntax&lt;/td&gt;
&lt;td&gt;Change &lt;code&gt;=&lt;/code&gt; to &lt;code&gt;==&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt; to &lt;code&gt;&amp;gt;=&lt;/code&gt; etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compute Pool Creation&lt;/td&gt;
&lt;td&gt;Create appropriately-sized compute pool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;External Access Integration&lt;/td&gt;
&lt;td&gt;Create if PyPI access is needed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/developer-guide/streamlit/migrations-and-upgrades/runtime-migration" rel="noopener noreferrer"&gt;Migrate to a container runtime (Snowflake Documentation)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;SiS Container Runtime is a long-awaited feature that &lt;strong&gt;separates app execution from query execution&lt;/strong&gt; and enables &lt;strong&gt;lightweight resource allocation for apps&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The days of spinning up a warehouse just to run a simple visualization app are over! Container Runtime shines in use cases like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Always-on Dashboards&lt;/strong&gt;: Dashboards with frequent multi-user access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lightweight Visualization Apps&lt;/strong&gt;: Simple apps without heavy analytical processing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache-Leveraging Apps&lt;/strong&gt;: Apps that cache and reuse query results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It launched in Public Preview and &lt;strong&gt;reached GA in March 2026&lt;/strong&gt;. I encourage you to try this feature and make your Snowflake app development more efficient!&lt;/p&gt;

&lt;p&gt;If you want to deploy a &lt;strong&gt;full-stack web app like React / Next.js&lt;/strong&gt; (rather than Python) inside Snowflake, &lt;strong&gt;Snowflake App Runtime&lt;/strong&gt; — introduced at Snowflake Summit 2026 — is another option. See "&lt;a href="https://dev.to/tsubasa_tech/snowflake-app-runtime-deploy-full-stack-web-apps-right-next-to-your-data-from-a-single-prompt-1a29"&gt;Snowflake App Runtime - Deploy Full-Stack Web Apps Right Next to Your Data from a Single Prompt&lt;/a&gt;" for details.&lt;/p&gt;

&lt;p&gt;I'm excited to explore more ideas using SiS Container Runtime and will share useful apps I create in future blog posts. Stay tuned!&lt;/p&gt;

&lt;h2&gt;
  
  
  Promotion
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Snowflake What's New Updates on X
&lt;/h3&gt;

&lt;p&gt;I share Snowflake What's New updates on X. Follow for the latest insights:&lt;/p&gt;

&lt;h4&gt;
  
  
  English Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_en" rel="noopener noreferrer"&gt;Snowflake What's New Bot (English Version)&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Japanese Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_jp" rel="noopener noreferrer"&gt;Snowflake's What's New Bot (Japanese Version)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Change Log
&lt;/h2&gt;

&lt;p&gt;(20260606) Updated following Snowflake Summit 2026: added a pointer to Snowflake App Runtime and noted the GA of SiS Container Runtime&lt;br&gt;
(20251223) Initial post&lt;/p&gt;

&lt;h2&gt;
  
  
  Original Japanese Article
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://zenn.dev/snowflakejp/articles/abe3379e6e44cd" rel="noopener noreferrer"&gt;https://zenn.dev/snowflakejp/articles/abe3379e6e44cd&lt;/a&gt;&lt;/p&gt;

</description>
      <category>snowflake</category>
      <category>streamlit</category>
      <category>container</category>
      <category>python</category>
    </item>
    <item>
      <title>Auto-Generate Snowflake Semantic Views with AI - A Developer's Fast-Track to Cortex Analyst</title>
      <dc:creator>Tsubasa Kanno</dc:creator>
      <pubDate>Thu, 09 Oct 2025 12:53:00 +0000</pubDate>
      <link>https://dev.to/tsubasa_tech/auto-generate-snowflake-semantic-views-with-ai-a-developers-fast-track-to-cortex-analyst-44bp</link>
      <guid>https://dev.to/tsubasa_tech/auto-generate-snowflake-semantic-views-with-ai-a-developers-fast-track-to-cortex-analyst-44bp</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-analyst" rel="noopener noreferrer"&gt;&lt;strong&gt;Cortex Analyst&lt;/strong&gt;&lt;/a&gt; is one of Snowflake's most exciting features, enabling revolutionary natural language data analysis. Business users who don't usually write queries can simply ask "What are the top 10 products by sales last month?" and get instant insights without SQL - true &lt;strong&gt;data democratization&lt;/strong&gt; in action!&lt;/p&gt;

&lt;p&gt;However, for Cortex Analyst to reach its full potential, you need a well-structured &lt;strong&gt;semantic layer&lt;/strong&gt; as the foundation. Snowflake offers &lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-analyst/semantic-model-spec" rel="noopener noreferrer"&gt;Semantic Models&lt;/a&gt; or &lt;a href="https://docs.snowflake.com/en/user-guide/views-semantic/overview" rel="noopener noreferrer"&gt;Semantic Views&lt;/a&gt; to accomplish this, but creating semantic layers requires time and effort: understanding table structures, defining business logic, setting appropriate descriptions and synonyms, and more.&lt;/p&gt;

&lt;p&gt;If you're thinking "I want to use Cortex Analyst, but setting up the semantic layer is taking forever..." - you're in the right place! Today I'm introducing a &lt;strong&gt;stored procedure that auto-generates semantic views using AI&lt;/strong&gt;. This tool lets you quickly create a baseline semantic view from existing tables, giving you a fast start toward delivering analytics environments to business users.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This stored procedure is designed to &lt;strong&gt;assist with initial semantic view creation&lt;/strong&gt;. We recommend customizing the generated views according to your business requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: At the June 2025 Snowflake Summit, an official semantic layer auto-generation feature was announced. This stored procedure serves as a &lt;strong&gt;stopgap solution until the official feature is released&lt;/strong&gt;. When the official feature launches, I'll write about it as well!&lt;/p&gt;

&lt;p&gt;Note: This article represents my personal views and not those of Snowflake.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is a Semantic View?
&lt;/h2&gt;

&lt;p&gt;A semantic view is a Snowflake schema-level object that adds &lt;strong&gt;business context&lt;/strong&gt; to physical database tables. It maps technical column names (e.g., &lt;code&gt;amt_ttl_pre_dsc&lt;/code&gt;) to business-friendly concepts (e.g., "Total Sales", "Sales Amount") with detailed descriptions (e.g., "Total sales value for stores in the metropolitan area"), bridging the gap between data and business.&lt;/p&gt;

&lt;p&gt;Even more importantly, semantic views &lt;strong&gt;help AI correctly understand database structure and business logic&lt;/strong&gt;. Cortex Analyst can generate high-precision SQL queries from natural language questions precisely because of the semantic layer. Through synonyms and detailed descriptions, AI learns to understand that "last month's sales", "total sales", and "sales amount" all refer to the same concept, enabling it to select the right tables and columns for accurate query generation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Components of a Semantic View
&lt;/h3&gt;

&lt;p&gt;Semantic views consist of these elements:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Element&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Facts&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Primarily numeric fact data (row-level attributes)&lt;/td&gt;
&lt;td&gt;Sales quantity, unit price, amount, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dimensions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Category and attribute data (analysis axes)&lt;/td&gt;
&lt;td&gt;Product name, customer ID, date, region, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Metrics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Aggregated indicators (business KPIs)&lt;/td&gt;
&lt;td&gt;Total sales, average unit price, sales growth rate, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each element can be defined with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Synonyms&lt;/strong&gt;: Business aliases and natural phrasings (e.g., "sales" → "revenue", "sales amount")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comment&lt;/strong&gt;: Business explanations including units, ranges, and other details&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why Semantic Views Matter
&lt;/h3&gt;

&lt;p&gt;Semantic views provide these key values:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Improved Cortex Analyst Accuracy&lt;/strong&gt;: Serves as the foundation for AI to understand natural language and generate accurate SQL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent Business Definitions&lt;/strong&gt;: Unified business metrics across the entire organization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Democratization&lt;/strong&gt;: Enables non-technical users to access data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For more details, see the &lt;a href="https://docs.snowflake.com/en/user-guide/views-semantic/overview" rel="noopener noreferrer"&gt;official Snowflake documentation - Semantic View Overview&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: For information about Semantic Models (YAML format), see the &lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-analyst/semantic-model-spec" rel="noopener noreferrer"&gt;Cortex Analyst Semantic Model Documentation&lt;/a&gt;. This article focuses on the newer Semantic Views feature.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Challenges in Creating Semantic Layers
&lt;/h2&gt;

&lt;p&gt;Creating semantic layers manually involves these tasks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Understanding table structure (table definitions, column names, data types, sample data review)&lt;/li&gt;
&lt;li&gt;Classifying Facts, Dimensions, and Metrics&lt;/li&gt;
&lt;li&gt;Identifying business-relevant synonyms actually used in the field&lt;/li&gt;
&lt;li&gt;Considering appropriate descriptions (Comments) for each element&lt;/li&gt;
&lt;li&gt;Defining the structure in SQL syntax&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For large tables or multiple tables, this process takes considerable time. However, spending too much time on preparation delays the delivery of analytics environments to business users - having a quality baseline to start with is extremely valuable!&lt;/p&gt;

&lt;h2&gt;
  
  
  AI-Powered Auto-Generation Stored Procedure
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Overview
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;GENERATE_SEMANTIC_VIEW&lt;/code&gt; stored procedure I'm introducing auto-generates semantic views through these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Retrieve Table Information&lt;/strong&gt;: Get column info, data types, and comments using &lt;code&gt;DESCRIBE TABLE&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analyze Sample Data&lt;/strong&gt;: Infer actual usage and data characteristics from the first 5 rows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-Generated SQL&lt;/strong&gt;: LLM via AI_COMPLETE function (like claude-sonnet-4-5) generates semantic view DDL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create Semantic View&lt;/strong&gt;: Execute the generated SQL&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fully Automated&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automatically classifies Facts, Dimensions, and Metrics by just specifying table name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rich Synonyms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Infers actual usage from sample data to generate natural business-relevant synonyms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Detailed Descriptions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Auto-generates Comments with business meaning for each element&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Customizable&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Specify which LLM model to use (default: claude-sonnet-4-5)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Stored Procedure Code
&lt;/h3&gt;

&lt;p&gt;The complete code for the &lt;code&gt;GENERATE_SEMANTIC_VIEW&lt;/code&gt; stored procedure is provided below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="k"&gt;PROCEDURE&lt;/span&gt; &lt;span class="n"&gt;GENERATE_SEMANTIC_VIEW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;SOURCE_DATABASE&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;-- Source database name&lt;/span&gt;
    &lt;span class="n"&gt;SOURCE_SCHEMA&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;-- Source schema name&lt;/span&gt;
    &lt;span class="n"&gt;SOURCE_TABLE&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="c1"&gt;-- Source table name&lt;/span&gt;
    &lt;span class="n"&gt;TARGET_DATABASE&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;-- Target database name&lt;/span&gt;
    &lt;span class="n"&gt;TARGET_SCHEMA&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;-- Target schema name&lt;/span&gt;
    &lt;span class="n"&gt;TARGET_VIEW_NAME&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;-- Semantic view name to create&lt;/span&gt;
    &lt;span class="n"&gt;LLM_MODEL&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'claude-sonnet-4-5'&lt;/span&gt; &lt;span class="c1"&gt;-- LLM model to use&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;RETURNS&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;
&lt;span class="k"&gt;LANGUAGE&lt;/span&gt; &lt;span class="k"&gt;SQL&lt;/span&gt;
&lt;span class="k"&gt;EXECUTE&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;CALLER&lt;/span&gt;
&lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;
&lt;span class="k"&gt;DECLARE&lt;/span&gt;
    &lt;span class="c1"&gt;-- Table information&lt;/span&gt;
    &lt;span class="n"&gt;column_info&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;sample_data_json&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;table_comment&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;-- AI generation results&lt;/span&gt;
    &lt;span class="n"&gt;ai_response&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;-- Final SQL&lt;/span&gt;
    &lt;span class="n"&gt;create_view_sql&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;BEGIN&lt;/span&gt;
    &lt;span class="c1"&gt;-- ================================================================================&lt;/span&gt;
    &lt;span class="c1"&gt;-- STEP 1: Retrieve table information&lt;/span&gt;
    &lt;span class="c1"&gt;-- ================================================================================&lt;/span&gt;

    &lt;span class="c1"&gt;-- Get column information (using DESCRIBE TABLE)&lt;/span&gt;
    &lt;span class="k"&gt;DECLARE&lt;/span&gt;
        &lt;span class="n"&gt;describe_sql&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;rs&lt;/span&gt; &lt;span class="n"&gt;RESULTSET&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;BEGIN&lt;/span&gt;
        &lt;span class="n"&gt;describe_sql&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'DESCRIBE TABLE '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_DATABASE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_SCHEMA&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_TABLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;rs&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;EXECUTE&lt;/span&gt; &lt;span class="k"&gt;IMMEDIATE&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;describe_sql&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;-- Get information from results&lt;/span&gt;
        &lt;span class="c1"&gt;-- $1: Column name, $2: Data type, $10: Comment&lt;/span&gt;
        &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;LISTAGG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;':'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;CASE&lt;/span&gt; &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="s1"&gt;'('&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;')'&lt;/span&gt; &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;', '&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;column_info&lt;/span&gt;
        &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RESULT_SCAN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LAST_QUERY_ID&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

    &lt;span class="n"&gt;EXCEPTION&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;OTHER&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt;
            &lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="s1"&gt;'Error: Could not retrieve table information - '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_DATABASE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_SCHEMA&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_TABLE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'. Error: '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;SQLERRM&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;-- Error check&lt;/span&gt;
    &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;column_info&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;LENGTH&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;column_info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt;
        &lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="s1"&gt;'Error: Column information is empty - '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_DATABASE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_SCHEMA&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_TABLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;-- Get table comment&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;table_comment&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;INFORMATION_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TABLES&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;TABLE_CATALOG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_DATABASE&lt;/span&gt;
      &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;TABLE_SCHEMA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_SCHEMA&lt;/span&gt;
      &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="k"&gt;TABLE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_TABLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;-- Get sample data (first 5 rows)&lt;/span&gt;
    &lt;span class="k"&gt;DECLARE&lt;/span&gt;
        &lt;span class="n"&gt;sample_sql&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;sample_rs&lt;/span&gt; &lt;span class="n"&gt;RESULTSET&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;BEGIN&lt;/span&gt;
        &lt;span class="n"&gt;sample_sql&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'SELECT * FROM '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_DATABASE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_SCHEMA&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_TABLE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;' LIMIT 5'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;sample_rs&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;EXECUTE&lt;/span&gt; &lt;span class="k"&gt;IMMEDIATE&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sample_sql&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;-- Get sample data in JSON format&lt;/span&gt;
        &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;TO_VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ARRAY_AGG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OBJECT_CONSTRUCT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;sample_data_json&lt;/span&gt;
        &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RESULT_SCAN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LAST_QUERY_ID&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

    &lt;span class="n"&gt;EXCEPTION&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;OTHER&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt;
            &lt;span class="n"&gt;sample_data_json&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sample data unavailable'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;-- ================================================================================&lt;/span&gt;
    &lt;span class="c1"&gt;-- STEP 2: Generate complete Semantic View definition with AI&lt;/span&gt;
    &lt;span class="c1"&gt;-- ================================================================================&lt;/span&gt;

    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;SNOWFLAKE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CORTEX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COMPLETE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;LLM_MODEL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;CONCAT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'[IMPORTANT] Generate a Snowflake semantic view using the information below.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;★ DO NOT use any column names that do not exist ★'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;[TABLE INFORMATION]'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;Table: '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_DATABASE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_TABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;Alias: '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_TABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;Table Comment: '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;COALESCE&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;table_comment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'None'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;[EXISTING COLUMNS (Use ONLY these)]'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;column_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;[SAMPLE DATA (For understanding data usage)]'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;SUBSTRING&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;sample_data_json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;[SQL TO GENERATE]'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;CREATE OR REPLACE SEMANTIC VIEW '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;TARGET_DATABASE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;TARGET_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;TARGET_VIEW_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;  TABLES ('&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;    '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_TABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;' AS '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_DATABASE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_TABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;      WITH SYNONYMS (&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;alias1&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;, &lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;alias2&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;, &lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;alias3&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;, &lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;alias4&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;      COMMENT = &lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;Detailed table description&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;  )'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;  FACTS ('&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;    '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_TABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.fact_name AS existing_column_name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;      WITH SYNONYMS (&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;alias1&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;, &lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;alias2&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;      COMMENT = &lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;Detailed column description&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;  )'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;  DIMENSIONS ('&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;    '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_TABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.dim_name AS existing_column_name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;      WITH SYNONYMS (&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;alias1&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;, &lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;alias2&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;      COMMENT = &lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;Detailed column description&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;  )'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;  METRICS ('&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;    '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SOURCE_TABLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.metric_name AS SUM(existing_column_name)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;      WITH SYNONYMS (&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;alias1&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;, &lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;alias2&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;      COMMENT = &lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;Detailed column description&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;  )'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;  COMMENT = &lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;Detailed semantic view description&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;[ABSOLUTE RULES]'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;★★★ MOST IMPORTANT ★★★ Use ONLY column names from the above list'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;0. Omit Primary Key:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Do not write PRIMARY KEY clause'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Primary key constraints do not function in Snowflake and are optional'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;1. Column Name Usage:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Column names used on the right side of AS must also exist in the list'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Example OK: YEAR(TRANSACTION_DATE) ← only if TRANSACTION_DATE exists'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Example NG: YEAR(ORDER_DATE) ← if ORDER_DATE does not exist'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;2. FACTS (Numeric Data):'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Quantity, amount, price, score, rate - numeric type columns'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Include both simple column references and calculated formulas'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Example (simple): QUANTITY, PRICE, AMOUNT'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Example (calculated): revenue AS QUANTITY * UNIT_PRICE, discount_amount AS TOTAL_PRICE * 0.1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;3. DIMENSIONS (Attribute Data):'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - IDs, names, dates, categories, statuses'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Do not overlap with FACTS'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;4. No Duplicate Names: All table.name combinations on the left must be unique'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;5. Date Derivative Naming: original_column_name_year, original_column_name_month'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;6. Rich Synonyms (Critical for Cortex Analyst to understand user requests):'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Tables: 4-5 business-relevant aliases'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Each DIMENSION, FACT, METRIC: 2-3 natural aliases'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Infer appropriate synonyms from sample data actual usage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Example: sales amount → "total sales", "sales total", "revenue"'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Example: product ID → "product code", "item number", "SKU"'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;7. Rich COMMENTS:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Generate specific descriptions from sample data'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Include business meaning'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Specify units and ranges'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;8. Utilize Sample Data:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Understand actual usage from sample data content'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Generate more concrete, practical synonyms'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - Reflect data characteristics (range, units, etc.) in COMMENTS'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;9. Generate Abundant FACTS and DIMENSIONS:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - FACTS: Around 5-10 (simple columns + calculated formulas)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - DIMENSIONS: Around 5-15 (original columns + date derivatives)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;   - METRICS: Around 4-8 (various aggregation patterns)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;10. Output: SQL syntax only (no ```, no explanatory text)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;Output only the CREATE SEMANTIC VIEW statement:'&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;ai_response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;-- Debug: Verify AI response length&lt;/span&gt;
    &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;ai_response&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;LENGTH&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;ai_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt;
        &lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="s1"&gt;'Error: AI_COMPLETE returned an empty response. Column info: '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;SUBSTRING&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;column_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;-- Remove unnecessary characters&lt;/span&gt;
    &lt;span class="n"&gt;create_view_sql&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ai_response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;create_view_sql&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;create_view_sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'```sql'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;create_view_sql&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;create_view_sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'```'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;create_view_sql&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;create_view_sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;create_view_sql&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;create_view_sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Revised:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;create_view_sql&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;create_view_sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Modifications:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;create_view_sql&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;create_view_sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'**'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;create_view_sql&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;TRIM&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;create_view_sql&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;-- Final verification: Check SQL statement is not empty&lt;/span&gt;
    &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;create_view_sql&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;LENGTH&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;create_view_sql&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt;
        &lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="s1"&gt;'Error: Generated SQL is empty or too short. AI response: '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;SUBSTRING&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;ai_response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;-- ================================================================================&lt;/span&gt;
    &lt;span class="c1"&gt;-- STEP 4: Create semantic view&lt;/span&gt;
    &lt;span class="c1"&gt;-- ================================================================================&lt;/span&gt;

    &lt;span class="k"&gt;BEGIN&lt;/span&gt;
        &lt;span class="k"&gt;EXECUTE&lt;/span&gt; &lt;span class="k"&gt;IMMEDIATE&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;create_view_sql&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="s1"&gt;'Semantic view '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;TARGET_DATABASE&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;TARGET_SCHEMA&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;TARGET_VIEW_NAME&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;' created successfully. SQL: '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;create_view_sql&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;EXCEPTION&lt;/span&gt;
        &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;OTHER&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt;
            &lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="s1"&gt;'Error: '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;SQLERRM&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;' -- Generated SQL: '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;SUBSTRING&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="n"&gt;create_view_sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- ================================================================================&lt;/span&gt;
&lt;span class="c1"&gt;-- Usage Example&lt;/span&gt;
&lt;span class="c1"&gt;-- ================================================================================&lt;/span&gt;

&lt;span class="cm"&gt;/*
-- Basic usage
CALL GENERATE_SEMANTIC_VIEW(
    '&amp;lt;source_database&amp;gt;',
    '&amp;lt;source_schema&amp;gt;',
    '&amp;lt;source_table&amp;gt;',
    '&amp;lt;target_database&amp;gt;',
    '&amp;lt;target_schema&amp;gt;',
    '&amp;lt;semantic_view_name&amp;gt;',
    '&amp;lt;LLM_model_name&amp;gt;'
);

-- Verify created semantic view
DESCRIBE SEMANTIC VIEW &amp;lt;target_database&amp;gt;.&amp;lt;target_schema&amp;gt;.&amp;lt;semantic_view_name&amp;gt;;
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: You can copy and paste this stored procedure directly into your Snowflake environment for immediate use.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to Use
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;To use this stored procedure, you'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Snowflake account&lt;/li&gt;
&lt;li&gt;An environment where Cortex LLM is available (&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cross-region-inference" rel="noopener noreferrer"&gt;cross-region inference&lt;/a&gt; makes this available in most regions)&lt;/li&gt;
&lt;li&gt;Permissions to create semantic views&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Basic Usage Example
&lt;/h3&gt;

&lt;p&gt;Here's how to generate a semantic view from the &lt;code&gt;SALES_DATABASE.PUBLIC.ORDERS&lt;/code&gt; table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Call the stored procedure&lt;/span&gt;
&lt;span class="k"&gt;CALL&lt;/span&gt; &lt;span class="n"&gt;GENERATE_SEMANTIC_VIEW&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'SALES_DATABASE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;-- Source database&lt;/span&gt;
    &lt;span class="s1"&gt;'PUBLIC'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                   &lt;span class="c1"&gt;-- Source schema&lt;/span&gt;
    &lt;span class="s1"&gt;'ORDERS'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                   &lt;span class="c1"&gt;-- Source table&lt;/span&gt;
    &lt;span class="s1"&gt;'ANALYTICS_DATABASE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;-- Target database&lt;/span&gt;
    &lt;span class="s1"&gt;'SEMANTIC'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                 &lt;span class="c1"&gt;-- Target schema&lt;/span&gt;
    &lt;span class="s1"&gt;'ORDERS_SEMANTIC_VIEW'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;-- Semantic view name&lt;/span&gt;
    &lt;span class="s1"&gt;'claude-sonnet-4-5'&lt;/span&gt;         &lt;span class="c1"&gt;-- LLM model (optional)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- Verify the created semantic view&lt;/span&gt;
&lt;span class="k"&gt;DESCRIBE&lt;/span&gt; &lt;span class="n"&gt;SEMANTIC&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;ANALYTICS_DATABASE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SEMANTIC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ORDERS_SEMANTIC_VIEW&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example Generated Semantic View
&lt;/h3&gt;

&lt;p&gt;For example, given this table structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Sample table&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;ORDERS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ORDER_ID&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CUSTOMER_ID&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ORDER_DATE&lt;/span&gt; &lt;span class="nb"&gt;DATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;PRODUCT_NAME&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;QUANTITY&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;UNIT_PRICE&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;TOTAL_AMOUNT&lt;/span&gt; &lt;span class="n"&gt;NUMBER&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The stored procedure auto-generates a semantic view like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="n"&gt;SEMANTIC&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;ANALYTICS_DATABASE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SEMANTIC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ORDERS_SEMANTIC_VIEW&lt;/span&gt;
  &lt;span class="n"&gt;TABLES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ORDERS&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;SALES_DATABASE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;PUBLIC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ORDERS&lt;/span&gt;
      &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;SYNONYMS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Order Table'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Sales Data'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Purchase History'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Transactions'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Table managing customer order information'&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;FACTS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ORDERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quantity&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;QUANTITY&lt;/span&gt;
      &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;SYNONYMS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Qty'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Amount Ordered'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Number of Items'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Quantity of products ordered'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ORDERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unit_price&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;UNIT_PRICE&lt;/span&gt;
      &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;SYNONYMS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Price'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Item Price'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Product Price'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Price per product unit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ORDERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_amount&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;TOTAL_AMOUNT&lt;/span&gt;
      &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;SYNONYMS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Total'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Order Amount'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Purchase Total'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Total order amount'&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;DIMENSIONS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ORDERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;ORDER_ID&lt;/span&gt;
      &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;SYNONYMS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Order Number'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Transaction ID'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Order Ref'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Unique identifier for the order'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ORDERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;CUSTOMER_ID&lt;/span&gt;
      &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;SYNONYMS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Client ID'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Customer Number'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Account ID'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Customer identifier'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ORDERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_date&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;ORDER_DATE&lt;/span&gt;
      &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;SYNONYMS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Purchase Date'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Transaction Date'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Date Ordered'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Date the order was placed'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ORDERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;product_name&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;PRODUCT_NAME&lt;/span&gt;
      &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;SYNONYMS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Product'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Item Name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Item'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Name of the ordered product'&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;METRICS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ORDERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_sales&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TOTAL_AMOUNT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;SYNONYMS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Total Revenue'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Sales Total'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Revenue'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Total sales amount for all orders'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ORDERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;avg_order_amount&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TOTAL_AMOUNT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;SYNONYMS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Average Order Value'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'AOV'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Avg Purchase'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Average amount per order'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ORDERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;total_orders&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;SYNONYMS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Order Count'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Number of Orders'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Total Transactions'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Total number of orders'&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Semantic view for order data analysis'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use Case 1: Fast Start
&lt;/h3&gt;

&lt;p&gt;When introducing Cortex Analyst to a new project, use this stored procedure to quickly generate semantic views for key tables. Then customize only the necessary parts according to business requirements and add relationships between tables - &lt;strong&gt;several times faster than building from scratch&lt;/strong&gt;, helping you set up your semantic layer efficiently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Case 2: Data Catalog
&lt;/h3&gt;

&lt;p&gt;Generated semantic views contain rich synonyms and comments, making them excellent &lt;strong&gt;table documentation&lt;/strong&gt;. They serve as reference material for new team members learning the table structure or can be loaded into AI Agents as an AI-oriented data catalog.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Case 3: POC (Proof of Concept)
&lt;/h3&gt;

&lt;p&gt;For POCs validating Cortex Analyst's effectiveness, you often don't want to spend much time creating semantic layers. This stored procedure lets you &lt;strong&gt;build a demo environment in minutes&lt;/strong&gt; and immediately experience Cortex Analyst's value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customization Tips
&lt;/h2&gt;

&lt;p&gt;While auto-generated semantic views may work as-is, customizing these points will achieve even more accurate query generation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: You can customize semantic views not just through SQL commands (ALTER SEMANTIC VIEW), but also &lt;strong&gt;via GUI in Snowsight's AI/ML Studio&lt;/strong&gt;. AI/ML Studio lets you visually confirm the semantic view structure while intuitively adding synonyms, editing comments, and adding new Metrics.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  1. Adding/Modifying Synonyms
&lt;/h3&gt;

&lt;p&gt;Add industry-specific terms and internal company terminology to help Cortex Analyst better understand users' natural language:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Example: Add industry terms&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="n"&gt;SEMANTIC&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;ORDERS_SEMANTIC_VIEW&lt;/span&gt; 
&lt;span class="k"&gt;MODIFY&lt;/span&gt; &lt;span class="n"&gt;DIMENSION&lt;/span&gt; &lt;span class="n"&gt;ORDERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;product_name&lt;/span&gt; 
  &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="n"&gt;SYNONYMS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SKU'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Item Code'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Barcode'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Adding Complex Calculated Metrics
&lt;/h3&gt;

&lt;p&gt;Add advanced calculation formulas according to business logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Example: Add profit margin&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="n"&gt;SEMANTIC&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;ORDERS_SEMANTIC_VIEW&lt;/span&gt; 
&lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="n"&gt;METRIC&lt;/span&gt; &lt;span class="n"&gt;ORDERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;profit_margin&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TOTAL_AMOUNT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;COST&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TOTAL_AMOUNT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;SYNONYMS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Margin'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Profit Rate'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Return Rate'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;COMMENT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Profit ratio relative to sales'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Integrating Multiple Tables into a Semantic View
&lt;/h3&gt;

&lt;p&gt;To analyze across multiple tables, integrate individually generated semantic views and define relationships between tables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Example: Create semantic view containing both ORDERS and CUSTOMERS tables&lt;/span&gt;
&lt;span class="c1"&gt;-- First, generate semantic views for each table individually,&lt;/span&gt;
&lt;span class="c1"&gt;-- Then integrate into a new semantic view&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="n"&gt;SEMANTIC&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;SALES_ANALYSIS_VIEW&lt;/span&gt;
  &lt;span class="n"&gt;TABLES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ORDERS&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;SALES_DATABASE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;PUBLIC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ORDERS&lt;/span&gt;
      &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;SYNONYMS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Orders'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Sales Data'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;CUSTOMERS&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;SALES_DATABASE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;PUBLIC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CUSTOMERS&lt;/span&gt;
      &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;SYNONYMS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Customers'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Client Info'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;RELATIONSHIPS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ORDERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CUSTOMER_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CUSTOMERS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CUSTOMER_ID&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;-- Facts, Dimensions, Metrics omitted&lt;/span&gt;
  &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For detailed customization options, see the &lt;a href="https://docs.snowflake.com/en/user-guide/views-semantic/sql" rel="noopener noreferrer"&gt;official Snowflake documentation - Using SQL commands to create and manage semantic views&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integration with Cortex Analyst
&lt;/h2&gt;

&lt;p&gt;Generated semantic views are immediately usable with Cortex Analyst.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verifying in Snowsight
&lt;/h3&gt;

&lt;p&gt;After creating your semantic view, verify it works right away in &lt;strong&gt;Snowsight's AI/ML Studio Cortex Analyst playground&lt;/strong&gt;. For implementation, Snowflake offers various options including calling from Snowflake Intelligence, calling from Cortex Agents, or configuring as a tool in Snowflake MCP Server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important Notes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tool Limitations
&lt;/h3&gt;

&lt;p&gt;This stored procedure has the following constraint:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single Table Only&lt;/strong&gt;: This tool &lt;strong&gt;generates semantic views from a single table only&lt;/strong&gt;. To create semantic views combining multiple tables, first generate views for each table individually, then manually add relationships between tables.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Generated Semantic View Quality
&lt;/h3&gt;

&lt;p&gt;As this uses AI auto-generation, please note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Not Perfect&lt;/strong&gt;: Always review and customize generated semantic views according to business requirements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sample Data Dependency&lt;/strong&gt;: Generated synonyms and descriptions vary based on sample data content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex Logic&lt;/strong&gt;: Advanced business logic requires manual additions and modifications&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This AI auto-generation stored procedure is a tool that &lt;strong&gt;dramatically accelerates the initial stages of semantic view creation&lt;/strong&gt;. While semantic layer preparation is essential for Cortex Analyst to deliver "natural language data analysis" - that ideal world - it would be a shame if this necessary work becomes a barrier that delays your start!&lt;/p&gt;

&lt;p&gt;Using this stored procedure, you can generate baseline semantic views in seconds, then customize necessary parts from there. As a result, you can &lt;strong&gt;deliver analytics environments to business departments in a much shorter timeframe&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Take the first step toward realizing data democratization and empowering business users to extract insights from data themselves - I hope this tool helps you get there!&lt;/p&gt;

&lt;h2&gt;
  
  
  Promotion
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Snowflake What's New Updates on X
&lt;/h3&gt;

&lt;p&gt;I share Snowflake What's New updates on X. Follow for the latest insights:&lt;/p&gt;

&lt;h4&gt;
  
  
  English Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_en" rel="noopener noreferrer"&gt;Snowflake What's New Bot (English Version)&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Japanese Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_jp" rel="noopener noreferrer"&gt;Snowflake's What's New Bot (Japanese Version)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Change Log
&lt;/h2&gt;

&lt;p&gt;(20251009) Initial post&lt;/p&gt;

&lt;h2&gt;
  
  
  Original Japanese Article
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://zenn.dev/tsubasa_tech/articles/ce732d628a9bee" rel="noopener noreferrer"&gt;https://zenn.dev/tsubasa_tech/articles/ce732d628a9bee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>snowflake</category>
      <category>llm</category>
      <category>semanticlayer</category>
      <category>sql</category>
    </item>
    <item>
      <title>Unlock Advanced Data Analytics in Cursor with Snowflake MCP Server</title>
      <dc:creator>Tsubasa Kanno</dc:creator>
      <pubDate>Mon, 01 Sep 2025 11:00:03 +0000</pubDate>
      <link>https://dev.to/tsubasa_tech/unlock-advanced-data-analytics-in-cursor-with-snowflake-mcp-server-2flb</link>
      <guid>https://dev.to/tsubasa_tech/unlock-advanced-data-analytics-in-cursor-with-snowflake-mcp-server-2flb</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Major revision notice (July 2026)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The community MCP Server (Snowflake-Labs/mcp) originally covered in this article has been &lt;strong&gt;deprecated and is expected to be removed soon&lt;/strong&gt;. This article has therefore been fully revised to use the official, fully-managed &lt;strong&gt;Snowflake Managed MCP Server&lt;/strong&gt;. Key changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replaced the community (OSS) setup steps with the Snowflake Managed MCP Server workflow&lt;/li&gt;
&lt;li&gt;Changed the Cursor connection to use the Managed MCP Server endpoint URL + PAT (Bearer token)&lt;/li&gt;
&lt;li&gt;Reflected the rename of "Snowflake Intelligence" to "Snowflake CoWork"&lt;/li&gt;
&lt;li&gt;Updated configuration and feature descriptions to the latest specification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you previously set up the community version, please consider migrating to the Snowflake Managed MCP Server.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The AI agent movement in development keeps gaining momentum. The &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt;, a standardized protocol from Anthropic, enables seamless connections between LLMs and various tools and APIs. And Snowflake now offers an official, fully-managed &lt;strong&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp" rel="noopener noreferrer"&gt;Snowflake Managed MCP Server&lt;/a&gt;&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;While Cortex Search and Cortex Analyst were previously available as individual features, now that &lt;strong&gt;SQL execution&lt;/strong&gt; and &lt;strong&gt;Cortex Agents&lt;/strong&gt; can also be bundled as tools, you can access Snowflake's analytics environment directly from MCP clients (like Cursor or Claude Desktop). &lt;strong&gt;Simply give natural language instructions to your AI agent and complete your data analysis&lt;/strong&gt; - a welcome update for developers!&lt;/p&gt;

&lt;p&gt;In this article, I'll walk you through setting up and using the Snowflake Managed MCP Server with Cursor, explore the analytics possibilities it unlocks, and discuss when to use it versus Snowflake CoWork (formerly Snowflake Intelligence). If you're an engineer looking to analyze Snowflake data more efficiently, this guide is for you!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: The community version (Snowflake-Labs/mcp) has been deprecated and is expected to be removed soon. Going forward, the officially supported Snowflake Managed MCP Server is recommended, and this article is based on it.&lt;/p&gt;

&lt;p&gt;Note: This article represents my personal views and not those of Snowflake.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is Snowflake Managed MCP Server?
&lt;/h2&gt;

&lt;p&gt;Snowflake Managed MCP Server is an &lt;strong&gt;official, fully-managed server&lt;/strong&gt; that integrates various Snowflake features into the MCP ecosystem. By connecting with MCP clients (Cursor, Claude Desktop, etc.), you can operate Snowflake's data analytics capabilities through AI agents.&lt;/p&gt;

&lt;p&gt;Its key characteristic is that &lt;strong&gt;the server is hosted inside your Snowflake account&lt;/strong&gt;. There's no need to stand up a separate local server - you simply run a &lt;code&gt;CREATE MCP SERVER&lt;/code&gt; SQL statement, and Snowflake provisions a managed endpoint. Authentication and access control ride on Snowflake's RBAC / OAuth, making governance easier to enforce.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;p&gt;Snowflake Managed MCP Server lets you combine the following tools and expose them as a single server:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Cortex Search&lt;/strong&gt; (&lt;code&gt;CORTEX_SEARCH_SERVICE_QUERY&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Search unstructured data (e.g., for RAG applications)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Cortex Analyst&lt;/strong&gt; (&lt;code&gt;CORTEX_ANALYST_MESSAGE&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Analyze structured data using Semantic Views (Text2SQL)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Cortex Agents&lt;/strong&gt; (&lt;code&gt;CORTEX_AGENT_RUN&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Agentic orchestrator spanning structured and unstructured data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;SQL Execution&lt;/strong&gt; (&lt;code&gt;SYSTEM_EXECUTE_SQL&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Execute SQL generated by the AI agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Custom Tools&lt;/strong&gt; (&lt;code&gt;GENERIC&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Invoke user-defined functions (UDFs) or stored procedures as tools&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The Cortex Analyst tool in Snowflake Managed MCP Server works with &lt;strong&gt;Semantic Views&lt;/strong&gt;. Note that YAML-based semantic models are not supported.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Technical Characteristics
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Snowflake-hosted&lt;/strong&gt;: No separate infrastructure required; provided as a remote HTTP endpoint&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RBAC-based permissions&lt;/strong&gt;: Grant privileges separately to the MCP server itself and to each tool (the server-connection privilege and the tool-execution privilege are managed independently)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible authentication&lt;/strong&gt;: Supports OAuth 2.0 and PAT (Programmatic Access Token)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fine-grained SQL control&lt;/strong&gt;: The SQL execution tool can be restricted to read-only via the &lt;code&gt;read_only&lt;/code&gt; option&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Calling Other Tools and Agents from Cortex Agents via MCP
&lt;/h3&gt;

&lt;p&gt;So far we've looked at the "server that exposes Snowflake features to MCP clients (like Cursor)" side. Conversely, &lt;strong&gt;Cortex Agents themselves can act as MCP clients&lt;/strong&gt;. Through &lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp-connectors" rel="noopener noreferrer"&gt;MCP Connectors&lt;/a&gt;, a Cortex Agent can connect to external MCP servers and invoke their tools during orchestration.&lt;/p&gt;

&lt;p&gt;What's interesting is that a Managed MCP Server can expose a Cortex Agent itself as a tool (&lt;code&gt;CORTEX_AGENT_RUN&lt;/code&gt;). Combining these, you can build a setup where &lt;strong&gt;one agent calls another agent through MCP (agent-to-agent, or A2A)&lt;/strong&gt;. For example, you could have specialized agents handle different domains and delegate work to one another as needed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: When an agent calls another agent, be careful to avoid loops. Snowflake enforces a maximum recursion depth (10 invocations), but you should still design your configuration to avoid circular invocation paths. MCP Connectors coverage continues to expand, so check the &lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp-connectors" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; for the latest.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Choosing Between Snowflake CoWork and Managed MCP Server
&lt;/h2&gt;

&lt;p&gt;If you're familiar with Snowflake, you might wonder: "We already have &lt;strong&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/snowflake-cowork" rel="noopener noreferrer"&gt;Snowflake CoWork&lt;/a&gt;&lt;/strong&gt; (formerly Snowflake Intelligence) - how should I choose between them?" Here's my perspective:&lt;/p&gt;

&lt;h3&gt;
  
  
  When Snowflake CoWork is Better
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Target Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Business users, analysts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Environment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Web browser-based GUI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Main Use Cases&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Enterprise data analysis app deployment, report creation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Advantages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Easy setup, intuitive GUI operation. All environments managed by Snowflake for enhanced security&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Easy organization-wide rollout&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  When Snowflake Managed MCP Server is Better
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Target Users&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Engineers, developers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Environment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Development tools like Cursor, Claude Desktop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Main Use Cases&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Checking data during development, ad-hoc analysis, integration from external applications&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Advantages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Integrates with development workflow, analyze data alongside code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Individual or team-level usage&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In essence: &lt;strong&gt;Choose CoWork for easy enterprise-wide natural language analysis app deployment&lt;/strong&gt;, and &lt;strong&gt;Managed MCP Server for integrating Snowflake analytics into engineering MCP clients&lt;/strong&gt;. When in doubt, start with the easier-to-adopt Snowflake CoWork to clarify business expectations, then consider Snowflake Managed MCP Server as needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up with Cursor
&lt;/h2&gt;

&lt;p&gt;Let's create a Snowflake Managed MCP Server and connect to it from Cursor. There are three main steps: (1) create the MCP server on the Snowflake side, (2) issue a PAT and set up access, and (3) configure the connection on the Cursor side. We'll use a &lt;strong&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/programmatic-access-tokens" rel="noopener noreferrer"&gt;PAT (Programmatic Access Token)&lt;/a&gt;&lt;/strong&gt; for authentication.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create the MCP Server on Snowflake
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Prepare the Tools to Expose
&lt;/h4&gt;

&lt;p&gt;An MCP server exposes Cortex Search / Cortex Analyst / Cortex Agents and more as "tools." Depending on which tools you want, prepare the following in advance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;To use Cortex Search&lt;/strong&gt;: Create a &lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-search/cortex-search-overview" rel="noopener noreferrer"&gt;Cortex Search Service&lt;/a&gt; (for searching unstructured data)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;To use Cortex Analyst&lt;/strong&gt;: Create a &lt;a href="https://docs.snowflake.com/en/user-guide/views-semantic/overview" rel="noopener noreferrer"&gt;Semantic View&lt;/a&gt; (for Text2SQL over structured data)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;To use Cortex Agents&lt;/strong&gt;: Create a &lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents" rel="noopener noreferrer"&gt;Cortex Agent&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If you only need SQL execution&lt;/strong&gt;: No preparation required&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Create the MCP Server
&lt;/h4&gt;

&lt;p&gt;Once ready, create the MCP server with &lt;code&gt;CREATE MCP SERVER&lt;/code&gt;. List the tools you want to expose in YAML under &lt;code&gt;FROM SPECIFICATION&lt;/code&gt;. The following example exposes three tools: Cortex Analyst, Cortex Search, and SQL execution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;REPLACE&lt;/span&gt; &lt;span class="n"&gt;MCP&lt;/span&gt; &lt;span class="n"&gt;SERVER&lt;/span&gt; &lt;span class="n"&gt;MY_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MY_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MY_MCP_SERVER&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;SPECIFICATION&lt;/span&gt; &lt;span class="err"&gt;$$&lt;/span&gt;
&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Cortex&lt;/span&gt; &lt;span class="n"&gt;Analyst&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text2SQL&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;Semantic&lt;/span&gt; &lt;span class="k"&gt;View&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;"sales-analyst"&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;"CORTEX_ANALYST_MESSAGE"&lt;/span&gt;
    &lt;span class="n"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;"MY_DB.MY_SCHEMA.SALES_SEMANTIC_VIEW"&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;"Semantic view for analyzing sales data"&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;"Sales Analysis"&lt;/span&gt;

  &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Cortex&lt;/span&gt; &lt;span class="k"&gt;Search&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;search&lt;/span&gt; &lt;span class="n"&gt;unstructured&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;"manual-search"&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;"CORTEX_SEARCH_SERVICE_QUERY"&lt;/span&gt;
    &lt;span class="n"&gt;identifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;"MY_DB.MY_SCHEMA.MANUAL_SEARCH_SERVICE"&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;"Search documents such as operations manuals"&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;"Document Search"&lt;/span&gt;

  &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;SQL&lt;/span&gt; &lt;span class="n"&gt;execution&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;restricted&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="k"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;only&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="n"&gt;read_only&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;"sql_exec_tool"&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;"SYSTEM_EXECUTE_SQL"&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;"Execute read-only SQL against Snowflake"&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;"SQL Execution"&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="n"&gt;read_only&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;query_timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each tool's &lt;code&gt;description&lt;/code&gt; helps the AI agent decide which tool to use, so write it as specifically as possible. After creation, you can list your servers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt; &lt;span class="n"&gt;MCP&lt;/span&gt; &lt;span class="n"&gt;SERVERS&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="k"&gt;SCHEMA&lt;/span&gt; &lt;span class="n"&gt;MY_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MY_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The &lt;code&gt;identifier&lt;/code&gt; for a Cortex Analyst tool must point to a Semantic View (YAML-based semantic models are not supported). Also, a single MCP server can hold up to 50 tools; too many tools can reduce tool-selection accuracy, so consider splitting servers by purpose.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2. Generate a PAT and Set Up Access
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Grant Privileges to the Connecting Role
&lt;/h4&gt;

&lt;p&gt;Connections to the MCP server use role-based access control (RBAC). Note that &lt;strong&gt;the privilege to connect to the MCP server and the privileges on the objects each tool references must be granted separately&lt;/strong&gt;. Prepare a least-privilege role and grant the required privileges.&lt;/p&gt;

&lt;p&gt;First, grant the &lt;code&gt;USAGE&lt;/code&gt; needed to connect to (list and call tools on) the MCP server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;GRANT&lt;/span&gt; &lt;span class="k"&gt;USAGE&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;MCP&lt;/span&gt; &lt;span class="n"&gt;SERVER&lt;/span&gt; &lt;span class="n"&gt;MY_DB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MY_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MY_MCP_SERVER&lt;/span&gt; &lt;span class="k"&gt;TO&lt;/span&gt; &lt;span class="k"&gt;ROLE&lt;/span&gt; &lt;span class="n"&gt;MY_MCP_ROLE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition, grant the role the following privileges on the objects each exposed tool references:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Required Privilege&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cortex Search&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;USAGE&lt;/code&gt; on the target Cortex Search Service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cortex Analyst&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;SELECT&lt;/code&gt; on the target Semantic View&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cortex Agents&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;USAGE&lt;/code&gt; on the target Cortex Agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom Tools&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;USAGE&lt;/code&gt; on the target UDF / stored procedure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Even if a role can access the MCP server, it can't run a tool without privileges on the objects that tool references. Following the least-privilege principle, grant privileges only on the objects for the tools you need.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Generate the PAT
&lt;/h4&gt;

&lt;p&gt;Next, log into Snowsight and generate a PAT:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click your profile icon in the bottom left and select &lt;strong&gt;Settings&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Navigate to the &lt;strong&gt;Authentication&lt;/strong&gt; section&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;Generate New Token&lt;/strong&gt; button&lt;/li&gt;
&lt;li&gt;Set the token name and expiration&lt;/li&gt;
&lt;li&gt;For the role, select the connecting role you prepared earlier&lt;/li&gt;
&lt;li&gt;Copy the generated token&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fucc9vnvpebgoh0moqo2e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fucc9vnvpebgoh0moqo2e.png" alt="PAT Generation Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: By default, using a PAT requires the user to be subject to a network policy. Without a network policy, PAT authentication may fail. For detailed PAT requirements, please refer to the &lt;a href="https://docs.snowflake.com/en/user-guide/programmatic-access-tokens" rel="noopener noreferrer"&gt;official Snowflake documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3. Configure Cursor MCP
&lt;/h3&gt;

&lt;p&gt;Open the MCP settings in Cursor and add a new MCP server, or edit the configuration file (&lt;code&gt;~/.cursor/mcp.json&lt;/code&gt;) directly. Because the Managed MCP Server is accessed as a &lt;strong&gt;remote HTTP endpoint&lt;/strong&gt;, you specify the endpoint URL and an authentication header (PAT).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"snowflake"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://&amp;lt;orgname&amp;gt;-&amp;lt;account_name&amp;gt;.snowflakecomputing.com/api/v2/databases/&amp;lt;database&amp;gt;/schemas/&amp;lt;schema&amp;gt;/mcp-servers/&amp;lt;mcp_server_name&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer &amp;lt;the PAT you generated earlier&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The endpoint URL follows the format &lt;code&gt;https://&amp;lt;account_url&amp;gt;/api/v2/databases/{database}/schemas/{schema}/mcp-servers/{mcp_server_name}&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: In the hostname part of the URL, if your account identifier contains underscores (&lt;code&gt;_&lt;/code&gt;), replace them with hyphens (&lt;code&gt;-&lt;/code&gt;) (e.g., &lt;code&gt;ORGNAME-AAA_BBB&lt;/code&gt; → &lt;code&gt;ORGNAME-AAA-BBB&lt;/code&gt;). Leaving underscores can cause connection failures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article uses PAT authentication for simplicity, but &lt;strong&gt;OAuth 2.0&lt;/strong&gt; is recommended for production. However, the library that Cursor and Claude Desktop use internally does not support Dynamic Client Registration (DCR), so OAuth may require extra considerations. For that reason, PAT (Bearer token) is the practical connection method for Cursor. For OAuth steps, see the &lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4. Verifying Connection
&lt;/h3&gt;

&lt;p&gt;After configuration, confirm the server is enabled in Cursor's MCP settings. When successfully connected, a green indicator lights up on the MCP Server icon, and Snowflake features become available in Cursor's chat interface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi0d6kmaufx00vcd53jjc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi0d6kmaufx00vcd53jjc.png" alt="Connection Success Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Examples
&lt;/h2&gt;

&lt;p&gt;Let's explore data analysis using Snowflake Managed MCP Server from Cursor!&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 1: Natural Language Data Exploration
&lt;/h3&gt;

&lt;p&gt;Type this in Cursor's chat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List all Snowflake databases.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MCP Server automatically generates and executes appropriate SQL, returning results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SNOWFLAKE Database List

1. SALES
Database managing customer sales data

2. CUSTOMER
Database managing customer information
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI Agent generates and executes appropriate SQL within your Snowflake role's permissions and the range allowed by the SQL execution tool's configuration (such as &lt;code&gt;read_only&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 2: Searching Unstructured Data with Cortex Search
&lt;/h3&gt;

&lt;p&gt;When searching for specific information from internal documents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Summarize the operations manual.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The configured Cortex Search Service is automatically called, returning relevant information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📚 RetailCorp Operations Manual Summary
🏢 Company Philosophy
Mission: "Delivering exceptional customer experiences through innovation and quality"
Core Values:
Customer-first approach
Operational excellence
Sustainable growth
Employee empowerment
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example 3: Complex Analysis Queries
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Analyze monthly sales trends for H2 2024 and identify variation factors.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cortex Analyst interprets the Semantic View, generates an appropriate SQL query, and Cursor's AI Agent returns the result as a report:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📊 H2 2024 Sales Analysis Report

📈 Monthly Sales Trends
Month       Sales ($)   MoM Change  Features
July        152,435     -       H2 Start
August      248,291     +62.8%      Peak month
September   201,762     -18.8%      High level maintained
October     149,698     -25.8%      Sales decline
November    145,386     -2.9%       Lowest month
December    292,847     +101.3%     Holiday surge
Total       1,190,419   -       H2 Total

🔍 Key Variation Factors
1. Seasonal Factors
August: Back-to-school season peak
High-volume sales of electronics and premium products
Product lineup generating $75K per SKU

December: Holiday shopping season
Sales more than doubled from previous month
December 16 ($107,145) and 24 ($106,221) were exceptional days
Black Friday and Cyber Monday impact
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Permission Configuration Guidelines
&lt;/h3&gt;

&lt;p&gt;With Snowflake Managed MCP Server, you can operate securely by combining RBAC with per-tool settings.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Restrict to read-only&lt;/strong&gt;: Set the SQL execution tool to &lt;code&gt;read_only: true&lt;/code&gt; to limit it to reference queries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use least-privilege roles&lt;/strong&gt;: Bind the PAT to a role that only has privileges on the objects for the tools you need&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Split servers by purpose&lt;/strong&gt;: Use separate MCP servers for development and production, varying the exposed tools and privileges&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Snowflake Managed MCP Server is a &lt;strong&gt;tool that meaningfully improves the developer experience&lt;/strong&gt;. It delivers particular value through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Development Flow Integration&lt;/strong&gt;: Analyze data without leaving Cursor&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural Language Operations&lt;/strong&gt;: Execute complex analysis tasks with natural language instructions to AI Agents without writing SQL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Execution Environment&lt;/strong&gt;: Safe usage through granular permission controls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having tried it myself, I find it incredibly convenient to complete everything within Cursor without switching tools when wondering "What was that table structure?" or "I need to check sales trends for this period."&lt;/p&gt;

&lt;p&gt;While Snowflake CoWork is a powerful tool for promoting organization-wide data utilization, the Managed MCP Server integrated with daily development tools offers different value for engineers and data scientists. By choosing the right tool for each use case, we can achieve more efficient data utilization.&lt;/p&gt;

&lt;p&gt;Give Snowflake Managed MCP Server a try today!&lt;/p&gt;

&lt;h2&gt;
  
  
  Promotion
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Snowflake What's New Updates on X
&lt;/h3&gt;

&lt;p&gt;I share Snowflake What's New updates on X. Follow for the latest insights:&lt;/p&gt;

&lt;h4&gt;
  
  
  English Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_en" rel="noopener noreferrer"&gt;Snowflake What's New Bot (English Version)&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Japanese Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_jp" rel="noopener noreferrer"&gt;Snowflake's What's New Bot (Japanese Version)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Change Log
&lt;/h2&gt;

&lt;p&gt;(20250901) Initial post&lt;br&gt;
(20260702) Major revision: replaced the deprecated community MCP Server (Snowflake-Labs/mcp) with the Snowflake Managed MCP Server, reflected the Snowflake Intelligence -&amp;gt; Snowflake CoWork rename, and added coverage of the Cortex Agents MCP client capability (A2A).&lt;/p&gt;

&lt;h2&gt;
  
  
  Original Japanese Article
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://zenn.dev/tsubasa_tech/articles/70ab5fb2b5ed99" rel="noopener noreferrer"&gt;https://zenn.dev/tsubasa_tech/articles/70ab5fb2b5ed99&lt;/a&gt;&lt;/p&gt;

</description>
      <category>snowflake</category>
      <category>cursor</category>
      <category>mcp</category>
      <category>llm</category>
    </item>
    <item>
      <title>Snowflake AI_TRANSCRIBE - Transform Audio to Insights with SQL in Seconds</title>
      <dc:creator>Tsubasa Kanno</dc:creator>
      <pubDate>Sun, 10 Aug 2025 10:37:14 +0000</pubDate>
      <link>https://dev.to/tsubasa_tech/snowflake-aitranscribe-transform-audio-to-insights-with-sql-in-seconds-21j6</link>
      <guid>https://dev.to/tsubasa_tech/snowflake-aitranscribe-transform-audio-to-insights-with-sql-in-seconds-21j6</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Snowflake's unstructured data analytics has taken another leap forward! After expanding Cortex AI capabilities for images and documents throughout 2025, we can now work with &lt;strong&gt;audio data&lt;/strong&gt; directly from SQL!&lt;/p&gt;

&lt;p&gt;The new &lt;strong&gt;&lt;a href="https://docs.snowflake.com/en/sql-reference/functions/ai_transcribe" rel="noopener noreferrer"&gt;AI_TRANSCRIBE function&lt;/a&gt;&lt;/strong&gt;, released in Public Preview as part of Snowflake Cortex AISQL, transforms how we handle audio data. Customer support calls, meeting recordings, interviews - all these previously hard-to-leverage audio assets can now be transcribed with a single SQL query and combined with other AISQL functions for advanced analytics.&lt;/p&gt;

&lt;p&gt;With support for images, documents, and now audio - the three major unstructured data formats - &lt;strong&gt;Snowflake has dramatically expanded the possibilities for business data analytics&lt;/strong&gt;. Let's explore how AI_TRANSCRIBE works, its practical applications, and I'll even share a voice-enabled AI chatbot built with Streamlit in Snowflake!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: AI_TRANSCRIBE is currently in Public Preview, so features may undergo significant updates in the future.&lt;/p&gt;

&lt;p&gt;Note: This article represents my personal views and not those of Snowflake.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is AI_TRANSCRIBE?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/sql-reference/functions/ai_transcribe" rel="noopener noreferrer"&gt;AI_TRANSCRIBE&lt;/a&gt; is Snowflake Cortex AISQL's audio-to-text transcription function. Previously, leveraging audio data required external services or third-party packages, but AI_TRANSCRIBE enables &lt;strong&gt;direct audio transcription within SQL queries&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SQL Native&lt;/strong&gt;: Call directly from SQL like other AISQL functions for simple integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-language Support&lt;/strong&gt;: Supports numerous languages including English, Spanish, French, German, Chinese, and many more&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speaker Identification&lt;/strong&gt;: Distinguishes and labels multiple speakers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timestamp Generation&lt;/strong&gt;: Provides timestamps at word or speaker level&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Processing&lt;/strong&gt;: All data processing occurs within Snowflake's secure environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Part of the Cortex AISQL Family
&lt;/h3&gt;

&lt;p&gt;AI_TRANSCRIBE becomes even more powerful when combined with existing Cortex AISQL functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI_SENTIMENT&lt;/strong&gt;: Analyze sentiment in transcribed audio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI_CLASSIFY&lt;/strong&gt;: Automatically categorize audio content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI_COMPLETE&lt;/strong&gt;: Summarize or answer questions about audio content&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI_AGG&lt;/strong&gt;: Extract insights from grouped audio data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI_EMBED&lt;/strong&gt;: Vectorize audio transcripts for similarity search&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Basic Usage
&lt;/h2&gt;

&lt;p&gt;The basic syntax for AI_TRANSCRIBE is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;AI_TRANSCRIBE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;audio_file&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;options&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Parameters
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;audio_file&lt;/strong&gt;: FILE type object representing the audio file. Use &lt;code&gt;TO_FILE&lt;/code&gt; function to create a reference to staged files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;options&lt;/strong&gt;: Optional OBJECT type with the following fields:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;timestamp_granularity&lt;/code&gt;: Specifies timestamp granularity&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"word"&lt;/code&gt;: Timestamps for each word&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"speaker"&lt;/code&gt;: Timestamps and labels for each speaker&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example 1: Simple Text Transcription
&lt;/h3&gt;

&lt;p&gt;The simplest use case is converting audio to text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Convert audio file to text&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;AI_TRANSCRIBE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@audio_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'customer_call_001.wav'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"audio_duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;19.08&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hi, I'd like to inquire about the product I purchased last week. The packaging was damaged when it arrived, and I'd like to request an exchange if possible. Could you help me with this? Thank you."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Processing time for this 19-second audio file was approximately 2 seconds - impressively fast for analytics scenarios!&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 2: Word-Level Timestamps
&lt;/h3&gt;

&lt;p&gt;For detailed analysis, add word-level timestamps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Transcribe with word-level timestamps&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;AI_TRANSCRIBE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@audio_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'meeting_recording.wav'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'timestamp_granularity'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'word'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"audio_duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;19.08&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"segments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.254&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.993&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hi"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.434&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.254&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"I'd"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.514&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.434&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"like"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;more&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;segments&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hi I'd like to inquire about the product..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example 3: Speaker Identification
&lt;/h3&gt;

&lt;p&gt;For meetings or interviews with multiple speakers, use speaker identification:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Transcribe with speaker identification&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;AI_TRANSCRIBE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;TO_FILE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@audio_stage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'interview_2025.mp3'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'timestamp_granularity'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'speaker'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"audio_duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;16.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"segments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;8.461&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"speaker_label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SPEAKER_00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.511&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Good morning, thank you for joining us today. My name is Sarah."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;15.153&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"speaker_label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SPEAKER_01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;9.048&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Thank you for having me. I'm John, pleased to be here."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Good morning, thank you for joining us today. My name is Sarah. Thank you for having me. I'm John, pleased to be here."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Supported Languages and Formats
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Supported Languages
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/sql-reference/functions/ai_transcribe#usage-notes" rel="noopener noreferrer"&gt;AI_TRANSCRIBE supports an extensive list of languages&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;English, Spanish, French, German&lt;/li&gt;
&lt;li&gt;Mandarin Chinese, Cantonese&lt;/li&gt;
&lt;li&gt;Japanese, Korean&lt;/li&gt;
&lt;li&gt;Arabic, Bulgarian, Catalan&lt;/li&gt;
&lt;li&gt;Czech, Dutch, Greek&lt;/li&gt;
&lt;li&gt;Hungarian, Indonesian, Italian&lt;/li&gt;
&lt;li&gt;Latvian, Polish, Portuguese&lt;/li&gt;
&lt;li&gt;Romanian, Russian, Serbian&lt;/li&gt;
&lt;li&gt;Slovenian, Swedish, Thai&lt;/li&gt;
&lt;li&gt;Turkish, Ukrainian&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Supported Audio Formats
&lt;/h3&gt;

&lt;p&gt;Major audio formats are supported:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MP3&lt;/strong&gt;: Most common audio format&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WAV&lt;/strong&gt;: Uncompressed high-quality audio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FLAC&lt;/strong&gt;: Lossless compressed audio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ogg&lt;/strong&gt;: Open-source format&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebM&lt;/strong&gt;: Web standard format&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limitations and Considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Technical Limitations
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Limitation&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Maximum File Size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;700MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Maximum Duration (without timestamps)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;120 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Maximum Duration (with timestamps)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;60 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Concurrent Processing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Depends on account compute resources&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Usage Considerations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Audio Quality Impact&lt;/strong&gt;: Background noise or poor audio quality may reduce transcription accuracy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technical Terminology&lt;/strong&gt;: Industry-specific terms or proper nouns may not be accurately transcribed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language-Specific Behavior&lt;/strong&gt;: Some languages may have unique behaviors with word-level timestamps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Processing&lt;/strong&gt;: Currently supports batch processing only, not real-time streaming&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Regional Availability
&lt;/h3&gt;

&lt;p&gt;AI_TRANSCRIBE is natively available in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS US West 2 (Oregon)&lt;/li&gt;
&lt;li&gt;AWS US East 1 (N. Virginia)&lt;/li&gt;
&lt;li&gt;AWS EU Central 1 (Frankfurt)&lt;/li&gt;
&lt;li&gt;Azure East US 2 (Virginia)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For other regions&lt;/strong&gt;: Use &lt;strong&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/cross-region-inference" rel="noopener noreferrer"&gt;cross-region inference&lt;/a&gt;&lt;/strong&gt; to access AI_TRANSCRIBE functionality with potentially slight latency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Business Use Cases
&lt;/h2&gt;

&lt;p&gt;AI_TRANSCRIBE excels in various business scenarios:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Customer Service Quality Enhancement
&lt;/h3&gt;

&lt;p&gt;Transform call center recordings into actionable insights:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sentiment Analysis&lt;/strong&gt;: Use AI_SENTIMENT to analyze professionalism, problem resolution, and wait time perspectives&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Call Classification&lt;/strong&gt;: Automatically categorize calls as complaints, inquiries, or praise with AI_CLASSIFY&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speaker Separation&lt;/strong&gt;: Analyze operator and customer speech separately for detailed insights&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Dashboards&lt;/strong&gt;: Visualize analysis results for immediate service quality improvements&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Meeting Automation and Action Item Extraction
&lt;/h3&gt;

&lt;p&gt;Transform meeting recordings into productivity tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Meeting Minutes&lt;/strong&gt;: Instantly obtain full text from lengthy meetings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Summary Generation&lt;/strong&gt;: Use AI_COMPLETE to create concise meeting summaries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action Item Extraction&lt;/strong&gt;: Automatically identify decisions and to-dos for efficient follow-up&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Participant Analysis&lt;/strong&gt;: Track who said what using speaker identification&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Legal and Compliance Automation
&lt;/h3&gt;

&lt;p&gt;Strengthen risk management with transcribed legal conversations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complete Documentation&lt;/strong&gt;: Preserve all contract negotiations and legal discussions as text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance Risk Detection&lt;/strong&gt;: Classify conversation content by risk level using AI_CLASSIFY&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evidence Preservation&lt;/strong&gt;: Accurately record who said what and when with speaker identification and timestamps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Audit Reports&lt;/strong&gt;: Extract key points and generate audit-ready documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Education and Training Enhancement
&lt;/h3&gt;

&lt;p&gt;Maximize learning effectiveness with transcribed educational content:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lecture Archives&lt;/strong&gt;: Save course content as searchable text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subtitle Creation&lt;/strong&gt;: Add captions to video materials using word-level timestamps&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Training Feedback Analysis&lt;/strong&gt;: Identify improvement areas in training methodologies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multilingual Support&lt;/strong&gt;: Transcribe foreign language courses for easier review&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Healthcare Documentation (with proper privacy controls)
&lt;/h3&gt;

&lt;p&gt;Streamline medical documentation workflows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automated Clinical Notes&lt;/strong&gt;: Generate structured medical records from doctor-patient conversations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EHR Integration&lt;/strong&gt;: Extract relevant information for electronic health records&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multilingual Patient Care&lt;/strong&gt;: Support international patients with transcription and translation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality Assurance&lt;/strong&gt;: Analyze consultation content for healthcare improvement&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Building a Voice-Enabled AI Chatbot with Streamlit in Snowflake
&lt;/h2&gt;

&lt;p&gt;Let's build a simple voice-enabled AI chatbot using AI_TRANSCRIBE in Streamlit in Snowflake. Users can ask questions via voice, which gets transcribed and answered by AI (including the newly added OpenAI GPT-5!).&lt;/p&gt;

&lt;h3&gt;
  
  
  Application Overview
&lt;/h3&gt;

&lt;p&gt;This application provides:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Voice Recording&lt;/strong&gt;: Record audio directly from browser and save to stage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audio Transcription&lt;/strong&gt;: Convert to text using AI_TRANSCRIBE&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Response Generation&lt;/strong&gt;: Generate answers using AI_COMPLETE&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Environment Requirements
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python Version&lt;/strong&gt;: 3.11 or higher&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Additional Packages&lt;/strong&gt;: &lt;strong&gt;None required&lt;/strong&gt; (works with standard packages only)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streamlit in Snowflake&lt;/strong&gt;: Environment to create and run applications&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Regional Verification
&lt;/h4&gt;

&lt;p&gt;Ensure your region supports AI_TRANSCRIBE and AI_COMPLETE functions, or enable cross-region inference.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation Steps
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Create a New Streamlit in Snowflake App
&lt;/h4&gt;

&lt;p&gt;Navigate to 'Streamlit' in Snowsight's left pane and click '+ Streamlit' to create a new app.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Paste the Sample Code
&lt;/h4&gt;

&lt;p&gt;Copy and paste the sample code below directly into the app editor. No modifications needed - stage names are automatically configured.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Run the Application
&lt;/h4&gt;

&lt;p&gt;Click the "Run" button to launch the app. The stage will be created automatically on first run.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Use the Application
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Voice Input&lt;/strong&gt;: Click the microphone button to speak&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model Selection&lt;/strong&gt;: Choose your preferred AI model from the sidebar&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text Input&lt;/strong&gt;: Regular chat input is also available&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Sample Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;streamlit&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;snowflake.snowpark.context&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_active_session&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;snowflake.snowpark.functions&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ai_complete&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to_file&lt;/span&gt;

&lt;span class="c1"&gt;# Get Snowflake session
&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_active_session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Constants
&lt;/span&gt;&lt;span class="n"&gt;STAGE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AUDIO_TRANSCRIBE_STAGE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Page configuration
&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_page_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wide&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI Voice Chatbot&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Sidebar: Model selection
&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sidebar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;⚙️ Settings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Model options
&lt;/span&gt;&lt;span class="n"&gt;model_options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;━━━ 🟢 OpenAI ━━━&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai-gpt-oss-120b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai-gpt-oss-20b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai-gpt-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai-gpt-5-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai-gpt-5-nano&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai-gpt-5-chat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai-gpt-4.1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai-o4-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;━━━ 🔵 Claude ━━━&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-4-opus&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-4-sonnet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-3-7-sonnet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-3-5-sonnet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;━━━ 🦙 Llama ━━━&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama4-maverick&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama4-scout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3.3-70b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3.2-3b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3.2-1b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3.1-405b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3.1-70b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3.1-8b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3-70b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3-8b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;━━━ 🟣 Mistral ━━━&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mistral-large2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mistral-large&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mixtral-8x7b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mistral-7b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;━━━ ❄️ Snowflake ━━━&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;snowflake-arctic&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;snowflake-llama-3.3-70b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;snowflake-llama-3.1-405b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;━━━ 🔴 Others ━━━&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deepseek-r1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reka-core&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reka-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jamba-1.5-large&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jamba-1.5-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jamba-instruct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemma-7b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Default model setting
&lt;/span&gt;&lt;span class="n"&gt;default_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama4-maverick&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;default_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model_options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default_model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;default_model&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;model_options&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="n"&gt;llm_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sidebar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;radio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Select AI Model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model_options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;default_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;format_func&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;━━━&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  • &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Use next model if separator is selected
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;━━━&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;llm_model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;llm_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama4-maverick&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Stage setup
&lt;/span&gt;&lt;span class="nd"&gt;@st.cache_resource&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setup_stage&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Setup stage for audio file storage&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DESC STAGE &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;STAGE_NAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
            CREATE STAGE IF NOT EXISTS &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;STAGE_NAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
            ENCRYPTION = (TYPE = &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SNOWFLAKE_SSE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)
            DIRECTORY = (ENABLE = TRUE)
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;setup_stage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize session state
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat_history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract_text_from_transcript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transcript_result&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Extract text from AI_TRANSCRIBE result&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transcript_result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;transcript_result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transcript_result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;transcript_result&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;transcript_result&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;clean_ai_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Clean up AI response&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_ai_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Generate AI response&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;ai_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;clean_ai_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RESPONSE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# Display chat history
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
        &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# Voice input section
&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subheader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Voice Input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;audio_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;audio_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Click the microphone button to speak&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;📤 Send Voice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;disabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio_value&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;use_container_width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;audio_value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Upload audio file
&lt;/span&gt;            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spinner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🎤 Uploading audio...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;audio_filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audio_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%Y%m%d_%H%M%S&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nb"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.wav&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="n"&gt;audio_stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BytesIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio_value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getvalue&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;audio_stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;STAGE_NAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;audio_filename&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;auto_compress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;overwrite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Transcribe
&lt;/span&gt;            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spinner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;📝 Transcribing audio...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
                    SELECT AI_TRANSCRIBE(
                        TO_FILE(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;@&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;STAGE_NAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;audio_filename&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)
                    ) as transcript
                &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
                &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;transcribed_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extract_text_from_transcript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;TRANSCRIPT&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;transcribed_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="c1"&gt;# Add user message
&lt;/span&gt;                    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transcribed_text&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
                    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat_history&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;transcribed_text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

                    &lt;span class="c1"&gt;# Generate AI response
&lt;/span&gt;                    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spinner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🤖 AI is generating response...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                        &lt;span class="n"&gt;full_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat_history&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_ai_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;full_prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;llm_model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
                    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat_history&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

                    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rerun&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Transcription failed. Please try again.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error occurred: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Text input
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enter your message...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Add and display user message
&lt;/span&gt;    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat_history&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Generate and display AI response
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spinner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🤖 AI is generating response...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;full_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat_history&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_ai_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;full_prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;llm_model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat_history&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error occurred: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Clear chat history
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🗑️ Clear Chat History&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat_history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rerun&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Application Screenshots
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qho81aiuncz9xtd24a1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9qho81aiuncz9xtd24a1.png" alt="Voice-enabled AI Chatbot Interface" width="799" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46xzqa9nw1adt3ermx82.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46xzqa9nw1adt3ermx82.png" alt="Chat interaction with voice input" width="800" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation Highlights
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simple Implementation&lt;/strong&gt;: No additional packages required, works with standard libraries only&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audio Management&lt;/strong&gt;: Store audio data in stages and process with AI_TRANSCRIBE&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multimodal Support&lt;/strong&gt;: Supports both voice and text input&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich Model Selection&lt;/strong&gt;: Choose from latest models including OpenAI GPT-5&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cost Considerations
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/ai-audio#cost-considerations" rel="noopener noreferrer"&gt;AI_TRANSCRIBE pricing&lt;/a&gt; follows the same token-based model as other AISQL functions:&lt;/p&gt;

&lt;h3&gt;
  
  
  Token Consumption and Pricing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;50 tokens per second of audio&lt;/strong&gt;: Consistent across languages and timestamp granularities&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1 hour of audio = 180,000 tokens&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Estimated cost&lt;/strong&gt;: At 1.3 credits per million tokens and assuming $3 per credit, &lt;strong&gt;1 hour of audio processing costs approximately $0.117&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, a 60-second audio file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;60 seconds × 50 tokens = 3,000 tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Audio files under 1 minute are &lt;strong&gt;billed as 1 minute (3,000 tokens) minimum&lt;/strong&gt;. For processing many short audio files, consider batching them together for cost optimization.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For latest pricing information, refer to the &lt;a href="https://www.snowflake.com/legal-files/CreditConsumptionTable.pdf" rel="noopener noreferrer"&gt;Snowflake Service Consumption Table&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;AI_TRANSCRIBE represents a &lt;strong&gt;breakthrough function that opens the door to audio data analytics&lt;/strong&gt;. Combined with Snowflake's enhanced support for images and documents in 2025, the addition of audio - the third major unstructured data format - truly positions Snowflake as a comprehensive multimodal data platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Benefits
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Unified Data Processing&lt;/strong&gt;: Process all data types including audio within Snowflake&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AISQL Function Integration&lt;/strong&gt;: Combine with sentiment analysis, classification, summarization, and vectorization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Environment&lt;/strong&gt;: No external data movement required, maintaining governance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Development Efficiency&lt;/strong&gt;: Build audio analytics pipelines with just SQL, no third-party packages needed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From customer service and meeting transcription to healthcare documentation and legal compliance, AI_TRANSCRIBE unlocks valuable insights from previously untapped audio data. Start exploring how this function can transform your business analytics today!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you tried audio analytics in your data workflows? What use cases are you most excited about? Share your experiences in the comments below!&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Promotion
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Snowflake What's New Updates on X
&lt;/h3&gt;

&lt;p&gt;I share Snowflake What's New updates on X. Follow for the latest insights:&lt;/p&gt;

&lt;h4&gt;
  
  
  English Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_en" rel="noopener noreferrer"&gt;Snowflake What's New Bot (English Version)&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Japanese Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_jp" rel="noopener noreferrer"&gt;Snowflake's What's New Bot (Japanese Version)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Change Log
&lt;/h2&gt;

&lt;p&gt;(20250810) Initial post&lt;/p&gt;

&lt;h2&gt;
  
  
  Original Japanese Article
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://zenn.dev/tsubasa_tech/articles/65e96e2bd257ec" rel="noopener noreferrer"&gt;https://zenn.dev/tsubasa_tech/articles/65e96e2bd257ec&lt;/a&gt;&lt;/p&gt;

</description>
      <category>snowflake</category>
      <category>sql</category>
      <category>ai</category>
      <category>llm</category>
    </item>
    <item>
      <title>Snowflake AI_SENTIMENT - Industry-Leading Sentiment Analysis with 0.92 Accuracy and Multi-Aspect Support</title>
      <dc:creator>Tsubasa Kanno</dc:creator>
      <pubDate>Sun, 03 Aug 2025 09:48:49 +0000</pubDate>
      <link>https://dev.to/tsubasa_tech/snowflake-aisentiment-industry-leading-sentiment-analysis-with-092-accuracy-and-multi-aspect-49k3</link>
      <guid>https://dev.to/tsubasa_tech/snowflake-aisentiment-industry-leading-sentiment-analysis-with-092-accuracy-and-multi-aspect-49k3</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Snowflake has released the new &lt;strong&gt;&lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/ai-sentiment" rel="noopener noreferrer"&gt;AI_SENTIMENT function&lt;/a&gt;&lt;/strong&gt; as part of Cortex AISQL, becoming GA on July 25, 2025! This represents a &lt;strong&gt;significant accuracy improvement over the previous ENTITY_SENTIMENT function&lt;/strong&gt;, enabling state-of-the-art sentiment analysis directly from SQL within Snowflake.&lt;/p&gt;

&lt;p&gt;AI_SENTIMENT goes beyond simple "positive/negative" classifications to support &lt;strong&gt;aspect-based sentiment analysis&lt;/strong&gt;. For instance, with restaurant reviews, you can analyze sentiment for specific aspects like "food quality," "pricing," and "service" separately, providing much deeper insights into customer feedback.&lt;/p&gt;

&lt;p&gt;In this article, I'll walk through the practical value and implementation approaches for the AI_SENTIMENT function, including real-world testing results that demonstrate its capabilities across different scenarios.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: This article represents my personal views and not those of Snowflake.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is AI_SENTIMENT?
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://docs.snowflake.com/en/user-guide/snowflake-cortex/ai-sentiment" rel="noopener noreferrer"&gt;AI_SENTIMENT function&lt;/a&gt; is Snowflake Cortex AISQL's latest sentiment analysis function. Compared to the previous ENTITY_SENTIMENT function, it delivers &lt;strong&gt;significantly improved accuracy&lt;/strong&gt; along with &lt;strong&gt;advanced features like mixed sentiment detection&lt;/strong&gt; and &lt;strong&gt;nuanced expression understanding&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Industry-leading accuracy&lt;/strong&gt;: Achieves 0.92 accuracy in aspect-based sentiment analysis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich sentiment classification&lt;/strong&gt;: Five-level detailed analysis including positive, negative, neutral, mixed, and unknown&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multilingual support&lt;/strong&gt;: Native support for 6 languages including English, French, German, Hindi, Italian, and Portuguese&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aspect-based analysis&lt;/strong&gt;: Simultaneous analysis of up to 10 different aspects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced context understanding&lt;/strong&gt;: Accurately interprets implicit expressions and figurative language&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Benchmark Performance
&lt;/h3&gt;

&lt;p&gt;AI_SENTIMENT demonstrates superior performance compared to major LLMs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Aspect-based sentiment accuracy (ABSA-mix)&lt;/th&gt;
&lt;th&gt;Aspect-based sentiment accuracy (ABSA-multilingual)&lt;/th&gt;
&lt;th&gt;Overall sentiment accuracy&lt;/th&gt;
&lt;th&gt;Overall sentiment accuracy (multilingual)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AI_SENTIMENT&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.92&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.81&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.83&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.83&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;claude-4-sonnet&lt;/td&gt;
&lt;td&gt;0.84&lt;/td&gt;
&lt;td&gt;0.79&lt;/td&gt;
&lt;td&gt;0.75&lt;/td&gt;
&lt;td&gt;0.82&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mistral-large2&lt;/td&gt;
&lt;td&gt;0.83&lt;/td&gt;
&lt;td&gt;0.80&lt;/td&gt;
&lt;td&gt;0.77&lt;/td&gt;
&lt;td&gt;0.78&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;openai-gpt-4.1&lt;/td&gt;
&lt;td&gt;0.83&lt;/td&gt;
&lt;td&gt;0.73&lt;/td&gt;
&lt;td&gt;0.80&lt;/td&gt;
&lt;td&gt;0.78&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;llama4-scout&lt;/td&gt;
&lt;td&gt;0.82&lt;/td&gt;
&lt;td&gt;0.79&lt;/td&gt;
&lt;td&gt;0.71&lt;/td&gt;
&lt;td&gt;0.76&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;llama3.3-70b&lt;/td&gt;
&lt;td&gt;0.82&lt;/td&gt;
&lt;td&gt;0.79&lt;/td&gt;
&lt;td&gt;0.71&lt;/td&gt;
&lt;td&gt;0.76&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS DetectSentiment&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;0.62&lt;/td&gt;
&lt;td&gt;0.64&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This high accuracy makes AI_SENTIMENT reliable for business-critical sentiment analysis tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Usage
&lt;/h2&gt;

&lt;p&gt;AI_SENTIMENT supports two primary usage patterns:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Overall Sentiment Analysis
&lt;/h3&gt;

&lt;p&gt;The simplest approach analyzes overall text sentiment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;AI_SENTIMENT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Text content'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Aspect-Based Sentiment Analysis
&lt;/h3&gt;

&lt;p&gt;Analyze sentiment for specific aspects individually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;AI_SENTIMENT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Text content'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Aspect1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Aspect2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can specify up to 10 aspects, with each aspect limited to 30 characters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing with Unsupported Languages
&lt;/h2&gt;

&lt;p&gt;While Japanese isn't officially supported, I tested AI_SENTIMENT's behavior with non-supported languages to understand its capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test: English Aspect Labels
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;AI_SENTIMENT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'This restaurant&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;s omelet rice is quite delicious. The eggs were freshly collected this morning. However, it&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;s quite expensive compared to nearby stores.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Price'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Taste'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Freshness'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"categories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"overall"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"sentiment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mixed"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Freshness"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"sentiment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"positive"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Price"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"sentiment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"negative"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Taste"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"sentiment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"positive"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results show accurate understanding of the content with proper sentiment classification:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;overall&lt;/strong&gt;: mixed (complex emotions)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Freshness&lt;/strong&gt;: positive (freshness praised)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price&lt;/strong&gt;: negative (price criticism)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Taste&lt;/strong&gt;: positive (taste praised)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Insights
&lt;/h3&gt;

&lt;p&gt;This testing revealed that for unsupported languages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Content understanding&lt;/strong&gt;: Text content can be understood with reasonable accuracy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aspect constraints&lt;/strong&gt;: Aspects should be specified in supported languages (English, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practical workaround&lt;/strong&gt;: Use English aspect labels even for content in unsupported languages&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Supported Languages
&lt;/h2&gt;

&lt;p&gt;AI_SENTIMENT natively supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;English&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;French&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;German&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hindi&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Italian&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Portuguese&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While other languages aren't officially supported, the testing above shows that content understanding may work for additional languages when using supported-language aspect labels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Business Use Cases
&lt;/h2&gt;

&lt;p&gt;AI_SENTIMENT excels in various business scenarios:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Social Media Monitoring
&lt;/h3&gt;

&lt;p&gt;Monitor brand and product mentions across social platforms, tracking sentiment changes in real-time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Social media analysis&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; 
    &lt;span class="n"&gt;post_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;AI_SENTIMENT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Brand'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Product'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Service'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;sentiment_analysis&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;social_media_posts&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;brand_mention&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;post_date&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Product Review Analysis
&lt;/h3&gt;

&lt;p&gt;Analyze e-commerce reviews across multiple dimensions to identify improvement areas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Product review analysis&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; 
    &lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;AI_SENTIMENT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;review_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Quality'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Price'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Delivery'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Customer_Service'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;review_sentiment&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;product_reviews&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;review_date&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2025-01-01'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Customer Support Analysis
&lt;/h3&gt;

&lt;p&gt;Measure customer satisfaction from support tickets and chat logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Customer support sentiment analysis&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; 
    &lt;span class="n"&gt;ticket_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;support_category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;AI_SENTIMENT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Response_Time'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Solution_Quality'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Agent_Helpfulness'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;support_sentiment&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;support_tickets&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'closed'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Employee Engagement Analysis
&lt;/h3&gt;

&lt;p&gt;Assess organizational health through employee surveys and feedback:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Employee satisfaction analysis&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; 
    &lt;span class="n"&gt;department&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;AI_SENTIMENT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;feedback_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Work_Environment'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Management'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Career_Growth'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Compensation'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;employee_sentiment&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;employee_feedback&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;survey_date&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2025-01-01'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sentiment Classification Details
&lt;/h2&gt;

&lt;p&gt;AI_SENTIMENT returns these sentiment classifications:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Classification&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;positive&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Clearly positive sentiment&lt;/td&gt;
&lt;td&gt;"Excellent quality product"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;negative&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Clearly negative sentiment&lt;/td&gt;
&lt;td&gt;"Completely disappointing experience"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;neutral&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Neutral sentiment&lt;/td&gt;
&lt;td&gt;"Standard product as expected"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;mixed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Both positive and negative elements&lt;/td&gt;
&lt;td&gt;"Good quality but overpriced"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;unknown&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cannot determine sentiment&lt;/td&gt;
&lt;td&gt;When specified aspect doesn't exist&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;mixed&lt;/strong&gt; classification is particularly valuable as it accurately captures complex emotions that contain both positive and negative elements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations and Considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Technical Limitations
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Limitation&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Context Window&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2,048 tokens (approximately 1,600 words)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Maximum Aspects&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Up to 10 aspects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Aspect Length&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;30 characters maximum per aspect&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Supported Languages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;6 languages (others not officially supported)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Usage Guidelines
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Long text handling&lt;/strong&gt;: Split content exceeding 2,048 tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aspect selection&lt;/strong&gt;: Choose business-relevant aspects carefully, preferably in supported languages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result validation&lt;/strong&gt;: Use AI results as reference; verify critical decisions manually&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cost Information
&lt;/h2&gt;

&lt;p&gt;AI_SENTIMENT has a credit consumption rate of &lt;strong&gt;1.6 credits per 1 million tokens&lt;/strong&gt;, making it quite cost-effective for sentiment analysis workloads. For detailed credit consumption information, refer to the &lt;a href="https://www.snowflake.com/legal-files/CreditConsumptionTable.pdf" rel="noopener noreferrer"&gt;Snowflake Credit Consumption Table&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cost Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No data movement&lt;/strong&gt;: All processing occurs within Snowflake's secure environment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No infrastructure required&lt;/strong&gt;: No dedicated AI infrastructure setup needed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated operations&lt;/strong&gt;: Easy automation through SQL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pay-per-use&lt;/strong&gt;: Only pay for actual usage, avoiding waste&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;AI_SENTIMENT represents a &lt;strong&gt;breakthrough function that combines sentiment analysis accuracy with business applicability&lt;/strong&gt;. It delivers exceptional value through:&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Advantages
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Industry-leading accuracy&lt;/strong&gt;: 0.92 accuracy in aspect-based sentiment analysis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex emotion understanding&lt;/strong&gt;: Accurate analysis of mixed sentiments and implicit expressions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQL integration&lt;/strong&gt;: Easy integration into existing data pipelines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost efficiency&lt;/strong&gt;: Significant cost savings compared to external services&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Recommendations for Global Usage
&lt;/h3&gt;

&lt;p&gt;Based on testing results, even for unsupported languages, practical usage is possible with these approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use English aspect labels&lt;/strong&gt; (Price, Quality, Service, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content understanding works across languages&lt;/strong&gt; (though not officially supported)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I encourage you to explore AI_SENTIMENT for customer voice analysis, brand monitoring, employee satisfaction surveys, and other business scenarios to enable secure and fast data-driven decision making!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you tried implementing sentiment analysis in your data workflows? Share your experiences in the comments below!&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Promotion
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Snowflake What's New Updates on X
&lt;/h3&gt;

&lt;p&gt;I share Snowflake What's New updates on X. Follow for the latest insights:&lt;/p&gt;

&lt;h4&gt;
  
  
  English Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_en" rel="noopener noreferrer"&gt;Snowflake What's New Bot (English Version)&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Japanese Version
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://x.com/snow_new_jp" rel="noopener noreferrer"&gt;Snowflake's What's New Bot (Japanese Version)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Change Log
&lt;/h2&gt;

&lt;p&gt;(20250803) Initial post&lt;/p&gt;

&lt;h2&gt;
  
  
  Original Japanese Article
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://zenn.dev/tsubasa_tech/articles/972c86d2ac2702" rel="noopener noreferrer"&gt;https://zenn.dev/tsubasa_tech/articles/972c86d2ac2702&lt;/a&gt;&lt;/p&gt;

</description>
      <category>snowflake</category>
      <category>sentiment</category>
      <category>llm</category>
      <category>analytics</category>
    </item>
  </channel>
</rss>
