{"slug": "agentic-ai-in-action-part-28-a-geospatial-store-intelligence-agent-in-snowflake", "title": "Agentic AI in Action — Part 28 — A Geospatial Store Intelligence Agent in Snowflake", "summary": "Snowflake Inc. demonstrated a geospatial store intelligence agent in Snowflake Notebooks that lets retail managers query store footfall and locations in plain English, using Cortex Analyst with Semantic Views for natural language-to-SQL translation and native geography functions like ST_DWITHIN for radius queries. The notebook, part of the 'Agentic AI in Action' series, generates roughly eighty synthetic stores across New York, Chicago, Austin, and Seattle, with a STORE_LOCATIONS table and a STORE_SEMANTIC_VIEW exposing city, store_name, avg_footfall, and store_count metrics, while deliberately excluding latitude and longitude from the semantic layer to keep spatial math in native SQL.", "body_md": "This blog walks through a store intelligence notebook, plain English questions answered through Cortex Analyst and Semantic Views, store locations plotted through native geography functions.\n\nThe use case is straightforward. A retail chain wants store managers and regional planners to ask plain English questions about footfall and location, things like *“show me stores in Chicago with footfall below 500 last month”*, and get back both the matching rows and a rendered map. The pieces that make this possible, a Semantic View for Cortex Analyst, native geography functions for radius queries, and simple, popular Python packages like matplotlib for the visual layer, already exist inside Snowflake Notebooks. Nothing needs to be stitched together from outside services, and nothing fancy is required to render the output either.\n\nAlong the way this also surfaces a useful design pattern. Cortex Analyst is genuinely good at turning language into SQL over the dimensions and metrics you have exposed to it, and pairing it with native SQL for spatial math gives each piece the job it is best suited for. That division, natural language for attribute filtering, native SQL for geometry, is what it actually comes down to.\n\nA single STORE_LOCATIONS table holds each store's id, city, footfall for the last month, and a GEOGRAPHY column built from latitude and longitude. A Semantic View sits on top of this table and exposes the dimensions and metrics Cortex Analyst needs to translate a natural language question into SQL. The distance filtering itself uses Snowflake's native ST_DWITHIN function against the geography column, so radius queries run as ordinary SQL rather than anything bolted on.\n\nThe notebook is built around four US cities, New York, Chicago, Austin, and Seattle, with roughly eighty synthetic stores jittered around each city center so the points land in realistic locations without needing a real estate dataset.\n\nLet’s begin by creating dedicated database and schema.\n\nWe will generate roughly eighty stores spread across four US cities, New York, Chicago, Austin, and Seattle, each with a footfall reading for the last month. Coordinates are jittered around each city center so the points fall in relatively realistic locations without needing a real estate dataset.\n\nEach city gets twenty stores with footfall figures spread widely enough that a “below 500” style filter returns a meaningful subset rather than an empty result or the whole table.\n\nSemantic Views give Cortex Analyst a governed, business friendly layer over raw tables, defining dimensions, metrics, and join logic once so that natural language questions resolve consistently instead of relying on the model to guess at SQL each time.\n\n*(For details on how semantic views work, please refer to* *Part 23* *of my Agentic AI in Action series).*\n\nIn this cell, STORE_SEMANTIC_VIEW is created over the STORE_LOCATIONS table, keyed on store_id. It exposes city and store_name as dimensions, so questions can be sliced by location or by individual store, and defines two metrics, *avg_footfall* as the average of footfall_last_month and *store_count* as a count of store_id. When Cortex Analyst answers a question like which city has the highest average footfall, it resolves it against these definitions rather than improvising the aggregation, and the same city and footfall groupings carry through cleanly into the pydeck map later in the notebook.\n\nThis is deliberately narrow. Cortex Analyst only needs enough structure to translate “stores in Chicago with low footfall” into a WHERE clause and an aggregation. Notice what’s missing, latitude, longitude, and anything geography-flavored aren’t in here at all. That’s on purpose, and it matters for what comes next.\n\nCortex Analyst is scoped to whatever the Semantic View exposes, city and footfall in this case, so questions about attributes and aggregates go to it directly. Distance is a different kind of question, geometry rather than filtering, and Snowflake already has native functions for that. The cleaner pattern keeps the two separate. Cortex Analyst handles “which stores, filtered by which attributes,” and a direct query against the GEOGRAPHY column built in Cell 2 handles “which stores, within this radius.”\n\nThis runs on its own using Snowflake’s native ST_DWITHIN function whenever the question genuinely needs distance math, radius searches, nearest neighbor lookups, and so on. Cortex Analyst picks up from there for the attribute filtering that follows.\n\nRunning this against the actual data returns all 20 Chicago stores, footfall ranging from 233 up to 1,379. With the jitter radius used to scatter stores around each city center, a 25 km search from downtown Chicago comfortably covers every store tagged to that city, which is a useful sanity check in itself, the geometry is doing exactly what it should.\n\nThis cell creates a reusable Python function called ask_cortex_analyst() to send a natural-language question to Snowflake Cortex Analyst. The function takes the user’s question and, by default, the semantic view GEO_DEMO.RETAIL.STORE_SEMANTIC_VIEW, which we just created. It then obtains the Snowflake connection, authentication token, and account host from the existing Snowpark session and constructs the Cortex Analyst REST API endpoint. The question and semantic view are packaged into a JSON payload and sent to the API using an HTTP POST request, with the Snowflake token included for authentication. The function waits up to 60 seconds for a response and checks the HTTP status code to determine whether the request was successful. If an error occurs, it prints the status and part of the error response and raises an exception; otherwise, it converts the API response from JSON into a Python object and returns it. In short, the cell acts as the bridge between a Python notebook and Cortex Analyst, allowing a user to ask business questions in natural language and receive Cortex Analyst’s response programmatically.\n\nAt the bottom of the cell is the question:\n\nThe question is scoped to city and footfall, since radius search belongs to the native SQL step above rather than to Cortex Analyst. That’s why the phrasing is “stores in Chicago” instead of “stores within 25 km,” and Cortex Analyst returns a clean SQL statement matching exactly that scope. In other words, this demonstrates how you can use Cortex Analyst not just to answer a business question, but to retrieve and inspect the SQL that it generated to answer that question.\n\nThat’s the actual SQL Cortex Analyst generated for the question, wrapped in a CTE, filtered on CITY and FOOTFALL_LAST_MONTH, and ordered descending. There are no coordinates or distance calculations involved. It stays exactly within the scope supported by the Semantic View.\n\nRunning it returns five stores as seen above.\n\nOne more design detail before the map renders. The Semantic View scopes Cortex Analyst’s output to STORE_ID, STORE_NAME, CITY, and FOOTFALL_LAST_MONTH, the dimensions and metrics defined for it, so coordinates come back in through a join against STORE_LOCATIONS. This is a reasonable pattern in general, the app layer around Cortex Analyst enriches its output with anything outside the semantic model rather than assuming the result already carries everything a downstream step needs.\n\nStore 24 sits well north of the other four, at the edge of the jittered coordinate spread, while the rest cluster closer to the city center. This is the payoff. The same question that started as a plain English sentence ends up as pins on a map, and the whole round trip, natural language in, SQL generated, query executed, coordinates joined back in, result rendered, happens inside one Notebook session using only pandas and matplotlib, both of which ship with every Snowflake Notebook by default. If your environment has streamlit and pydeck available through the Packages selector, the same map_df drops into a pdk.Layer and st.pydeck_chart for a more polished interactive map, but the matplotlib version is the one guaranteed to run without any package configuration.\n\nIndividual pins work well for a specific question, but a regional planner usually wants a rollup by territory rather than a list of points. Bucketing stores into H3 cells and summarizing average footfall per cell gives that view.\n\nH3 cells are Uber’s hexagonal grid system for dividing the map into uniform regions, and H3_POINT_TO_CELL_STRING(location, resolution) is Snowflake’s native function for looking up which hexagon a given point falls into, returning that hexagon’s ID as a string so stores in the same region can be grouped together with GROUP BY. That string is just an identifier, not a shape, so it’s enough to group and aggregate footfall by territory, but drawing the actual hexagon boundaries on a map needs geometry that pydeck’s H3HexagonLayer normally supplies. (Since this notebook stays dependency-light, the output here is a table and bar chart of cell IDs and their average footfall rather than rendered hexagons).\n\nWe will go ahead and plot a bar chart summary of footfall by H3 territory.\n\nEach of these top cells holds exactly one store, which tracks with H3 resolution 7 at this scale, eighty stores spread across four metro areas, most stores land in their own cell. A coarser resolution, say H3_POINT_TO_CELL_STRING(LOCATION, 5), groups more stores per cell for a broader density read. This step turns “find nearby stores” into “identify underserved territories,” which tends to land better with a business audience than a list of individual points. (If pydeck is available in your environment, the same h3_df drops into an H3HexagonLayer for an actual hexagon map instead of a bar chart).\n\nWhat matters here isn’t the map, it’s where each piece of the work actually happens.\n\nCortex Analyst handles the part it’s built for, turning a plain English question into SQL over a defined set of dimensions and metrics, and native SQL and Python handle the rest, geometry, joins, and rendering. There is no external service in the loop and no data leaves the account. Swap the underlying table and Semantic View metrics, warehouse footfall for logistics, branch traffic for banking, and the same pattern carries over with the Cortex Analyst and rendering cells unchanged.\n\nThe notebook for this blog can be accessed [here.](https://github.com/Krishsriniv/geospatial-store-intelligence-snowflake)\n\n*I share hands-on, implementation-focused perspectives on Generative & Agentic AI, LLMs, Snowflake and Cortex AI, translating advanced capabilities into practical, real-world analytics use cases. Do follow me on* *LinkedIn* *and* *Medium* *for more such insights.*\n\n[Agentic AI in Action — Part 28 — A Geospatial Store Intelligence Agent in Snowflake](https://pub.towardsai.net/agentic-ai-in-action-part-28-a-geospatial-store-intelligence-agent-in-snowflake-d4facffe7a5f) was originally published in [Towards AI](https://pub.towardsai.net) on Medium, where people are continuing the conversation by highlighting and responding to this story.", "url": "https://wpnews.pro/news/agentic-ai-in-action-part-28-a-geospatial-store-intelligence-agent-in-snowflake", "canonical_source": "https://pub.towardsai.net/agentic-ai-in-action-part-28-a-geospatial-store-intelligence-agent-in-snowflake-d4facffe7a5f?source=rss----98111c9905da---4", "published_at": "2026-09-08 05:32:30+00:00", "updated_at": "2026-09-08 06:01:42.073234+00:00", "lang": "en", "topics": ["artificial-intelligence", "natural-language-processing", "ai-tools", "ai-infrastructure"], "entities": ["Snowflake Inc.", "Cortex Analyst", "Semantic Views", "Snowflake Notebooks", "ST_DWITHIN"], "alternates": {"html": "https://wpnews.pro/news/agentic-ai-in-action-part-28-a-geospatial-store-intelligence-agent-in-snowflake", "markdown": "https://wpnews.pro/news/agentic-ai-in-action-part-28-a-geospatial-store-intelligence-agent-in-snowflake.md", "text": "https://wpnews.pro/news/agentic-ai-in-action-part-28-a-geospatial-store-intelligence-agent-in-snowflake.txt", "jsonld": "https://wpnews.pro/news/agentic-ai-in-action-part-28-a-geospatial-store-intelligence-agent-in-snowflake.jsonld"}}