<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>article Managing Databricks Genie Agents as Code with Databricks Declarative Automation Bundles (DAB) in Technical Blog</title>
    <link>https://community.databricks.com/t5/technical-blog/managing-databricks-genie-agents-as-code-with-databricks/ba-p/164697</link>
    <description>&lt;P class="code-line" data-line="18"&gt;Databricks Genie Agents (formerly Genie Spaces) are domain-specific, no-code chat interfaces that let business users ask natural-language questions about their data and get back SQL queries, result tables, and visualizations. As a Genie Agent grows more sophisticated, with carefully crafted instructions, SQL filter snippets, example queries, and evaluation benchmarks, a new problem emerges: how do you manage all of that configuration reliably across environments?&lt;/P&gt;
&lt;P class="code-line" data-line="20"&gt;If your team is editing agent instructions directly in the Genie UI, you have no version history, no code review, and no reliable path to promote changes from dev to production. One wrong update and there's no rollback.&lt;/P&gt;
&lt;P class="code-line" data-line="22"&gt;In this post I'll show how to solve that using&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;&lt;A href="https://docs.databricks.com/aws/en/dev-tools/bundles/resources#genie_space" target="_blank" rel="noopener" data-href="https://docs.databricks.com/aws/en/dev-tools/bundles/resources#genie_space"&gt;Declarative Automation Bundles (DABs)&lt;/A&gt;&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;to manage a Genie Agent and its underlying Unity Catalog metric view entirely as code.&lt;/P&gt;
&lt;H2 id="the-problem-with-ui-only-genie-agent-management" class="code-line" dir="auto" data-line="24"&gt;The problem with UI-only Genie Agent management&lt;/H2&gt;
&lt;P class="code-line" data-line="25"&gt;A production-ready Genie Agent carries a surprising amount of configuration:&lt;/P&gt;
&lt;UL class="code-line" dir="auto" data-line="26"&gt;
&lt;LI class="code-line" dir="auto" data-line="26"&gt;&lt;STRONG&gt;Text instructions&lt;/STRONG&gt;: rules governing how the agent interprets questions, resolves ambiguity, and formats responses&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="27"&gt;&lt;STRONG&gt;SQL filter snippets&lt;/STRONG&gt;: pre-built filters users can reference naturally ("show me US revenue")&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="28"&gt;&lt;STRONG&gt;Example queries&lt;/STRONG&gt;: Q&amp;amp;A pairs that teach the agent how to respond to common questions&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="29"&gt;&lt;STRONG&gt;Benchmark questions&lt;/STRONG&gt;: ground truth SQL used to evaluate answer quality&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="30"&gt;&lt;STRONG&gt;Column configs&lt;/STRONG&gt;: controls format assistance (how values are displayed) and entity matching (so "germany" resolves to&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;Germany&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;in the Country dimension); entity matching requires format assistance to be enabled on the column&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="code-line" data-line="32"&gt;When all of this lives only in the UI, you get:&lt;/P&gt;
&lt;UL class="code-line" dir="auto" data-line="33"&gt;
&lt;LI class="code-line" dir="auto" data-line="33"&gt;No audit trail for who changed what and when&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="34"&gt;No peer review before changes hit production&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="35"&gt;No reliable way to promote the exact same configuration from dev to prod&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="36"&gt;No rollback if a bad instruction update breaks query behavior&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="code-line" data-line="38"&gt;The fix: treat the Genie Agent like any other piece of software: version-controlled, reviewed, and deployed through a pipeline.&lt;/P&gt;
&lt;H2 id="solution-overview-declarative-automation-bundles" class="code-line" dir="auto" data-line="40"&gt;Solution overview: Declarative Automation Bundles&lt;/H2&gt;
&lt;P class="code-line" data-line="41"&gt;Declarative Automation Bundles (DABs) is Databricks' infrastructure-as-code framework. It supports jobs, pipelines, dashboards, and as of CLI v1.10,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;Genie Agents&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;as first-class resources.&lt;/P&gt;
&lt;P class="code-line" data-line="43"&gt;The approach has two key pieces:&lt;/P&gt;
&lt;UL class="code-line" dir="auto" data-line="44"&gt;
&lt;LI class="code-line" dir="auto" data-line="44"&gt;&lt;STRONG&gt;UC Metric View&lt;/STRONG&gt;: the semantic layer that backs the Genie Agent, defined in YAML&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="45"&gt;&lt;STRONG&gt;Genie Agent&lt;/STRONG&gt;: the agent configuration (instructions, snippets, benchmarks), exported from the workspace and committed as JSON Both are versioned in git and deployed via&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;databricks bundle deploy&lt;/CODE&gt;.&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2 id="repository-structure" class="code-line" dir="auto" data-line="48"&gt;Repository structure&lt;/H2&gt;
&lt;P class="code-line" data-line="49"&gt;The full example is on GitHub:&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;A href="https://github.com/databricks-solutions/databricks-blogposts/tree/main/2026-08-genie-agent-cicd" target="_blank" rel="noopener" data-href="https://github.com/databricks-solutions/databricks-blogposts/tree/main/2026-08-genie-agent-cicd"&gt;https://github.com/databricks-solutions/databricks-blogposts/tree/main/2026-08-genie-agent-cicd&lt;/A&gt;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;genie-agent-cicd/
├── databricks.yml                        # bundle config, targets (dev/prod)
├── prebuild_notebook.py                  # substitutes {schema} into Genie Agent JSON — runs locally OR in Databricks
│
├── resources/
│   ├── metric_view.job.yml               # job: CREATE OR REPLACE metric view
│   └── tpcds_retail.genie_space.yml      # Genie Agent resource definition
│
├── src/                                  # source of truth — uses {schema} placeholders
│   ├── metric-view.yaml                  # metric view dimensions and measures (edit this; substitution handled by DABs at run time)
│   ├── create_metric_view.py             # notebook that runs CREATE OR REPLACE; receives catalog/schema as job parameters
│   └── tpcds_retail.geniespace.json      # Genie Agent content (edit this; substitution handled by prebuild_notebook.py)
│
└── build/                                # generated by prebuild_notebook.py — gitignored
   └── tpcds_retail.geniespace.json&lt;/LI-CODE&gt;
&lt;P class="code-line" data-line="67"&gt;Two files are the source of truth:&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;src/metric-view.yaml&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;defines the semantic layer (dimensions, measures, synonyms), and&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;src/tpcds_retail.geniespace.json&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;holds the agent configuration (instructions, SQL snippets, benchmarks).&lt;/P&gt;
&lt;P class="code-line" data-line="69"&gt;A small Python script (prebuild_notebook.py) substitutes&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;${catalog}&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;and&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;${schema}&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;placeholders into the Genie Agent JSON before deployment.&lt;/P&gt;
&lt;P class="code-line" data-line="71"&gt;A separate notebook (src/create_metric_view.py) handles the metric view: it reads&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;src/metric-view.yaml&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;at runtime and substitutes catalog/schema from job parameters before running the DDL.&lt;/P&gt;
&lt;P class="code-line" data-line="73"&gt;The Genie Agent and metric view are both deployed via&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;databricks bundle deploy&lt;/CODE&gt;, with the metric view applied by running the bundle job.&lt;/P&gt;
&lt;H2 id="why-this-pattern-works" class="code-line" dir="auto" data-line="75"&gt;Why this pattern works&lt;/H2&gt;
&lt;P class="code-line" data-line="76"&gt;&lt;STRONG&gt;The metric view YAML is human-friendly.&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;The inline source query, joins, dimensions, and measures are all readable and diff well in pull requests. A reviewer can see exactly which UNION ALL branch changed, which join was added, or which synonym was modified.&lt;/P&gt;
&lt;P class="code-line" data-line="78"&gt;&lt;STRONG&gt;The&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;.geniespace.json&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;is structured JSON, not a blob.&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;When DABs introduced the&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;genie-space&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;resource type, it made the agent config a proper file rather than a stringified JSON-inside-JSON. Every section (instructions, snippets, benchmarks, column configs) is a first-class JSON object you can edit and review.&lt;/P&gt;
&lt;P class="code-line" data-line="80"&gt;&lt;STRONG&gt;&lt;CODE&gt;databricks.yml&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;is the single source of environment config.&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;Catalog and schema are declared once per target. prebuild_notebook.py reads them and stamps the Genie Agent JSON into build/ before each deploy. For the metric view, catalog and schema are injected at runtime as job parameters — no hardcoded values in committed files, no manual reset when switching between dev and prod.&lt;/P&gt;
&lt;P class="code-line" data-line="82"&gt;&lt;STRONG&gt;The separation is clean.&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;The metric view (semantic layer) and the agent config (behavior layer) are in separate files with separate edit workflows. Changing a synonym does not require touching the agent instructions. Adding a benchmark question does not require regenerating SQL.&lt;/P&gt;
&lt;H2 id="example-dataset" class="code-line" dir="auto" data-line="84"&gt;Example dataset&lt;/H2&gt;
&lt;P class="code-line" data-line="85"&gt;The walkthrough below uses&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;&lt;CODE&gt;samples.tpcds_sf1&lt;/CODE&gt;&lt;/STRONG&gt;, a TPC-DS retail benchmark dataset that comes pre-loaded in every Databricks workspace. It contains three sales fact tables (&lt;CODE&gt;store_sales&lt;/CODE&gt;,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;catalog_sales&lt;/CODE&gt;,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;web_sales&lt;/CODE&gt;) plus standard dimension tables (&lt;CODE&gt;date_dim&lt;/CODE&gt;,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;item&lt;/CODE&gt;,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;customer&lt;/CODE&gt;). No data setup is required. You can follow every step using this dataset as-is.&lt;/P&gt;
&lt;P class="code-line" data-line="87"&gt;The same pattern applies to your own data: replace&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;samples.tpcds_sf1&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;with your source tables, and replace&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;&amp;lt;your_catalog&amp;gt;.&amp;lt;your_schema&amp;gt;&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;with the catalog and schema where you want the base view and metric view to live.&lt;/P&gt;
&lt;H2 id="prerequisites" class="code-line" dir="auto" data-line="89"&gt;Prerequisites&lt;/H2&gt;
&lt;H3 id="1-clone-the-repo" class="code-line" dir="auto" data-line="91"&gt;1. Clone the repo&lt;/H3&gt;
&lt;LI-CODE lang="markup"&gt;git clone https://github.com/databricks-solutions/databricks-blogposts.git
cd 2026-08-genie-agent-cicd&lt;/LI-CODE&gt;
&lt;H3 id="2-install-the-databricks-cli" class="code-line" dir="auto" data-line="97"&gt;2. Install the Databricks CLI&lt;/H3&gt;
&lt;P class="code-line" data-line="98"&gt;The bundle commands require Databricks CLI v1.10 or later.&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;macOS:&lt;/STRONG&gt;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;brew tap databricks/tap
brew install databricks&lt;/LI-CODE&gt;
&lt;P class="code-line" data-line="104"&gt;&lt;STRONG&gt;Linux / macOS (curl):&lt;/STRONG&gt;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;curl -fsSL https://raw.githubusercontent.com/databricks/setup-cli/main/install.sh | sh&lt;/LI-CODE&gt;
&lt;P class="code-line" data-line="108"&gt;&lt;STRONG&gt;Windows:&lt;/STRONG&gt;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;winget install Databricks.DatabricksCLI&lt;/LI-CODE&gt;
&lt;P class="code-line" data-line="112"&gt;Verify the installation:&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;databricks --version&lt;/LI-CODE&gt;
&lt;H3 id="3-configure-workspace-profiles" class="code-line" dir="auto" data-line="117"&gt;3. Configure workspace profiles&lt;/H3&gt;
&lt;P class="code-line" data-line="118"&gt;Each target in&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;databricks.yml&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;maps to a named profile in&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;~/.databrickscfg&lt;/CODE&gt;. Set up one profile per workspace using OAuth (recommended):&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;# Dev workspace
databricks auth login --host https://&amp;lt;dev-workspace&amp;gt;.cloud.databricks.com --profile DEFAULT
# Prod workspace
databricks auth login --host https://&amp;lt;prod-workspace&amp;gt;.cloud.databricks.com --profile PROD&lt;/LI-CODE&gt;
&lt;P class="code-line" data-line="125"&gt;Both commands open a browser for OAuth login and write the credentials to&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;~/.databrickscfg&lt;/CODE&gt;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;[DEFAULT]
host = https://&amp;lt;dev-workspace&amp;gt;.cloud.databricks.com
[PROD]
host = https://&amp;lt;prod-workspace&amp;gt;.cloud.databricks.com&lt;/LI-CODE&gt;
&lt;P class="code-line" data-line="132"&gt;Then update&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;databricks.yml&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;to reference the correct profile per target:&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;targets:
  dev:
    workspace:
      profile: DEFAULT
    variables:
      catalog: dev_catalog
      schema: genie
  prod:
    workspace:
      profile: PROD
    variables:
      catalog: prod_catalog
      schema: genie&lt;/LI-CODE&gt;
&lt;H2 id="step-1-define-your-uc-metric-view-in-yaml" class="code-line" dir="auto" data-line="150"&gt;Step 1: Define your UC metric view in YAML&lt;/H2&gt;
&lt;P class="code-line" data-line="151"&gt;A Unity Catalog metric view is a governed semantic layer — a special view type that separates how metrics are defined from how they're queried. Unlike a regular view that pre-aggregates at a fixed grain, a metric view lets callers choose which dimensions to group by at query time while guaranteeing the aggregation math is always correct. This makes it the ideal backing store for a Genie Agent: the agent uses your pre-vetted measure expressions, and the synonyms you define map natural-language terms like “revenue” or “sales” to the right SQL.&lt;/P&gt;
&lt;P class="code-line" data-line="153"&gt;You create a metric view with the&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;WITH METRICS LANGUAGE YAML&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;DDL — the YAML spec is embedded inline between $$ markers. The&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;STRONG&gt;metric view YAML&lt;/STRONG&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;defines dimensions, measures, and their configurations (synonyms, etc.). See the&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;src/metric-view.yaml&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;for detail.&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;CREATE OR REPLACE VIEW &amp;lt;your_catalog&amp;gt;.&amp;lt;your_schema&amp;gt;.tpcds_retail_sales_metrics
WITH METRICS
LANGUAGE YAML
AS $$
  version: 1.1
  source: |    -- inline UNION ALL of store_sales, catalog_sales, web_sales
    SELECT ... FROM samples.tpcds_sf1.store_sales UNION ALL ...
  dimensions:
    - name: Channel
      expr: source.channel
      synonyms: [sales channel, division]
  measures:
    - name: Total Sales
      expr: SUM(source.net_paid)
      synonyms: [revenue, net sales, sales]
$$&lt;/LI-CODE&gt;
&lt;P class="code-line" data-line="172"&gt;Querying a metric view requires wrapping every measure in MEASURE():&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;SELECT Channel, MEASURE(`Total Sales`) AS revenue
FROM &amp;lt;your_catalog&amp;gt;.&amp;lt;your_schema&amp;gt;.tpcds_retail_metrics
GROUP BY ALL&lt;/LI-CODE&gt;
&lt;P class="code-line" data-line="179"&gt;Source files use&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;${catalog}&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;and&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;${schema}&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;as placeholders, no environment-specific values are hardcoded. Then&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;metric_view.job.yml&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;injects&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;catalog&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;and&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;schema&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;as job parameters at run time via DABs variable substitution.&lt;/P&gt;
&lt;H3 id="note-understand-the-multi-fact-pattern" class="code-line" dir="auto" data-line="181"&gt;Note: Understand the multi-fact pattern&lt;/H3&gt;
&lt;P class="code-line" data-line="182"&gt;TPC-DS contains three sales fact tables — store_sales, catalog_sales, and web_sales — all representing the same business event: a sale line. When the analysis treats them as one unified sales process, normalize them with UNION ALL.&lt;/P&gt;
&lt;P class="code-line" data-line="184"&gt;The metric view's source: field accepts an inline SQL query, so the UNION ALL lives directly in the YAML — no pre-built base view needed. Each branch is explicitly enumerated (no SELECT *), date roles and customer roles are declared once, and a channel column is added to preserve provenance.&lt;/P&gt;
&lt;P class="code-line" data-line="186"&gt;Key design decisions in the union:&lt;/P&gt;
&lt;UL class="code-line" dir="auto" data-line="187"&gt;
&lt;LI class="code-line" dir="auto" data-line="187"&gt;Use UNION ALL, not UNION — two identical-looking lines can be separate real events.&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="188"&gt;Enumerate every column explicitly — union alignment is positional; implicit projections hide semantic mapping errors.&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="189"&gt;Date role: sold date, not ship date — ss_sold_date_sk / cs_sold_date_sk / ws_sold_date_sk consistently; ws_ship_date_sk is excluded.&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="190"&gt;Customer role: billing customer — catalog and web use the billing customer FK, not shipping. The dimension tables (date_dim, item) join many-to-one to the normalized union source, declared in the metric view's joins: block with rely.at_most_one_match: true. Databricks evaluates only the joins a query actually needs — no pre-flattening required.&lt;/LI&gt;
&lt;/UL&gt;
&lt;H2 id="step-2-export-your-genie-agent-from-the-workspace" class="code-line" dir="auto" data-line="193"&gt;Step 2: Export your Genie Agent from the workspace&lt;/H2&gt;
&lt;P class="code-line" data-line="194"&gt;If you already have a Genie Agent configured in the UI, the CLI can export it directly into your bundle. First, find the space ID in the browser URL:&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;https://&amp;lt;workspace&amp;gt;.cloud.databricks.com/genie/spaces/&amp;lt;SPACE_ID&amp;gt;&lt;/LI-CODE&gt;
&lt;P class="code-line" data-line="198"&gt;Then run:&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;databricks bundle generate genie-space \
  --existing-id &amp;lt;SPACE_ID&amp;gt; \
  --key tpcds_retail&lt;/LI-CODE&gt;
&lt;P class="code-line" data-line="204"&gt;The&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;--key&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;value (&lt;CODE&gt;tpcds_retail&lt;/CODE&gt;) becomes the resource key in the generated YAML and the identifier used when re-exporting or referencing the resource later.&lt;/P&gt;
&lt;P class="code-line" data-line="206"&gt;This generates two files:&lt;/P&gt;
&lt;UL class="code-line" dir="auto" data-line="207"&gt;
&lt;LI class="code-line" dir="auto" data-line="207"&gt;&lt;CODE&gt;src/tpcds_retail.geniespace.json&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;— the full agent configuration&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="208"&gt;&lt;CODE&gt;resources/tpcds_retail.genie_space.yml&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;— the DABs resource definition After the initial export,&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;src/tpcds_retail.geniespace.json&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;becomes your source of truth — edit it directly for subsequent changes rather than re-running generate.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="code-line" data-line="211"&gt;The&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;.geniespace.json&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;file is structured JSON, not a raw blob, so every section is directly editable:&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;{
  "version": 2,
  "instructions": {
    "text_instructions": [
      {
        "id": "...",
        "content": ["# Agent Instructions\r\n", "..."]
      }
    ],
    "sql_snippets": {
      "filters": [...],
      "measures": [...],
      "expressions": [...]
    },
    "example_question_sqls": [...]
  },
  "benchmarks": {
    "questions": [...]
  },
  "data_sources": {
    "tables": [
      {
        "identifier": "...",
        "column_configs": [...]
      }
    ]
  }
}
&lt;/LI-CODE&gt;
&lt;H3 id="managing-multiple-genie-agents" class="code-line" dir="auto" data-line="244"&gt;Managing multiple Genie Agents&lt;/H3&gt;
&lt;P class="code-line" data-line="245"&gt;Each agent uses its own&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;--key&lt;/CODE&gt;, so multiple agents coexist in the same bundle without conflict:&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;databricks bundle generate genie-space \
  --existing-id &amp;lt;SPACE_ID_B&amp;gt; \
  --key finance_agent&lt;/LI-CODE&gt;
&lt;P class="code-line" data-line="251"&gt;Add the new resource to&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;databricks.yml&lt;/CODE&gt;:&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;include:
  - resources/metric_view.job.yml
  - resources/tpcds_retail.genie_space.yml
  - resources/finance_agent.genie_space.yml&lt;/LI-CODE&gt;
&lt;P class="code-line" data-line="258"&gt;Each agent's files are completely independent —&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;src/finance_agent.geniespace.json&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;and&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;resources/finance_agent.genie_space.yml&lt;/CODE&gt;.&lt;/P&gt;
&lt;H2 id="step-3-configure-the-bundle-for-multiple-environments" class="code-line" dir="auto" data-line="260"&gt;Step 3: Configure the bundle for multiple environments&lt;/H2&gt;
&lt;P class="code-line" data-line="261"&gt;&lt;CODE&gt;databricks.yml&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;defines targets for each environment. A single&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;--target&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;flag promotes the exact same configuration to a different workspace with a different catalog.&lt;/P&gt;
&lt;P class="code-line" data-line="263"&gt;The&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;warehouse_id&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;variable is declared at the top level with no default — each target sets its own lookup by warehouse name, which resolves against that target's workspace at deploy time:&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;bundle:
  name: genie_agent_cicd
  engine: direct  # required for genie_spaces
variables:
  warehouse_id:
    description: SQL warehouse used to create the metric view and Genie Agent.
targets:
  dev:
    default: true
    mode: development
    workspace:
      profile: DEFAULT
    variables:
      catalog: dev_catalog
      schema: genie
      warehouse_id:
        lookup:
          warehouse: Serverless Starter Warehouse
  prod:
    mode: production
    workspace:
      profile: PROD
      root_path: /Workspace/Users/&amp;lt;user&amp;gt;@databricks.com/.bundle/${bundle.name}/${bundle.target}
    variables:
      catalog: prod_catalog
      schema: genie
      warehouse_id:
        lookup:
          warehouse: &amp;lt;prod_warehouse_name&amp;gt;&lt;/LI-CODE&gt;
&lt;H2 id="step-4-deploy" class="code-line" dir="auto" data-line="297"&gt;Step 4: Deploy&lt;/H2&gt;
&lt;H3 id="option-a--local-cli-laptop" class="code-line" dir="auto" data-line="299"&gt;Option A — Local CLI (laptop):&lt;/H3&gt;
&lt;P class="code-line" data-line="300"&gt;Generate build/ for dev and deploy&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;# The prebuild step substitutes ${catalog}/${schema} into the Genie Agent JSON. It must run before bundle deploy.
python3 prebuild_notebook.py --target dev
databricks bundle deploy --target dev
databricks bundle run metric_view --target dev

# Promote to prod — prebuild stamps prod catalog/schema into build/ first
python3 prebuild_notebook.py --target prod
python3 prebuild_notebook.py --verify prod   # CI guard: exits non-zero on mismatch
databricks bundle deploy --target prod
databricks bundle run metric_view --target prod
&lt;/LI-CODE&gt;
&lt;H3 id="option-b--deploying-from-the-databricks-workspace-ui" class="code-line" dir="auto" data-line="315"&gt;Option B — Deploying from the Databricks workspace UI&lt;/H3&gt;
&lt;P class="code-line" data-line="316"&gt;If you don't want to install the CLI locally, Databricks supports deploying bundles directly from the workspace. This is especially useful for team members who prefer a UI-driven workflow or don't have a local development environment set up.&lt;/P&gt;
&lt;P class="code-line" data-line="318"&gt;&lt;STRONG&gt;Prerequisites:&lt;/STRONG&gt;&lt;/P&gt;
&lt;UL class="code-line" dir="auto" data-line="319"&gt;
&lt;LI class="code-line" dir="auto" data-line="319"&gt;Workspace files must be enabled&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="320"&gt;The bundle must be cloned as a Git folder in the workspace (via Workspace &amp;gt; Git folders &amp;gt; Clone)&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="321"&gt;Serverless compute must be enabled&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="code-line" data-line="323"&gt;&lt;STRONG&gt;Workflow:&lt;/STRONG&gt;&lt;/P&gt;
&lt;OL class="code-line" dir="auto" data-line="324"&gt;
&lt;LI class="code-line" dir="auto" data-line="324"&gt;Clone the repo into your workspace as a Git folder&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="325"&gt;Open the bundle's Git folder — Databricks automatically detects databricks.yml and shows a bundle management UI&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="326"&gt;Select the target (dev or prod) from the dropdown&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="327"&gt;Run prebuild_notebook as a notebook in the workspace (set the target widget and run all cells) to generate&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;build/&lt;/CODE&gt;. It resolves paths from the notebook's workspace location. That's it. The Genie Agent and metric view now live in the target workspace. Because&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;prebuild_notebook.py&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;writes to&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;build/&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;each time, there's no risk of committing environment-specific values or having to manually reset between targets.&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="328"&gt;Click Deploy to deploy the bundle to the selected target. Click Run next to metric_view to apply the metric view DDL&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="dab-from-workspace.png" style="width: 999px;"&gt;&lt;img src="https://community.databricks.com/t5/image/serverpage/image-id/30234i9135DA173197F75B/image-size/large?v=v2&amp;amp;px=999" role="button" title="dab-from-workspace.png" alt="dab-from-workspace.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P class="code-line" data-line="332"&gt;&lt;STRONG&gt;Limitations:&lt;/STRONG&gt;&lt;/P&gt;
&lt;UL class="code-line" dir="auto" data-line="333"&gt;
&lt;LI class="code-line" dir="auto" data-line="333"&gt;Cross-workspace deployment (e.g., promoting from dev to prod in a different workspace) is not available from the UI editor — use the CLI or a CI/CD pipeline for cross-workspace promotion&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="334"&gt;Python for DABs is not supported in workspace mode&lt;/LI&gt;
&lt;LI class="code-line" dir="auto" data-line="335"&gt;Bundles inherit permissions from their parent Git folder.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="code-line" data-line="337"&gt;The workspace UI is a good fit for day-to-day iteration within a single environment. For multi-environment promotion and CI/CD pipelines, the CLI path remains the recommended approach.&lt;/P&gt;
&lt;H2 id="iterating-on-your-genie-agent" class="code-line" dir="auto" data-line="339"&gt;Iterating on Your Genie Agent&lt;/H2&gt;
&lt;H3 id="updating-the-genie-agent-instructions" class="code-line" dir="auto" data-line="341"&gt;Updating the Genie Agent instructions&lt;/H3&gt;
&lt;P class="code-line" data-line="342"&gt;Edit&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;src/tpcds_retail.geniespace.json&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;— for example, to add a new SQL filter snippet (use&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;CODE&gt;${catalog}.${schema}&lt;/CODE&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;for any table references):&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;"sql_snippets": {
  "filters": [
    {
      "id": "...",
      "display_name": "Store channel only",
      "sql": ["`channel` = 'Store'"],
      "synonyms": ["in-store", "brick and mortar"]
    }
  ]
}&lt;/LI-CODE&gt;
&lt;P class="code-line" data-line="355"&gt;Then:&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;python3 prebuild_notebook.py --target dev
databricks bundle deploy&lt;/LI-CODE&gt;
&lt;H3 id="updating-a-dimension-or-measure-in-metric-view" class="code-line" dir="auto" data-line="362"&gt;Updating a dimension or measure in metric view&lt;/H3&gt;
&lt;P class="code-line" data-line="363"&gt;Edit src/metric-view.yaml, then deploy and re-run the job to apply the DDL:&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;databricks bundle deploy
databricks bundle run metric_view&lt;/LI-CODE&gt;
&lt;H3 id="pulling-ui-changes-back-into-source-control" class="code-line" dir="auto" data-line="370"&gt;Pulling UI changes back into source control&lt;/H3&gt;
&lt;P class="code-line" data-line="371"&gt;If someone made changes directly in the Genie UI (it happens), re-export:&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;databricks bundle generate genie-space \
  --existing-id &amp;lt;SPACE_ID&amp;gt; \
  --key tpcds_retail&lt;/LI-CODE&gt;
&lt;H2 id="getting-started" class="code-line" dir="auto" data-line="379"&gt;Getting started&lt;/H2&gt;
&lt;P class="code-line" data-line="380"&gt;The full working example is available on GitHub:&lt;/P&gt;
&lt;P class="code-line" data-line="382"&gt;&lt;A href="https://github.com/databricks-solutions/databricks-blogposts/tree/main/2026-08-genie-agent-cicd" target="_blank" rel="noopener" data-href="https://github.com/databricks-solutions/databricks-blogposts/tree/main/2026-08-genie-agent-cicd"&gt;https://github.com/databricks-solutions/databricks-blogposts/tree/main/2026-08-genie-agent-cicd&lt;/A&gt;&lt;/P&gt;
&lt;P class="code-line" data-line="384"&gt;It includes the TPC-DS retail sales Genie Agent and metric view as a ready-to-deploy example. Clone it, swap in your workspace and catalog, import your own Genie Agent with bundle generate genie-space, and you have a CI/CD-ready Genie Agent in minutes.&lt;/P&gt;
&lt;P class="code-line" data-line="384"&gt;This post is also published on:&amp;nbsp;&lt;A href="https://anhcodes.dev/blog/genie-agent-cicd/" target="_blank" rel="noopener"&gt;https://anhcodes.dev/blog/genie-agent-cicd/&lt;/A&gt;&lt;/P&gt;</description>
    <pubDate>Tue, 01 Sep 2026 11:04:37 GMT</pubDate>
    <dc:creator>anhhchu</dc:creator>
    <dc:date>2026-09-01T11:04:37Z</dc:date>
    <item>
      <title>Managing Databricks Genie Agents as Code with Databricks Declarative Automation Bundles (DAB)</title>
      <link>https://community.databricks.com/t5/technical-blog/managing-databricks-genie-agents-as-code-with-databricks/ba-p/164697</link>
      <description>&lt;DIV&gt;
&lt;DIV&gt;&lt;SPAN&gt;If your team is editing agent instructions directly in the Genie UI, you have no version history, no code review, and no reliable path to promote changes from dev to production. One wrong update and there's no rollback.&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;SPAN&gt;In this post I'll show how to solve that using &lt;/SPAN&gt;&lt;SPAN&gt;&lt;STRONG&gt;Declarative Automation Bundles (DAB)&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;to manage a Genie Agent and its underlying Unity Catalog metric view entirely as code.&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;/DIV&gt;</description>
      <pubDate>Tue, 01 Sep 2026 11:04:37 GMT</pubDate>
      <guid>https://community.databricks.com/t5/technical-blog/managing-databricks-genie-agents-as-code-with-databricks/ba-p/164697</guid>
      <dc:creator>anhhchu</dc:creator>
      <dc:date>2026-09-01T11:04:37Z</dc:date>
    </item>
  </channel>
</rss>

