generate-view-from-table)
Overview and goal
In the Medallion LookML architecture (agentic-lookml), every physical database table is represented by a 1:1 autogenerated view in bronze/:table.view.lkml. Agents must never hand-write or hand-edit bronze/:table.view.lkml files. Run this skill for all physical tables referenced in the SQL queries every time (and whenever lkr parse sql-lookml-compare reveals a missing Bronze view or unmodeled_db_columns) so bronze/:table.view.lkml is always generated or refreshed directly from the database schema before authoring any refinements, Silver *_fields views, NDTs, or Explores.
Detecting missing or stale Bronze views with sql-lookml-compare
Run lkr parse sql-lookml-compare against the SQL query and local LookML project directory:
uv run lkr parse sql-lookml-compare \
--sql "SELECT o.order_id, o.user_id, o.total_amount FROM analytics.ecomm.orders AS o" \
--path ./lookml_project
Inspect each QueryLookmlMapping entry in queries[] by comparing parsed_query.tables against views:
- Identify all physical tables in
parsed_query.tables. Each entry is aTableRefwithname(table name),db(schema or dataset name),catalog(database or GCP project ID), andalias. Exclude any entry whosenamematches a CTE defined inparsed_query.ctes[].name. - Check for a missing Bronze view. If a physical table in
parsed_query.tableshas no matching entry inviews(whereviews[].sql_tablematches the table), no LookML view exists for that table yet. Trigger Bronze view generation immediately before attempting any downstream modeling. - Check for unmodeled physical columns on an existing Bronze view. If the physical table matches an existing
bronze/:table.view.lkmlinviews, inspectviews[].unmodeled_db_columns. Whenunmodeled_db_columnsis non-empty, the SQL query references physical columns on that table that are missing frombronze/:table.view.lkml. Regenerate the Bronze view from the database table rather than hand-editingbronze/:table.view.lkml.
Collision-aware Bronze folder routing
Before running the generator, determine the target folder inside bronze/ based on table-name uniqueness across the project:
| Scenario | Target folder (--folder / folder_name) |
Resulting file path |
|---|---|---|
No table name collision in bronze/ (default) |
bronze |
bronze/:table.view.lkml |
Table name :table collides across different schemas (db) |
bronze/:schema |
bronze/:schema/:table.view.lkml |
:schema.:table also collides across different databases or GCP projects (catalog) |
bronze/:dataset_or_database/:schema |
bronze/:dataset_or_database/:schema/:table.view.lkml |
If generating a new table causes a collision with an existing flat bronze/:table.view.lkml from another schema, move the existing view (and its companion .refinement.lkml if one exists) into its bronze/:schema/ subfolder and update its include: references so both tables follow the collision hierarchy cleanly.
Generating the Bronze view
Choose one of the three generation methods below depending on the active environment.
Using lkr tools lookml create CLI (recommended)
The lkr tools lookml create command switches to the Looker dev workspace, resets to production, creates a sync branch, invokes generate_lookml_with_new_files with file_type_for_explores="none", generate_descriptions=True, and add_autogenerated_header=True (# AUTOGENERATED), and commits/deploys the generated .view.lkml file:
# Generate a single Bronze view from a database table
uvx lkr-dev-cli tools lookml create \
--project-id "<project_id>" \
--connection "<connection_name>" \
--schema "<schema_name>" \
--table "<table_name>" \
--folder "bronze"
# Pull the newly generated Bronze view into the local LookML workspace
uvx lkr-dev-cli tools lookml pull ./lookml_project --project-id "<project_id>"
If multiple tables in a schema are missing from bronze/, pass --match "<schema_name>.*" or run lkr tools lookml create for each missing table identified in parsed_query.tables. Note that lkr tools lookml create refuses to overwrite an existing .view.lkml file that lacks the # AUTOGENERATED header unless --allow-update-without-header is passed.
Using lkr code-mode sandbox --dev-mode (generate_lookml_with_new_files)
When operating inside an active branch or lkr code-mode sandbox session, run scripts/generate_bronze_view.py with --dev-mode so Looker generates only the 1:1 physical .view.lkml files in bronze/ without resetting the active branch or creating raw explores:
lkr --base-url="$BASE_URL" --dev code-mode sandbox --dev-mode \
--file=.agents/skills/generate-view-from-table/scripts/generate_bronze_view.py \
--var project_id="<project_id>" \
--var model_name="<model_name>" \
--var connection_name="<connection_name>" \
--var schema_name="<schema_name>" \
--var table_name="<table_a>,<table_b>" \
--var folder_name="bronze"
After sandbox generation finishes, pull the generated files locally with lkr --base-url="$BASE_URL" --dev tools lookml pull ./lookml_project --project-id "<project_id>".
Using the Looker MCP Server (generate_view_from_table / create_view_from_table)
When connected to a Looker instance via the Looker MCP Server (without direct CLI write access to the remote project):
- Call the
dev_modeMCP tool withtrueso file generation runs in the developer workspace. - Call
generate_view_from_table(orcreate_view_from_tableon MCP Toolbox servers) with the targetproject_id,connection,schema(parsed_query.tables[].db),table(parsed_query.tables[].name), and target folderbronze(orbronze/<schema>). - Fetch the generated view content with
get_project_file(or pull vialkr tools lookml pull) so the localbronze/:table.view.lkmlfile matches the instance.
Post-generation verification and refinement boundary
After generating and pulling bronze/:table.view.lkml, complete two verification steps before continuing with agentic-lookml:
- Re-run
lkr parse sql-lookml-compareagainst the SQL query and local LookML directory. Confirm that every physical table inparsed_query.tablesnow resolves to aLookmlViewMatchentry inviewspointing tobronze/:table.view.lkmland thatunmodeled_db_columnsis empty ([]). - Respect the Bronze refinement boundary. Leave
bronze/:table.view.lkmluntouched (it already contains the autogenerated physical dimensions, basicdimension_groupblocks, andmeasure: count). If the SQL query requires a primary key override (primary_key: yes), a composite primary key (dimension: pk), calculated dimensions,type: durationdimension groups,hidden: yesandsuggestable: noflags on raw JSON columns, partition/clustering metadata descriptions, or single-table measures (sum,average,count_distinct, filtered single-table measures, or single-table ratios), createbronze/:table.refinement.lkmlon-demand withinclude: ":table.view.lkml"as its first line.