The Problem We All Face (And Nobody Talks About)

You know that feeling when someone asks “What did we decide about the API redesign?” and you’re frantically scrolling through three weeks of meeting notes trying to find that one conversation?

Or when your manager asks “What action items were assigned to the engineering team last month?” and you realize those decisions are buried across 47 different meeting transcripts scattered in Google Docs, Notion, and email threads?

Yeah, we’ve all been there.

Here’s the thing: companies have meetings. Lots of them. And every single meeting contains valuable information—decisions made, problems discussed, action items assigned, ideas shared. But all that knowledge just… disappears into the void of meeting notes that nobody reads again.

Until now.

What if we could build a system where you just ask “What did we decide about the database migration?” and get an instant answer with exact sources? Not some generic corporate search that returns 500 irrelevant documents, but an actual intelligent assistant that understands context.

That’s exactly what we can build with Snowflake Cortex. And honestly? It’s simpler than you think.

What We’re Building (In Plain English)

Before diving into code, let’s understand what a Meeting Notes RAG actually does:

RAG = Retrieval Augmented Generation

Think of it like this:

  1. Store all your meeting notes in Snowflake
  2. Convert them into a format that AI can search semantically (not just keyword matching)
  3. When someone asks a question, find the most relevant meeting notes
  4. Use an AI model to generate an intelligent answer based on those notes
  5. Show sources so people can verify information

Real example:

  • Question: “Why did we choose PostgreSQL over MySQL?”
  • System finds: Engineering meeting from March 15th discussing database options
  • Answer: “According to the March 15th engineering meeting, the team chose PostgreSQL primarily because of better JSON support and more robust handling of concurrent writes. Sarah from backend also mentioned PostgreSQL’s superior full-text search capabilities.”

See? Not just “here are 50 documents mentioning PostgreSQL” but an actual synthesized answer with context.

Why Snowflake for This?

You might be thinking: “Can’t I just use ChatGPT with my notes?”

Sure, but here’s why Snowflake is better for this:

  1. Security: Meeting notes contain sensitive information. With Snowflake, data never leaves your secure environment
  2. Scale: Got 10,000 meetings? No problem. Snowflake handles it easily
  3. Integration: Your meeting data might already be in Snowflake, or easily pipeable
  4. Cortex Search: Built-in vector search—no need for external vector databases
  5. SQL interface: Everyone on your team can query it without learning new tools
  6. Cost: Pay only for what you use, no separate infrastructure

Plus, there’s something elegant about keeping everything in one place.

The Architecture (Keep It Simple)

Here’s how we can structure this:

SQL 11 lines

SQL example — read the query, then copy it into your warehouse.

Meeting Notes (Zoom, Teams, Google Meet transcripts)                    ↓        Load into Snowflake table                    ↓          Split into chunks                    ↓      Generate vector embeddings                    ↓     Create Cortex Search Service                    ↓User asks question → Find relevant chunks → Generate answer with sources

No microservices, no Kubernetes, no headaches. Just Snowflake doing what it does best.

Step 1: Setting Up the Foundation

First, let’s create a proper database structure. We’re organizing this so it’s maintainable and scalable.

Step 1: Setting Up the Foundation: excerpt of this SQL example. This is a shortened excerpt of a 21-line script.
-- Create dedicated database for meeting intelligence
CREATE DATABASE IF NOT EXISTS meeting_intelligence;
USE DATABASE meeting_intelligence;

-- Create schema for organization
CREATE SCHEMA IF NOT EXISTS meetings;
USE SCHEMA meetings;

…

The remaining 13 lines stay in the interactive article so this page remains a written walkthrough rather than a raw SQL dump.

Nothing fancy here—just clean organization. A SMALL warehouse is perfectly fine for this; we can always scale if needed.

Step 2: Designing the Meeting Notes Table

This is where thoughtful schema design matters. We want to capture not just the content, but useful metadata.

Step 2: Designing the Meeting Notes Table: excerpt of this SQL example. This is a shortened excerpt of a 144-line script.
-- Main table for meeting transcripts
CREATE OR REPLACE TABLE meeting_transcripts (
    meeting_id STRING PRIMARY KEY,
    meeting_title STRING NOT NULL,
    meeting_date TIMESTAMP_LTZ NOT NULL,
    meeting_type STRING, -- 'standup', 'planning', 'retrospective', 'one-on-one'
    attendees ARRAY,
    duration_minutes INTEGER,
…

The remaining 136 lines stay in the interactive article so this page remains a written walkthrough rather than a raw SQL dump.

Notice how we’re capturing structured data (action items, decisions, topics) alongside unstructured text. This dual approach gives us flexibility in how we search and analyze later.

Step 3: Chunking Strategy for Meetings

Unlike documentation, meetings have natural structure—they flow chronologically. We can chunk intelligently based on topics or time segments.

Step 3: Chunking Strategy for Meetings: excerpt of this SQL example. This is a shortened excerpt of a 251-line script.

-- Table for meeting chunks (optimized for retrieval)
CREATE OR REPLACE TABLE meeting_chunks (
    chunk_id STRING PRIMARY KEY,
    meeting_id STRING,
    chunk_index INTEGER,
    chunk_text STRING,
    chunk_size INTEGER,
…

The remaining 243 lines stay in the interactive article so this page remains a written walkthrough rather than a raw SQL dump.

For production systems, we might want to split longer meetings into smaller chunks—maybe 3-5 minute segments or topic-based splits. But for this example, keeping each meeting as one chunk works well since our sample meetings are relatively short.

Step 4: Generate Vector Embeddings

This is where the magic starts. We’re converting text into mathematical vectors that capture semantic meaning.

Step 4: Generate Vector Embeddings: excerpt of this SQL example. This is a shortened excerpt of a 16-line script.
-- Generate embeddings using Snowflake Cortex
UPDATE meeting_chunks
SET chunk_embedding = SNOWFLAKE.CORTEX.EMBED_TEXT_1024(
    'snowflake-arctic-embed-l',
    chunk_text
);

-- Verify embeddings were created
…

The remaining 8 lines stay in the interactive article so this page remains a written walkthrough rather than a raw SQL dump.

The snowflake-arctic-embed-l model creates 1024-dimensional vectors. These vectors position similar concepts close together in mathematical space—so “API security” and “authentication” end up near each other, even without sharing exact words.

Step 5: Create Cortex Search Service

Now we set up the search infrastructure. This is what makes semantic search possible.

Step 5: Create Cortex Search Service: excerpt of this SQL example. This is a shortened excerpt of a 25-line script.
-- Create Cortex Search Service for meeting notes
CREATE OR REPLACE CORTEX SEARCH SERVICE meeting_search_service
ON chunk_text
WAREHOUSE = meeting_rag_wh
TARGET_LAG = '1 minute'
AS (
    SELECT
        chunk_id,
…

The remaining 17 lines stay in the interactive article so this page remains a written walkthrough rather than a raw SQL dump.

The TARGET_LAG of 1 minute means new meetings get indexed within a minute. For most use cases, this is plenty fast.

Step 6: Building the Query Interface

Now for the exciting part—creating a function that actually answers questions intelligently.

Step 6: Building the Query Interface: excerpt of this shell example. This is a shortened excerpt of a 73-line script.
-- Create the main RAG function
CREATE OR REPLACE FUNCTION ask_meeting_assistant(question STRING)
RETURNS VARIANT
LANGUAGE SQL
AS
$$
    WITH relevant_meetings AS (
        -- Step 1: Find most relevant meeting chunks
…

The remaining 65 lines stay in the interactive article so this page remains a written walkthrough rather than a raw shell dump.

Let’s break down what this function does:

  1. Searches for the 3 most relevant meeting chunks semantically
  2. Builds context by combining those meetings with metadata
  3. Generates answer using an LLM that has been given specific instructions
  4. Returns structured output with answer + sources

The key is that the LLM only uses information from our meetings—it doesn’t make things up or use its general knowledge.

Step 7: Real-World Testing

Let’s ask questions that we’d actually ask in real life:

Step 7: Real-World Testing: excerpt of this SQL example. This is a shortened excerpt of a 35-line script.
-- Question 1: Specific decision
SELECT 
    result:answer::STRING as answer
FROM (
    SELECT ask_meeting_assistant('Why did we choose PostgreSQL over MySQL?') as result
);

-- Question 2: Action items
…

The remaining 27 lines stay in the interactive article so this page remains a written walkthrough rather than a raw SQL dump.

What’s impressive is how the system can connect information across multiple meetings. If you ask “What’s blocking the product launch?”, it can pull from the security meeting AND the planning meeting to give a complete answer.

Step 8: Adding Specialized Query Functions

Different people need different things from meeting notes. Let’s create targeted functions:

Step 8: Adding Specialized Query Functions: excerpt of this shell example. This is a shortened excerpt of a 75-line script.
-- Function 1: Find action items for a person
CREATE OR REPLACE FUNCTION get_action_items_for(person_name STRING)
RETURNS TABLE (
    meeting_title STRING,
    meeting_date TIMESTAMP_LTZ,
    action_item STRING
)
AS
…

The remaining 67 lines stay in the interactive article so this page remains a written walkthrough rather than a raw shell dump.

These specialized functions give your team multiple ways to interact with meeting data—some people want natural language, others want structured queries.

Step 9: Building a Conversation History Table

To make this truly useful, we should track what people ask and whether answers were helpful:

Step 9: Building a Conversation History Table: excerpt of this shell example. This is a shortened excerpt of a 60-line script.
-- Track queries and feedback
CREATE OR REPLACE TABLE meeting_assistant_logs (
    log_id INTEGER AUTOINCREMENT,
    user_name STRING,
    question STRING,
    answer VARIANT,
    sources_used ARRAY,
    helpful_vote INTEGER, -- 1 = helpful, -1 = not helpful, NULL = no vote yet
…

The remaining 52 lines stay in the interactive article so this page remains a written walkthrough rather than a raw shell dump.

This logging is crucial for two reasons:

  1. Accountability: Know who’s using the system and what they’re asking
  2. Improvement: See which queries return unhelpful answers and refine

Step 10: Analytics Dashboard Queries

Let’s create queries that help us understand usage patterns:

Step 10: Analytics Dashboard Queries: excerpt of this SQL example. This is a shortened excerpt of a 41-line script.
-- Most common topics people ask about
SELECT 
    -- Extract key nouns/topics from questions
    LOWER(REGEXP_SUBSTR(question, '\\b(database|API|security|migration|dashboard|launch|PostgreSQL|Redis|cache|decision|action)\\b', 1, 1, 'i')) as topic,
    COUNT(*) as question_count
FROM meeting_assistant_logs
WHERE topic IS NOT NULL
GROUP BY topic
…

The remaining 33 lines stay in the interactive article so this page remains a written walkthrough rather than a raw SQL dump.

These analytics tell us what’s working and what needs improvement. If certain types of questions consistently get negative feedback, we know where to focus our refinement efforts.

Step 11: Automating Meeting Ingestion

In production, we’d want new meetings to automatically flow into the system. Here’s how that might look:

Step 11: Automating Meeting Ingestion: excerpt of this SQL example. This is a shortened excerpt of a 51-line script.
-- Create stage for incoming meeting transcripts
CREATE OR REPLACE STAGE meeting_uploads
    FILE_FORMAT = (TYPE = 'JSON');

-- Create stream to detect new meetings
CREATE OR REPLACE STREAM new_meetings_stream
ON TABLE meeting_transcripts;

…

The remaining 43 lines stay in the interactive article so this page remains a written walkthrough rather than a raw SQL dump.

Now whenever a new meeting gets added to the meeting_transcripts table, it’s automatically chunked, embedded, and searchable within 5 minutes. No manual intervention needed.

Advanced Feature: Topic Extraction

We can use Cortex to automatically extract topics from meetings:

Advanced Feature: Topic Extraction: excerpt of this SQL example. This is a shortened excerpt of a 34-line script.
-- Add topics column
ALTER TABLE meeting_transcripts 
ADD COLUMN ai_extracted_topics ARRAY;

-- Extract topics using LLM
UPDATE meeting_transcripts
SET ai_extracted_topics = PARSE_JSON(
    SNOWFLAKE.CORTEX.COMPLETE(
…

The remaining 26 lines stay in the interactive article so this page remains a written walkthrough rather than a raw SQL dump.

This auto-tagging makes meetings even more discoverable without manual categorization.

Cost Optimization Tips

Running LLMs on every query can get expensive. Here are strategies to keep costs reasonable:

Cost Optimization Tips: excerpt of this shell example. This is a shortened excerpt of a 104-line script.
-- Strategy 1: Response caching
CREATE OR REPLACE TABLE answer_cache (
    question_hash STRING PRIMARY KEY,
    question STRING,
    cached_answer VARIANT,
    cached_at TIMESTAMP_LTZ,
    cache_hits INTEGER DEFAULT 0
);
…

The remaining 96 lines stay in the interactive article so this page remains a written walkthrough rather than a raw shell dump.

These optimization strategies can cut costs by 40-60% while maintaining quality for most queries.

Quality Assurance: Building a Test Suite

We should validate that our RAG system returns accurate answers:

Quality Assurance: Building a Test Suite: excerpt of this SQL example. This is a shortened excerpt of a 63-line script.
-- Create test cases table
CREATE OR REPLACE TABLE rag_test_cases (
    test_id INTEGER AUTOINCREMENT,
    test_question STRING,
    expected_answer_contains STRING,
    expected_meeting_reference STRING,
    test_category STRING,
    created_at TIMESTAMP_LTZ DEFAULT CURRENT_TIMESTAMP()
…

The remaining 55 lines stay in the interactive article so this page remains a written walkthrough rather than a raw SQL dump.

This automated testing ensures our RAG system maintains quality as we add more meetings and refine prompts.

Monitoring and Alerts

Set up monitoring to catch issues early:

Monitoring and Alerts: excerpt of this SQL example. This is a shortened excerpt of a 46-line script.
-- Create monitoring table
CREATE OR REPLACE TABLE rag_health_metrics (
    metric_date DATE,
    total_queries INTEGER,
    avg_response_time_seconds FLOAT,
    successful_queries INTEGER,
    failed_queries INTEGER,
    avg_satisfaction_score FLOAT,
…

The remaining 38 lines stay in the interactive article so this page remains a written walkthrough rather than a raw SQL dump.

Advanced: Multi-Turn Conversations

Right now, each question is independent. We can add conversation context:

Advanced: Multi-Turn Conversations: excerpt of this shell example. This is a shortened excerpt of a 39-line script.
-- Table to track conversation sessions
CREATE OR REPLACE TABLE conversation_sessions (
    session_id STRING PRIMARY KEY,
    user_name STRING,
    started_at TIMESTAMP_LTZ DEFAULT CURRENT_TIMESTAMP(),
    last_interaction TIMESTAMP_LTZ DEFAULT CURRENT_TIMESTAMP(),
    conversation_history ARRAY
);
…

The remaining 31 lines stay in the interactive article so this page remains a written walkthrough rather than a raw shell dump.

This allows follow-up questions like:

  • User: “What did we decide about the database?”
  • System: “We chose PostgreSQL…”
  • User: “Why that over MySQL?” ← understands “that” refers to PostgreSQL

Example Use Cases in Action

Let’s see how different teams would use this:

Engineering Team:

Example Use Cases in Action: excerpt of this SQL example. This is a shortened excerpt of a 17-line script.
-- Find all technical decisions
SELECT 
    result:answer::STRING as answer
FROM (
    SELECT ask_meeting_assistant(
        'What technical decisions were made in the last month?'
    ) as result
);
…

The remaining 9 lines stay in the interactive article so this page remains a written walkthrough rather than a raw SQL dump.

Product Team:

Example Use Cases in Action: excerpt of this SQL example (part 2). This is a shortened excerpt of a 17-line script.
-- Customer feedback summary
SELECT 
    result:answer::STRING as answer
FROM (
    SELECT ask_meeting_assistant(
        'What customer feedback have we received about the dashboard?'
    ) as result
);
…

The remaining 9 lines stay in the interactive article so this page remains a written walkthrough rather than a raw SQL dump.

Management:

SQL 11 lines

SQL example — read the query, then copy it into your warehouse.

-- Project blockersSELECT     result:answer::STRING as answerFROM (    SELECT ask_meeting_assistant(        'What are the current blockers for the product launch?'    ) as result); -- Team action itemsSELECT * FROM TABLE(get_action_items_for('engineering team'));

Extending to Other Data Sources

The beautiful thing about this architecture is it’s extensible. We can add other knowledge sources:

Extending to Other Data Sources: excerpt of this shell example. This is a shortened excerpt of a 34-line script.
-- Add Jira tickets
CREATE TABLE jira_issues (
    issue_key STRING,
    summary STRING,
    description STRING,
    status STRING,
    created_date TIMESTAMP_LTZ
);
…

The remaining 26 lines stay in the interactive article so this page remains a written walkthrough rather than a raw shell dump.

Now your RAG system becomes a true organizational knowledge hub.

What We’ve Built

Let’s recap what this system can do:

✅ Natural language search across all meeting notes
✅ Intelligent answers with source citations
✅ Action item tracking by person and date
✅ Decision history with full context
✅ Topic extraction and categorization
✅ Multi-turn conversations with context memory
✅ Automated ingestion of new meetings
✅ Quality monitoring and testing
✅ Cost optimization through caching
✅ Integration ready for Slack, Teams, etc.

And all of this runs entirely within Snowflake—no external services, no data movement, no infrastructure headaches.

The Real Value Proposition

Here’s what changes when we have a system like this:

Before:

  • Someone asks “What did we decide about X?”
  • You spend 20 minutes searching through meeting notes
  • You find partial information across 3 different meetings
  • You piece together an answer, but you’re not 100% sure
  • Total time wasted: 20+ minutes

After:

  • Someone asks “What did we decide about X?”
  • You type the question into the assistant
  • Get a complete answer with sources in 2 seconds
  • Click through to verify if needed
  • Total time: 30 seconds

That’s a 40x improvement. Multiply that across your entire team, every day, and the ROI becomes obvious.

Future Enhancements We Can Build

This is just the foundation. Here are ideas for taking it further:

  1. Automatic summaries: Email digest every Monday with key decisions from last week
  2. Proactive alerts: “You have 3 action items due this week”
  3. Meeting preparation: “Here’s what was discussed last time you met with this team”
  4. Trend analysis: “Database migration has been mentioned 15 times this month”
  5. Sentiment tracking: Detect when team morale shifts in meetings
  6. Smart reminders: “You committed to X in the meeting but haven’t updated status”

The possibilities are endless once we have meeting data structured and searchable.

Final Thoughts

The technology for this has existed for years, but what’s changed is how accessible it’s become. Building a RAG system used to require:

  • Deep ML expertise
  • Complex infrastructure
  • Weeks of development time
  • Ongoing maintenance burden

Now, with Snowflake Cortex, we can build it in a weekend using SQL. That’s the real revolution—not the technology itself, but the democratization of it.

Every organization has the same problem: valuable knowledge trapped in meeting notes that nobody ever looks at again. We’ve just seen how to solve that problem in a practical, maintainable way.

The question isn’t “Can we build this?” anymore. It’s “When do we start?”


Complete Setup Script : Github Repo

Here’s everything in one place to get started:

Complete Setup Script : Github Repo: excerpt of this SQL example. This is a shortened excerpt of a 59-line script.
-- Complete setup script for Meeting Notes RAG
-- Run this entire script to set up the system

-- 1. Database setup
CREATE DATABASE IF NOT EXISTS meeting_intelligence;
USE DATABASE meeting_intelligence;
CREATE SCHEMA IF NOT EXISTS meetings;
USE SCHEMA meetings;
…

The remaining 51 lines stay in the interactive article so this page remains a written walkthrough rather than a raw SQL dump.

Additional Resources

Documentation Links:

Want to Learn More?
This is just scratching the surface of what’s possible with RAG systems in Snowflake. The same principles apply to:

  • Customer support ticket analysis
  • Documentation search
  • Code repository search
  • Email analysis
  • Contract review
  • Research paper analysis

The foundation we’ve built here can be adapted to any text-based knowledge base.

Questions this article answers

Short answers first. Open a question to read the working note.

What We're Building (In Plain English)?

Before diving into code, let's understand what a Meeting Notes RAG actually does: RAG = Retrieval Augmented Generation

Why Snowflake for This?

You might be thinking: "Can't I just use ChatGPT with my notes?" Sure, but here's why Snowflake is better for this:

What We've Built?

Let's recap what this system can do: ✅ Natural language search across all meeting notes ✅ Intelligent answers with source citations ✅ Action item tracking by person and date ✅ Decision history with full context ✅ Topic extraction and categorization ✅ Multi-turn conversations with context memory ✅ Automated ingestion of new meetings ✅ Quality monitoring and testing ✅ Cost optimization through caching ✅ Integration ready for Slack, Teams, etc.