Skip to main content

wren-generate-mdl

Generate a Wren MDL project by exploring a database with available tools (SQLAlchemy, database drivers, MCP connectors, or raw SQL). Guides agents through schema discovery, type normalization, and MDL YAML generation using the wren CLI. Use when: user wants to create or set up a new MDL, onboard a new data source, or scaffold a project from an existing database.

Ir para a instalação

Informações da origem

Repositório
Canner/wren-engine
Última atividade na origem
10 de abril de 2026 às 01:25
Idioma detectado do SKILL.md
inglês
Estrelas
664
Forks
200

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
wren-generate-mdl
description
Generate a Wren MDL project by exploring a database with available tools (SQLAlchemy, database drivers, MCP connectors, or raw SQL). Guides agents through schema discovery, type normalization, and MDL YAML generation using the wren CLI. Use when: user wants to create or set up a new MDL, onboard a new data source, or scaffold a project from an existing database.
license
Apache-2.0
metadata
{"author":"wren-engine","version":"2.2"}
# Generate Wren MDL — CLI Agent Workflow ## Version check Silently fetch `https://raw.githubusercontent.com/Canner/wren-engine/main/skills/versions.json`. Compare the `wren-generate-mdl` key with this skill's version (from the frontmatter above). If the remote version is newer, notify the user before proceeding: > A newer version of the **wren-generate-mdl** skill is available. > Update with: > ``` > npx skills add Canner/wren-engine --skill wren-generate-mdl > ``` > The CLI auto-detects your installed agent. To target a specific one, add `--agent <name>` (e.g., `claude-code`, `cursor`, `windsurf`, `cline`). Then continue with the workflow below regardless of update status. --- Builds an MDL project by discovering database schema and converting it into Wren's YAML project format. The agent uses whatever database tools are available in its environment for introspection; the wren CLI handles type normalization, validation, and build. For memory and query workflows after setup, see the **wren-usage** skill. --- ## Prerequisites - `wren` CLI installed (`pip install wren-engine[<datasource>]`) - A working database connection (credentials available to the agent) - A wren profile configured (`wren profile add`) or connection info ready --- ## Phase 0 — Detect existing project **Goal:** If the current directory is already inside a wren project, let the user decide how to proceed. Check whether `wren_project.yml` exists in the current working directory (or any parent up to the repository root). If found: 1. Tell the user that an existing wren project was detected and show its path. 2. Ask: - **Reset** — wipe the existing project (`models/`, `views/`, `relationships.yml`, `instructions.md`, and rebuild `wren_project.yml`) and regenerate from scratch in the same directory. - **New path** — keep the existing project untouched and choose a different directory for the new project. Ask the user for the new path, then `wren context init --path <new_path>` and continue from Phase 1 using that path. If no existing project is detected, proceed directly to Phase 1. --- ## Phase 1 — Establish connection and scope **Goal:** Confirm the agent can reach the database and agree on scope with the user. 1. Verify connectivity using whichever tool is available: - If SQLAlchemy: `engine.connect()` test - If database driver: simple query like `SELECT 1` - If wren profile exists: `wren profile debug` to check config - If raw SQL via wren: `wren --sql "SELECT 1"` (requires profile or connection file) 2. Ask the user: - Which **schema(s)** or **dataset(s)** to include (skip if only one exists) - Whether to include **all tables** or a subset - The **datasource type** for wren (e.g., `postgres`, `bigquery`, `snowflake`) — needed for type normalization dialect --- ## Phase 2 — Discover schema **Goal:** Collect table names, column names, column types, and constraints. Use whatever introspection method is available. Here are common approaches ranked by convenience: ### Option A: SQLAlchemy (recommended if available) ```python from sqlalchemy import create_engine, inspect engine = create_engine(connection_url) inspector = inspect(engine) tables = inspector.get_table_names(schema="public") for table in tables: columns = inspector.get_columns(table, schema="public") # columns → [{"name": "id", "type": INTEGER(), "nullable": False, ...}] pk = inspector.get_pk_constraint(table, schema="public") # pk → {"constrained_columns": ["id"], "name": "orders_pkey"} fks = inspector.get_foreign_keys(table, schema="public") # fks → [{"constrained_columns": ["customer_id"], # "referred_table": "customers", # "referred_columns": ["id"]}] ``` ### Option B: Database-specific driver - **psycopg / asyncpg (Postgres):** Query `information_schema.columns` and `information_schema.table_constraints` - **google-cloud-bigquery:** `client.list_tables()`, `client.get_table()` → `table.schema` - **snowflake-connector-python:** `SHOW COLUMNS IN TABLE`, `SHOW PRIMARY KEYS IN TABLE` - **clickhouse-driver:** `DESCRIBE TABLE`, `system.tables` ### Option C: Raw SQL via wren If no driver is available but a wren profile is configured, query `information_schema` through wren itself: ```bash wren --sql "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'" -o json wren --sql "SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'orders'" -o json ``` Note: this goes through the MDL layer, so it only works if you already have a minimal MDL or if the database supports `information_schema` as regular tables. For bootstrapping from zero, Option A or B is preferred. --- ## Phase 3 — Normalize types **Goal:** Convert raw database types to wren-core-compatible types. ### Python import (recommended for batch processing) ```python from wren.type_mapping import parse_type, parse_types # Single type normalized = parse_type("character varying(255)", "postgres") # → "VARCHAR(255)" # Batch — entire table at once columns = [ {"column": "id", "raw_type": "int8"}, {"column": "name", "raw_type": "character varying"}, {"column": "total", "raw_type": "numeric(10,2)"}, ] normalized_cols = parse_types(columns, dialect="postgres") # Each dict now has a "type" key with the normalized value ``` ### CLI (if Python import not available) Single type: ```bash wren utils parse-type --type "character varying(255)" --dialect postgres # → VARCHAR(255) ``` Batch (stdin JSON): ```bash echo '[{"column":"id","raw_type":"int8"},{"column":"name","raw_type":"character varying"}]' \ | wren utils parse-types --dialect postgres ``` --- ## Phase 4 — Scaffold and write MDL project **Goal:** Create the YAML project structure. ### Step 1 — Initialize project ```bash wren context init --path /path/to/project ``` This creates: ```text project/ ├── wren_project.yml ├── models/ ├── views/ ├── relationships.yml └── instructions.md ``` > **IMPORTANT: `catalog` and `schema` in `wren_project.yml`** > > These are Wren Engine's internal namespace — they are NOT the database's > native catalog or schema. Keep the defaults (`catalog: wren`, `schema: public`) > unless you are intentionally configuring a multi-project namespace. > > Your database's actual catalog/schema is specified per-model in `table_reference` > (see Step 2). Do not copy database catalog/schema values into `wren_project.yml`. ### Step 2 — Write model files For each table, create a YAML file under `models/`. Use snake_case naming (the build step converts to camelCase automatically). ```yaml # models/orders/metadata.yml name: orders table_reference: catalog: "" # database catalog (empty string if not applicable; # for DuckDB, use the DB file name without extension, # e.g. jaffle_shop.duckdb → catalog: jaffle_shop) schema: public # database schema (this IS the DB schema) table: orders # database table name primary_key: order_id columns: - name: order_id type: INTEGER not_null: true - name: customer_id type: INTEGER - name: total type: "DECIMAL(10, 2)" - name: status type: VARCHAR properties: description: "Order status: pending, shipped, delivered, cancelled" ``` ### Step 3 — Write relationships From foreign key constraints discovered in Phase 2: ```yaml # relationships.yml - name: orders_customers models: - orders - customers join_type: many_to_one condition: "orders.customer_id = customers.customer_id" ``` Join type mapping: - FK table → PK table: `many_to_one` - PK table → FK table: `one_to_many` - Unique FK: `one_to_one` - Junction table: `many_to_many` If no foreign keys were found, infer from naming conventions: - Column `<table>_id` or `<table_singular>_id` → likely FK to `<table>` - Ask the user to confirm inferred relationships ### Step 4 — Add descriptions (optional but valuable) Ask the user to describe: - Each model (1-2 sentences about what the table represents) - Key columns (especially calculated fields or non-obvious names) These descriptions are indexed by `wren memory index` and significantly improve LLM query accuracy. --- ## Phase 5 — Validate and build ```bash # Validate YAML structure and integrity wren context validate --path /path/to/project # If strict mode is desired: wren context validate --path /path/to/project --strict # Build JSON manifest wren context build --path /path/to/project # Verify against database wren --sql "SELECT * FROM <model_name> LIMIT 1" ``` If validation fails, fix the reported issues and re-run. Common errors: - Duplicate model/column names - Missing primary key - Relationship referencing non-existent model - Invalid column type (try re-running through `parse_type`) --- ## Phase 6 — Initialize memory ```bash # Index schema (generates seed NL-SQL examples automatically) wren memory index # Verify wren memory status ``` After this step, `wren memory fetch` and `wren memory recall` are operational. See the **wren-usage** skill for query workflows. --- ## Phase 7 — Iterate with the user The initial MDL is a starting point. Improve it by: - Adding calculated columns based on business logic - Adding views for common query patterns - Refining descriptions based on actual query usage - Adding access control (RLAC/CLAC) if needed Each change follows: edit YAML → `wren context validate` → `wren context build` → `wren memory index`. --- ## Quick reference | Task | Command / Method | |------|-----------------| | Discover tables | Agent's own tools (SQLAlchemy, driver, raw SQL) | | Discover columns + types | Agent's own tools | | Discover constraints | Agent's own tools | | Normalize types (Python) | `from wren.type_mapping import parse_type` | | Normalize types (CLI) | `wren utils parse-type --type T --dialect D` | | Normalize types (batch) | `wren utils parse-types --dialect D < columns.json` | | Scaffold project | `wren context init` | | Write models | Create `models/<name>/metadata.yml` | | Write relationships | Edit `relationships.yml` | | Validate | `wren context validate` | | Build manifest | `wren context build` | | Test query | `wren --sql "SELECT * FROM <model> LIMIT 1"` | | Index memory | `wren memory index` | --- ## Things to avoid - Do not hardcode database-specific type strings in MDL — always normalize via `parse_type` - Do not skip validation before build — invalid YAML produces broken manifests silently - Do not guess column types — introspect from the actual database - Do not write relationships without confirming join conditions — wrong conditions cause silent query errors - Do not skip `wren memory index` after build — stale indexes degrade recall quality
Ver no GitHub