{"id":50958281,"url":"https://github.com/henrymorgandibie/snowflake-semantic-agent","last_synced_at":"2026-06-18T10:02:47.326Z","repository":{"id":363699507,"uuid":"1264410385","full_name":"HenryMorganDibie/snowflake-semantic-agent","owner":"HenryMorganDibie","description":"Production-pattern dbt MetricFlow semantic layer with Snowflake Horizon Catalog integration and a FastAPI agentic query interface — governed metrics for AI systems, no raw SQL.","archived":false,"fork":false,"pushed_at":"2026-06-10T01:00:43.000Z","size":30,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-10T03:03:44.136Z","etag":null,"topics":["agentic-ai","data-engineering","dbt","fastapi","llm","metricflow","python","semantic-layer","snowflake","snowflake-horizon"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HenryMorganDibie.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-09T21:27:51.000Z","updated_at":"2026-06-10T01:00:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/HenryMorganDibie/snowflake-semantic-agent","commit_stats":null,"previous_names":["henrymorgandibie/snowflake-semantic-agent"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/HenryMorganDibie/snowflake-semantic-agent","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HenryMorganDibie%2Fsnowflake-semantic-agent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HenryMorganDibie%2Fsnowflake-semantic-agent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HenryMorganDibie%2Fsnowflake-semantic-agent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HenryMorganDibie%2Fsnowflake-semantic-agent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HenryMorganDibie","download_url":"https://codeload.github.com/HenryMorganDibie/snowflake-semantic-agent/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HenryMorganDibie%2Fsnowflake-semantic-agent/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34485169,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-18T02:00:06.871Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentic-ai","data-engineering","dbt","fastapi","llm","metricflow","python","semantic-layer","snowflake","snowflake-horizon"],"created_at":"2026-06-18T10:02:46.031Z","updated_at":"2026-06-18T10:02:47.319Z","avatar_url":"https://github.com/HenryMorganDibie.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Snowflake Semantic Layer Agent\n\n**Make your Snowflake data safe for AI agents — governed metrics, no raw SQL, no hallucinated joins.**\n\nA production-pattern implementation of a dbt MetricFlow semantic layer with Snowflake Horizon Catalog integration and a FastAPI agentic query interface.\n\n\u003e A production-ready pattern for teams moving from \"AI querying raw tables\" to \"AI querying governed, version-controlled business logic.\" Includes migration strategy for existing dbt projects, Horizon Catalog governance configuration, and a production readiness checklist.\n\n---\n\n## 1-Minute Overview\n\nThis system lets AI agents query Snowflake using governed business metrics instead of raw tables.\n\nInstead of an agent writing `SELECT SUM(amount) FROM orders WHERE...` and guessing at joins, filters, and business rules — it asks *\"What was revenue last month by region?\"* and gets back a structured, auditable answer grounded in metric definitions that your entire organisation has agreed on.\n\nEvery metric is defined once in dbt MetricFlow, registered in Snowflake Horizon Catalog, and served through a natural language API. All analytics — from BI dashboards to AI agents to ad-hoc queries — draw from the same governed source. No inconsistency. No metric drift. No surprises.\n\n---\n\n## Why This Is Different From Normal BI Tools\n\nMost analytics stacks solve part of the problem. This system solves the whole thing.\n\n| Approach | What It Does | What's Missing |\n|---|---|---|\n| **Looker / Tableau** | Governed metrics for dashboards | Static — agents can't query it; logic locked in LookML/calculated fields |\n| **dbt alone** | Clean, tested transformations | No semantic layer; agents still hit raw marts and guess at business logic |\n| **Snowflake Cortex only** | AI queries over Snowflake data | No governed metric layer; each query re-derives logic independently |\n| **This system** | Governed MetricFlow metrics + Horizon Catalog + agentic API | — |\n\nThe key difference: **business logic is defined once and enforced everywhere** — in BI tools, in AI agents, and in ad-hoc queries — through a single version-controlled semantic layer. Not per-dashboard. Not per-prompt.\n\n---\n\n## Live Example Flow\n\n**Question:** *\"What was total revenue last month by region?\"*\n\n```\nStep 1 — Intent Resolution\n  User question → Hybrid router\n  Rule-based triage: \"revenue\" keyword detected → candidate: total_revenue\n  ✓ Fast path resolved in \u003c1ms\n\nStep 2 — MetricFlow Query\n  Metric: total_revenue\n  Group by: region, metric_time (grain: month)\n  Filter: order_status != 'cancelled'   ← enforced at definition level\n  MetricFlow generates SQL →\n\nStep 3 — SQL Generated by MetricFlow\n  SELECT\n      DATE_TRUNC('month', order_date)  AS metric_time__month,\n      region,\n      SUM(order_amount_usd)            AS total_revenue\n  FROM analytics.marts.fct_orders\n  WHERE order_status != 'cancelled'\n  GROUP BY 1, 2\n\nStep 4 — Snowflake Executes\n  Query runs against marts.fct_orders\n  Horizon Catalog logs: agent identity, metric accessed, timestamp\n\nStep 5 — Structured Response\n  {\n    \"metric_name\": \"total_revenue\",\n    \"display_name\": \"Total Revenue (USD)\",\n    \"time_grain\": \"month\",\n    \"group_by\": [\"region\"],\n    \"rows\": [\n      { \"metric_time__month\": \"2024-01-01\", \"region\": \"EMEA\", \"total_revenue\": 48320.00 },\n      { \"metric_time__month\": \"2024-01-01\", \"region\": \"APAC\", \"total_revenue\": 39150.75 },\n      { \"metric_time__month\": \"2024-01-01\", \"region\": \"AMER\", \"total_revenue\": 55360.25 }\n    ],\n    \"generated_sql\": \"SELECT ...\",\n    \"governance_note\": \"Resolved through governed MetricFlow definitions. Version-controlled in dbt. Registered in Snowflake Horizon Catalog.\"\n  }\n```\n\nEvery step is logged. Every result is traceable back to a version-controlled metric definition.\n\n---\n\n## Architecture\n\n```\n  User / Agentic System\n  (LangGraph · Cortex · Claude · Custom)\n           │\n           │  Natural language question\n           ▼\n  ┌─────────────────────────────────┐\n  │     Semantic Layer Agent        │\n  │          (FastAPI)              │\n  │                                 │\n  │  ┌───────────────────────────┐  │\n  │  │     Hybrid Intent Router  │  │\n  │  │                           │  │\n  │  │  Rule-based (fast path)   │  │\n  │  │    keyword → metric       │  │\n  │  │         ↓ miss            │  │\n  │  │  LLM tool-calling         │  │\n  │  │  (slow path, Claude)      │  │\n  │  └───────────────────────────┘  │\n  └──────────────┬──────────────────┘\n                 │  Resolved metric + dimensions\n                 ▼\n  ┌─────────────────────────────────┐\n  │   dbt Semantic Layer API        │\n  │       (MetricFlow)              │\n  │                                 │\n  │  Semantic models · Metrics      │\n  │  Entities · Dimensions          │\n  │  SQL generated at query time    │\n  └──────────────┬──────────────────┘\n                 │  Generated SQL\n                 ▼\n  ┌─────────────────────────────────┐\n  │          Snowflake              │\n  │   marts.fct_orders              │\n  └──────────────┬──────────────────┘\n                 │\n                 ▼\n  ┌─────────────────────────────────────────────────────┐\n  │         Snowflake Horizon Catalog                    │\n  │              (Governance Layer)                      │\n  │                                                      │\n  │  Semantic Views  ·  Access Policies                  │\n  │  Data Lineage    ·  Agent Identity Logging           │\n  │  MCP Interface   ·  Metric Discoverability           │\n  │                                                      │\n  │  Every agent query is logged with:                   │\n  │    - agent identity (human vs. AI)                   │\n  │    - metric accessed                                  │\n  │    - timestamp and row-level access decision         │\n  └─────────────────────────────────────────────────────┘\n```\n\n---\n\n## Repository Structure\n\n```\nsnowflake-semantic-agent/\n│\n├── dbt_project/\n│   ├── dbt_project.yml\n│   └── models/\n│       ├── staging/\n│       │   ├── stg_orders.sql              # Typed, renamed raw orders\n│       │   └── stg_customers.sql           # Typed, renamed raw customers\n│       ├── marts/\n│       │   ├── fct_orders.sql              # Orders fact table — semantic anchor\n│       │   └── metricflow_time_spine.sql   # Required MetricFlow time axis\n│       └── semantic/\n│           └── sem_orders.yml              # ★ MetricFlow semantic model + all metrics\n│\n├── agent/\n│   └── main.py                             # FastAPI semantic layer agent\n│\n├── docs/\n│   ├── horizon_catalog_semantic_views.yml  # Horizon Catalog semantic view definitions\n│   ├── migration_guide.md                  # How to adopt MetricFlow on an existing dbt project\n│   └── production_readiness.md             # Pre-launch checklist for production deployment\n│\n├── .env.example\n└── requirements.txt\n```\n\n---\n\n## The Semantic Model\n\n`sem_orders.yml` is the core of the project — a MetricFlow semantic model that defines the single source of truth for all order metrics.\n\n**Entities** (how MetricFlow traverses relationships at query time):\n- `order` (primary), `customer` (foreign), `product` (foreign)\n\n**Measures** (aggregatable facts):\n- `revenue` — `SUM(order_amount_usd)`\n- `order_count` — `COUNT_DISTINCT(order_id)`\n- `units_sold` — `SUM(order_quantity)`\n- `customers_with_orders` — `COUNT_DISTINCT(customer_id)`\n\n**Dimensions** (slicing attributes):\n- `order_date` (time), `region`, `acquisition_channel`, `order_status`, `customer_plan_type`, `customer_country`\n\n---\n\n## Governed Metrics\n\n| Metric | Type | Description |\n|---|---|---|\n| `total_revenue` | Simple | Total confirmed order revenue (USD) |\n| `order_volume` | Simple | Count of confirmed orders |\n| `units_sold` | Simple | Total units shipped |\n| `active_customers` | Simple | Distinct customers with confirmed orders |\n| `average_order_value` | Ratio | `total_revenue / order_volume` |\n| `revenue_per_customer` | Ratio | `total_revenue / active_customers` |\n| `cumulative_revenue_mtd` | Cumulative | Month-to-date revenue, resets monthly |\n| `cumulative_orders_mtd` | Cumulative | Month-to-date order count |\n| `revenue_growth_wow` | Derived | Week-over-week revenue growth rate |\n\nEvery metric filters cancelled orders at **definition level** — not at the dashboard, not in the agent prompt. The business rule lives in one version-controlled place.\n\n---\n\n## Snowflake Horizon Catalog Integration\n\nMetric definitions are registered as **Semantic Views** in Snowflake Horizon Catalog — making metrics discoverable and queryable by both humans and AI agents from the same trusted source.\n\n| Semantic View | Metrics | Consumer |\n|---|---|---|\n| `sv_revenue_metrics` | Revenue, AOV, WoW growth, MTD | Finance, executive agents |\n| `sv_customer_metrics` | Active customers, revenue/customer | CRM, churn agents |\n| `sv_operational_metrics` | Order volume, units, MTD orders | Ops, supply chain agents |\n\nAgents connect via the **Model Context Protocol (MCP)** — a standard interface that lets any agent framework query governed Semantic Views without custom integration per system. Horizon Catalog enforces access policy, logs agent identity, and distinguishes human vs. AI queries.\n\nSee `docs/horizon_catalog_semantic_views.yml` for the full definitions.\n\n---\n\n## Intent Routing — How It Works\n\nThe agent uses a **hybrid routing strategy** designed to balance latency and coverage:\n\n| Path | Trigger | Latency | Example |\n|---|---|---|---|\n| **Rule-based (fast)** | Unambiguous keyword match | \u003c1ms | *\"What is revenue by region?\"* |\n| **LLM tool-calling (slow)** | No keyword match; ambiguous intent | ~1–2s | *\"How are our top customers trending vs. last quarter?\"* |\n| **Fallback** | LLM cannot resolve | — | Returns full metric catalog for re-prompting |\n\nThe LLM slow path uses Claude with the metric catalog exposed as tools — the model selects the right metric, dimensions, and filters through structured tool-calling, not free-text generation. This keeps outputs well-formed even for complex questions.\n\n---\n\n## Commercial Impact\n\nDeploying this architecture delivers measurable value across three areas:\n\n**Consistency** — Revenue reported in Salesforce, your finance dashboard, and your AI agent's weekly summary will be the same number. Metric definitions are version-controlled and shared.\n\n**Analyst capacity** — The long tail of metric queries (\"What's MTD revenue for EMEA pro-tier customers?\") is handled by the agent layer. Analysts focus on questions that require judgment, not SQL.\n\n**AI readiness** — Agents that query raw tables are fragile and unauditable. This architecture makes your Snowflake data agent-safe: governed, logged, and traceable to a specific metric version.\n\n---\n\n## Production Docs\n\nThis repository includes two documents that address the real concerns of deploying a semantic layer in an existing enterprise environment.\n\n**[Migration Guide](docs/migration_guide.md)** — How to introduce MetricFlow into an existing dbt project without disrupting current pipelines. Covers the full phased approach: audit, time spine, first semantic model, metric migration from legacy dbt metrics, Horizon Catalog registration, and agent consumption. Includes a table of common org constraints (multiple dbt projects, OSS dbt Core, Snowflake permission issues) and how to handle each.\n\n**[Production Readiness Checklist](docs/production_readiness.md)** — Eight areas to sign off before connecting agentic systems to a production Semantic Layer: semantic model correctness, metric parity validation, governance configuration, API security, agent safety, versioning, monitoring, and rollback readiness. Built to be used as an actual gate, with a sign-off table per area.\n\n---\n\n## Setup\n\n```bash\n# 1. Clone and install\ngit clone https://github.com/HenryMorganDibie/snowflake-semantic-agent\ncd snowflake-semantic-agent\npip install -r requirements.txt\n\n# 2. Configure environment\ncp .env.example .env\n# Fill in: DBT_SL_TOKEN, DBT_ENVIRONMENT_ID, Snowflake credentials\n\n# 3. Run dbt\ncd dbt_project\ndbt deps \u0026\u0026 dbt build\n\n# 4. Validate MetricFlow semantic models\nmf validate-configs\nmf query --metrics total_revenue --group-by metric_time__month\n\n# 5. Start the agent\ncd ..\nuvicorn agent.main:app --reload\n```\n\n**Running without credentials:** the agent degrades gracefully — all endpoints respond with stub data so you can explore the API structure without a live Snowflake connection.\n\n---\n\n## Key Design Decisions\n\n**Hybrid intent routing over pure LLM routing**\nPure LLM routing adds 1–3 seconds of latency to every query. Rule-based triage handles the ~80% of queries that are unambiguous; LLM tool-calling handles the rest. p50 latency stays low while coverage remains high.\n\n**MetricFlow over warehouse-native metric definitions**\nMetricFlow definitions travel with the dbt project. If the warehouse changes, the business logic doesn't.\n\n**`generated_sql` always returned**\nAgentic systems that can't be audited don't get deployed. Returning the MetricFlow-generated SQL closes the loop between the natural language question and the data that answered it.\n\n**Governance in Horizon Catalog, not the application layer**\nAccess policies, agent identity logging, and data classification live in Snowflake Horizon Catalog — not in application code that can be bypassed. Governance is infrastructure, not middleware.\n\n---\n\n## Related Work\n\n- [NaijaFinAI](https://github.com/HenryMorganDibie/NaijaFinAI) — Nigerian-context fraud intelligence agent (FastAPI + React)\n- [knowledge-rag-api](https://github.com/HenryMorganDibie/knowledge-rag-api) — Hybrid RAG with pgvector, BM25, and RRF reranking\n- [Deal Intelligence Agent](https://github.com/HenryMorganDibie/deal-intelligence-agent) — 8-node LangGraph pipeline for PE/credit signal detection\n\n---\n\n## Author\n\n**Henry Dibie** — ML Systems Engineer \u0026 Data Scientist\n[LinkedIn](https://linkedin.com/in/kinghenrymorgan) · [GitHub](https://github.com/HenryMorganDibie) · [Medium](https://medium.com/@KingHenryMorgan)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhenrymorgandibie%2Fsnowflake-semantic-agent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhenrymorgandibie%2Fsnowflake-semantic-agent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhenrymorgandibie%2Fsnowflake-semantic-agent/lists"}