mirror of
https://github.com/Canner/WrenAI.git
synced 2026-08-30 18:00:36 +08:00
docs(core): refine IA — Quickstart per agent + question-titled concepts (#2311)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
---
|
||||
sidebar_label: How does the agent learn from your context?
|
||||
---
|
||||
|
||||
# How does the agent learn from your context?
|
||||
|
||||
> An agent that ships in production does not memorize your business — it reads structured context, recalls proven examples, and writes them back as it works. Wren AI is designed around that loop.
|
||||
|
||||
## Why this matters
|
||||
|
||||
A first-day analyst does not know which table is canonical. Neither does an agent. Both get better through the same path: a guided start, focused questions, and a record of what worked.
|
||||
|
||||
The difference is that an agent forgets between sessions unless your tooling stores the learning somewhere reviewable. Wren AI captures that learning in four explicit places — MDL, instructions, memory, and skills — so the agent picks up where the team left off, every time.
|
||||
|
||||
## The two beats: scaffold fast, enrich deep
|
||||
|
||||
Wren AI runs the agent through two beats whenever you set up a new project.
|
||||
|
||||
**Beat 1 — Scaffold fast.** The `wren-generate-mdl` skill drives the agent through schema discovery, type normalization, and an initial MDL project. The agent can already query through that modeled layer in a few minutes. The MDL is rough but functional — it covers what the database can tell you about itself.
|
||||
|
||||
**Beat 2 — Enrich deep.** Structure is only the start. The hard business meaning lives in docs, decks, Slack threads, and analyst SQL. The `wren-enrich-context` workflow brings that meaning in through two modes:
|
||||
|
||||
- **Grill mode** — the agent asks one focused question at a time ("which is the canonical `orders` table?", "what does `status = 4` mean?", "should `active customer` exclude internal users?"). You answer; the agent patches MDL, `instructions.md`, `queries.yml`, or memory.
|
||||
- **Auto-pilot mode** — drop PDFs, glossaries, handbooks, and SQL history into `<project>/raw/`. The agent reads them, proposes context changes with evidence, and waits for review.
|
||||
|
||||
Both modes write to reviewable, version-controlled artifacts. Nothing is silently absorbed into a black box.
|
||||
|
||||
## What learning actually persists
|
||||
|
||||
Four artifacts capture different layers of learning:
|
||||
|
||||
| Artifact | What it stores | Updated by |
|
||||
|---|---|---|
|
||||
| **MDL** (`models/`, `views/`, `relationships.yml`) | Structural and semantic contract — what data exists, how it relates, which calculations are reusable | `wren context build`, manual edits, agent-proposed changes |
|
||||
| **`instructions.md`** | Operational guidance — preferred terminology, default filters, table selection rules, caveats | Manual edits or agent-proposed changes |
|
||||
| **Memory** (`.wren/memory/`) | Retrieval index over MDL + instructions, plus a record of confirmed natural-language-to-SQL pairs | `wren memory index`, `wren memory store` |
|
||||
| **`queries.yml`** | Curated, committable seed of natural-language-to-SQL examples | `wren memory dump` from accumulated memory |
|
||||
|
||||
The agent reads from all four when it gathers context for a new question. The first three change rarely; memory and queries grow with use.
|
||||
|
||||
## The query workflow in practice
|
||||
|
||||
The `wren-usage` skill orchestrates the day-to-day pattern:
|
||||
|
||||
```text
|
||||
User asks a business question
|
||||
│
|
||||
├── 1. wren memory recall → find similar accepted NL-SQL pairs
|
||||
├── 2. wren memory fetch → retrieve relevant models, columns, relationships
|
||||
├── 3. Write SQL against MDL objects, not raw tables
|
||||
├── 4. wren dry-plan → see expanded SQL before execution
|
||||
├── 5. wren --sql ... → execute
|
||||
├── 6. Repair on failure → diagnose at MDL layer vs DB layer
|
||||
└── 7. wren memory store → persist the confirmed pair
|
||||
```
|
||||
|
||||
Each step is a deterministic primitive the agent orchestrates. The trace stays visible in the agent's reasoning, not buried in a closed product.
|
||||
|
||||
## Why this is different from "more examples"
|
||||
|
||||
Sending more examples into a prompt has a ceiling. The model sees the schema and tries its best.
|
||||
|
||||
Wren AI lets the system compound:
|
||||
|
||||
- Recurring questions retrieve better examples each time.
|
||||
- Recurring metrics reuse accepted SQL patterns.
|
||||
- Schema retrieval narrows as the project grows.
|
||||
- Corrections become future grounding instead of disappearing at session end.
|
||||
- Teams can commit `queries.yml` so new environments inherit the learning.
|
||||
|
||||
The agent is not getting smarter. The context layer it reads from is getting richer, and it is reviewable every step of the way.
|
||||
|
||||
## See also
|
||||
|
||||
- [How does memory get smarter over time?](./memory_system.md) — the mechanics of recall and indexing.
|
||||
- [What does MDL do for the agent?](./what_is_mdl.md) — the semantic contract the agent reads.
|
||||
- [Refine answer quality](/oss/guides/refine) — the recipe for running the enrich loop.
|
||||
@@ -1,234 +0,0 @@
|
||||
# Architecture
|
||||
|
||||
Wren AI is built as a system for **correctness** — not as a single feature. Text-to-SQL fails when any one of six pieces is missing; we build all six as primitives the agent orchestrates.
|
||||
|
||||
## Correctness is a system, not a switch
|
||||
|
||||
Correctness is the result of six things working together. Miss any one of them and the agent fails in that exact gap.
|
||||
|
||||
| Pillar | What it means | Where it lives in Wren AI |
|
||||
|---|---|---|
|
||||
| **Schema linking** | Knowing which tables to look at for a given question. | MDL + memory schema retrieval (`wren memory fetch`) |
|
||||
| **Value profiling** | Knowing what values actually live in those columns — what `status = 4` resolves to, whether `is_active` is `'Y'/'N'` or `true/false`. | Connector type coercion + `instructions.md` indexed into memory |
|
||||
| **Ambiguity detection** | Knowing when a question is ambiguous and a clarification is needed before generating SQL. | Skill orchestration layer (handled by the agent using Wren AI's primitives) |
|
||||
| **Generation trace** | Being able to show *how* an answer was constructed — which models, which joins, which CTEs. | `wren dry-plan` returns the expanded SQL deterministically |
|
||||
| **Retry and repair** | Being able to recover when the first SQL fails — re-plan, try a different model, surface a structured error. | Structured error responses + `wren dry-run` for pre-flight validation |
|
||||
| **Eval** | Detecting regression when underlying definitions change — schema drift, business rule rewrites, model renames. | Golden NL-SQL eval runner (in development) |
|
||||
|
||||
This is why Wren AI exposes **primitives**, not a closed product. The agent does the orchestration — picking the skill, asking the clarification, looping on retry. The trace lives where the agent's reasoning lives. We do not wrap correctness inside our own dashboard that you have to learn.
|
||||
|
||||
The rest of this page documents the components that implement those primitives.
|
||||
|
||||
## Overview
|
||||
|
||||
```text
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ Wren CLI (Typer) │
|
||||
│ │
|
||||
│ --sql / query dry-plan dry-run version │
|
||||
│ context profile memory utils │
|
||||
└──┬──────────────┬──────────────┬──────────────┬──────────┘
|
||||
│ │ │ │
|
||||
▼ ▼ │ ▼
|
||||
┌────────────┐ ┌────────────┐ │ ┌────────────────────┐
|
||||
│ Profile │ │ Context │ │ │ Memory Layer │
|
||||
│ Mgmt │ │ Mgmt │ │ │ (LanceDB) │
|
||||
│ │ │ │ │ │ │
|
||||
│ ~/.wren/ │ │ init │ │ │ schema_items │
|
||||
│ profiles │ │ validate │ │ │ query_history │
|
||||
│ .yml │ │ build │ │ │ │
|
||||
└─────┬──────┘ └─────┬──────┘ │ │ fetch / recall │
|
||||
│ │ │ │ store / index │
|
||||
│ connection │ mdl.json │ └────────────────────┘
|
||||
│ info │ │
|
||||
└──────┐ ┌─────┘ │
|
||||
▼ ▼ │
|
||||
┌──────────────┐ │
|
||||
│ WrenEngine │◄──────────┘ (dry-plan, query, dry-run)
|
||||
│ │
|
||||
│ plan() │
|
||||
│ execute() │
|
||||
└──┬───────┬───┘
|
||||
│ │
|
||||
plan │ │ execute
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────┐ ┌──────────────────┐
|
||||
│ SQL Planning │ │ Connectors │
|
||||
│ │ │ │
|
||||
│ sqlglot │ │ │
|
||||
│ parse │ │ Postgres DuckDB │
|
||||
│ qualify │ │ BigQuery MySQL │
|
||||
│ transpile │ │ Snowflake Trino │
|
||||
│ │ │ ...18+ sources │
|
||||
│ CTE Rewriter │ │ │
|
||||
│ inject CTEs │ └──────────────────┘
|
||||
│ │
|
||||
│ Policy check │
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ wren-core-py │
|
||||
│ (Rust / PyO3) │
|
||||
│ │
|
||||
│ SessionContext │
|
||||
│ ManifestExtractor│
|
||||
│ transform_sql() │
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
## Components
|
||||
|
||||
### CLI layer
|
||||
|
||||
The top-level command router, built on [Typer](https://typer.tiangolo.com/). It parses flags, discovers the MDL project and active profile, then delegates to WrenEngine or the appropriate subsystem.
|
||||
|
||||
| Command | What it does |
|
||||
|---------|-------------|
|
||||
| `wren --sql` / `wren query` | Plan + execute SQL, return results |
|
||||
| `wren dry-plan` | Plan only — show the expanded SQL without executing |
|
||||
| `wren dry-run` | Validate SQL against the live database without returning rows |
|
||||
| `wren context` | Project management — init, validate, build, show |
|
||||
| `wren profile` | Connection management — add, switch, list, debug, rm |
|
||||
| `wren memory` | Schema indexing and NL-SQL recall |
|
||||
| `wren utils` | Type normalization utilities |
|
||||
|
||||
### WrenEngine
|
||||
|
||||
The central orchestrator (`engine.py`). It owns the plan-then-execute pipeline:
|
||||
|
||||
1. Receive user SQL
|
||||
2. Call the SQL planning subsystem to expand MDL references
|
||||
3. Pass the planned SQL to a connector for execution
|
||||
4. Return results as a PyArrow table
|
||||
|
||||
### SQL planning
|
||||
|
||||
Transforms user SQL from semantic model references to executable database SQL. Three libraries collaborate:
|
||||
|
||||
- **sqlglot** — parses SQL, qualifies table/column references, transpiles between dialects
|
||||
- **CTE Rewriter** — identifies which MDL models are referenced, builds a CTE for each, and injects them into the query
|
||||
- **wren-core-py** — Rust engine (via PyO3 bindings) that expands model definitions, resolves calculated fields, and handles relationship joins
|
||||
|
||||
The planning pipeline:
|
||||
|
||||
```
|
||||
User SQL (e.g. SELECT * FROM orders WHERE status = 'pending')
|
||||
│
|
||||
├── sqlglot: parse → qualify tables → normalize identifiers
|
||||
├── Extract referenced table names → ["orders"]
|
||||
├── ManifestExtractor: filter MDL to only referenced models
|
||||
├── Policy check (strict mode, denied functions)
|
||||
├── CTE Rewriter:
|
||||
│ ├── For each model: wren-core transform_sql() → expanded CTE
|
||||
│ └── Inject CTEs into original query
|
||||
└── sqlglot: transpile to target dialect (postgres, bigquery, etc.)
|
||||
│
|
||||
▼
|
||||
WITH "orders" AS (
|
||||
SELECT o_orderkey, o_custkey, o_totalprice
|
||||
FROM "public"."orders"
|
||||
)
|
||||
SELECT * FROM "orders" WHERE status = 'pending'
|
||||
```
|
||||
|
||||
### Connectors
|
||||
|
||||
Data source connectors execute the planned SQL against the actual database. Each connector implements a common interface for query execution, dry-run validation, and connection lifecycle.
|
||||
|
||||
Supported data sources: PostgreSQL, MySQL, BigQuery, Snowflake, DuckDB, ClickHouse, Trino, SQL Server, Databricks, Redshift, Oracle, Athena, Apache Spark, and more.
|
||||
|
||||
Each connector:
|
||||
- Receives dialect-specific SQL from the planning stage
|
||||
- Executes against the target database
|
||||
- Handles type coercion (Decimal, UUID, etc.)
|
||||
- Returns a PyArrow table
|
||||
|
||||
### Profile management
|
||||
|
||||
Stores named database connections in `~/.wren/profiles.yml`. One profile is active at a time. All `wren` commands use the active profile unless overridden with explicit flags.
|
||||
|
||||
See [Profiles](../guides/profiles.md) for details.
|
||||
|
||||
### Context management
|
||||
|
||||
Manages the MDL project lifecycle — YAML authoring, validation, and compilation to `target/mdl.json`.
|
||||
|
||||
Key operations:
|
||||
- `wren context init` — scaffold a new project (or import from existing `mdl.json`)
|
||||
- `wren context validate` — check YAML structure without a database
|
||||
- `wren context build` — compile snake_case YAML to camelCase JSON
|
||||
- `wren context show` — display the current project summary
|
||||
|
||||
See [Wren Project](../guides/modeling/wren_project.md) for the project format.
|
||||
|
||||
### Memory layer
|
||||
|
||||
A LanceDB-backed semantic index with two collections:
|
||||
|
||||
| Collection | Contents | Purpose |
|
||||
|------------|----------|---------|
|
||||
| **schema_items** | Models, columns, relationships, views | Semantic schema search per question |
|
||||
| **query_history** | Confirmed NL → SQL pairs | Few-shot recall for similar questions |
|
||||
|
||||
The memory layer enables the self-learning loop: each confirmed query improves future recall accuracy.
|
||||
|
||||
See [Memory](../guides/memory.md) for details.
|
||||
|
||||
### wren-core (Rust engine)
|
||||
|
||||
The core semantic engine, written in Rust and exposed to Python via PyO3 bindings (`wren-core-py`). It handles:
|
||||
|
||||
- **SessionContext** — maintains the MDL state and provides `transform_sql()` for expanding model definitions into SQL
|
||||
- **ManifestExtractor** — filters the full MDL manifest to only the models referenced in a query, reducing planning overhead
|
||||
- **Model expansion** — resolves `table_reference` and `ref_sql` models into physical SQL, handles calculated fields, and expands relationship joins
|
||||
|
||||
The Rust engine is where the MDL semantics are enforced — it is the source of truth for how models map to SQL.
|
||||
|
||||
## Data flows
|
||||
|
||||
### Query execution
|
||||
|
||||
```
|
||||
wren --sql "SELECT customer_id, SUM(total) FROM orders GROUP BY 1"
|
||||
│
|
||||
├── 1. Discover MDL: project auto-discovery → target/mdl.json
|
||||
├── 2. Resolve connection: active profile → ~/.wren/profiles.yml
|
||||
├── 3. Plan: sqlglot parse → extract models → wren-core CTE expand → transpile
|
||||
├── 4. Execute: connector → database → PyArrow table
|
||||
└── 5. Output: format as table / csv / json
|
||||
```
|
||||
|
||||
### Project build
|
||||
|
||||
```
|
||||
wren context build
|
||||
│
|
||||
├── Read wren_project.yml + models/*/ + views/*/ + relationships.yml
|
||||
├── Validate structure and references
|
||||
├── Convert snake_case → camelCase
|
||||
└── Write target/mdl.json
|
||||
```
|
||||
|
||||
### Memory lifecycle
|
||||
|
||||
```
|
||||
wren memory index → Parse MDL, embed schema items, store in LanceDB
|
||||
wren memory fetch -q "..." → Embed query, search schema_items, return context
|
||||
wren memory recall -q "..."→ Embed query, search query_history, return examples
|
||||
wren memory store → Embed NL-SQL pair, append to query_history
|
||||
```
|
||||
|
||||
## Key dependencies
|
||||
|
||||
| Dependency | Role |
|
||||
|------------|------|
|
||||
| **wren-core-py** | Rust semantic engine (PyO3 bindings) |
|
||||
| **sqlglot** | SQL parsing, qualification, dialect transpilation |
|
||||
| **database connectors** | Data source execution layer |
|
||||
| **pyarrow** | Query result representation |
|
||||
| **lancedb** | Vector storage for memory layer |
|
||||
| **sentence-transformers** | Local embeddings for memory search |
|
||||
| **typer** | CLI framework |
|
||||
| **pydantic** | Config and connection validation |
|
||||
@@ -0,0 +1,91 @@
|
||||
---
|
||||
sidebar_label: How does Wren AI keep agents from hallucinating?
|
||||
---
|
||||
|
||||
# How does Wren AI keep agents from hallucinating?
|
||||
|
||||
> Hallucination on business data is rarely a model problem. It is a missing-context problem. Wren AI exposes correctness as a system of primitives the agent composes — not a single feature you switch on.
|
||||
|
||||
## Why "trust the model" is not enough
|
||||
|
||||
The temptation is to treat correctness like a setting: add metadata, add examples, swap to a bigger model. That does not work.
|
||||
|
||||
We have seen projects ship 100+ examples and still watch the agent pick the wrong table, hallucinate column names, or invent joins. Examples help one of six pillars. Miss any of the other five and the agent fails in that exact gap.
|
||||
|
||||
Reliable text-to-SQL needs **six primitives working together**.
|
||||
|
||||
## The six correctness pillars
|
||||
|
||||
| Pillar | What the agent needs to do | How Wren AI helps |
|
||||
|---|---|---|
|
||||
| **Schema linking** | Know which models, columns, and relationships matter for the question | MDL + `wren memory fetch` retrieves only the relevant slice |
|
||||
| **Value profiling** | Know what values actually appear in the data (`status = 4` means refunded) | Connector introspection + `instructions.md` indexed into memory |
|
||||
| **Ambiguity detection** | Know when the question needs clarification before any SQL is written | Skill orchestration — the agent stops to ask |
|
||||
| **Generation trace** | Show what context, examples, model, and join path produced the answer | `wren dry-plan` expands SQL deterministically; the trace lives in the agent's reasoning |
|
||||
| **Retry and repair** | Distinguish an MDL bug from a DB bug from a prompt bug | Structured errors at every layer; `wren dry-run` validates without executing |
|
||||
| **Eval** | Detect regressions when MDL, instructions, or schema change | Golden NL-SQL eval workflows in active development |
|
||||
|
||||
Drop any one and the agent will eventually fail in that gap.
|
||||
|
||||
## Primitives, not a closed product
|
||||
|
||||
Other systems hide correctness inside a managed text-to-SQL service and ask you to trust the dashboard. Wren AI takes the opposite stance: every primitive is exposed as a CLI command or SDK tool the agent can call directly.
|
||||
|
||||
```bash
|
||||
wren memory fetch -q "..." # retrieve relevant schema for the question
|
||||
wren memory recall -q "..." # find similar past NL-SQL pairs
|
||||
wren dry-plan --sql "..." # expand SQL and show the planned query
|
||||
wren dry-run --sql "..." # validate against the live DB without returning rows
|
||||
wren --sql "..." # execute through the modeled layer
|
||||
wren memory store --nl --sql # persist the confirmed pair
|
||||
```
|
||||
|
||||
The agent decides when to fetch, when to dry-plan, when to repair, when to ask. The trace stays inside the agent's reasoning loop, where you already review its work.
|
||||
|
||||
## Pre-aggregation as a concrete primitive
|
||||
|
||||
Pre-aggregation cubes are the clearest example of "remove the failure mode entirely."
|
||||
|
||||
Small models routinely break on hand-written `GROUP BY` + `DATE_TRUNC` + filter SQL — joins go wrong, time grain gets misread, measures double-count. Wren AI cubes let you declare a business metric once with measures, dimensions, time grains, and hierarchies. The agent queries the cube with **structured input** instead of inventing SQL.
|
||||
|
||||
For small or local models, this is the difference between a 30% error rate and a working production agent. See [Pre-aggregate with cubes](/oss/guides/cubes) for the recipe.
|
||||
|
||||
## Schema linking through MDL
|
||||
|
||||
The same logic applies one level up. Raw warehouses give the agent ambiguous joins, near-duplicate tables (`customers` vs `customers_v3` vs `loyalty_v3`), and column names that overlap across schemas. MDL collapses that to one canonical surface.
|
||||
|
||||
When the agent asks "top customers by revenue":
|
||||
|
||||
1. Memory retrieves the `customers`, `orders`, and `revenue` models — not the legacy tables.
|
||||
2. MDL exposes the approved `orders_customers` relationship — the agent does not invent a join.
|
||||
3. If `revenue` is a calculated field on `customers`, the agent uses it instead of hand-writing `SUM(amount) - SUM(refunds)`.
|
||||
|
||||
Schema linking is not a model capability — it is a context structure that lets the model link correctly.
|
||||
|
||||
## Error recovery has a layer
|
||||
|
||||
When a query fails, the agent runs two diagnoses in order:
|
||||
|
||||
| Layer | Tool | Symptom | Likely fix |
|
||||
|---|---|---|---|
|
||||
| **MDL** | `wren dry-plan` fails | Wrong model/column reference, missing relationship, malformed CTE | Update MDL or fix the agent's SQL against MDL |
|
||||
| **Database** | `dry-plan` succeeds but execution fails | Type mismatch, permission error, dialect issue | Profile/connection fix, not an MDL issue |
|
||||
|
||||
This split is small but decisive. Without it, every failure looks the same and the agent retries blindly.
|
||||
|
||||
## What "correctness as a system" means in practice
|
||||
|
||||
A correctness system is a stance, not a checkbox. Wren AI takes it seriously by:
|
||||
|
||||
- Storing context as **explicit artifacts** (MDL, instructions, queries, memory) — reviewable, versionable, Git-friendly
|
||||
- Exposing every step as a **primitive** the agent can compose
|
||||
- Keeping the **trace inside the agent's reasoning**, not in another product UI
|
||||
- Refusing to ship a single "trust me" feature in place of the six pillars
|
||||
|
||||
You compose the correctness system your business needs. Wren AI ships the parts.
|
||||
|
||||
## See also
|
||||
|
||||
- [Architecture](/oss/reference/architecture) — how the pieces fit together under the hood
|
||||
- [Pre-aggregate with cubes](/oss/guides/cubes) — the recipe for the cube primitive
|
||||
- [Refine answer quality](/oss/guides/refine) — the recipe for closing the loop with memory and instructions
|
||||
@@ -1,32 +1,111 @@
|
||||
# The memory system
|
||||
|
||||
Wren AI's memory layer is the second of five layers of context — the place where successful natural-language-to-SQL pairs, prior interactions, and user feedback accumulate so the agent gets better at querying your data the more it is used.
|
||||
Memory is the behavioral layer of Wren AI's context system.
|
||||
|
||||
Memory is local. It is stored under `.wren/memory/` in your project directory, indexed with [LanceDB](https://lancedb.com/), and never leaves your machine unless you commit it to a shared Git repository.
|
||||
MDL tells an agent what your data means. Instructions tell it how your team wants that data used. Memory tells it what has worked before: which schema items were relevant, which SQL answered a similar question, and which examples your team has already confirmed.
|
||||
|
||||
## What lives in memory
|
||||
Without memory, every question starts from zero. With memory, each accepted answer can make the next answer easier to ground.
|
||||
|
||||
- **NL-SQL pairs** — `("How many customers placed more than one order?", "SELECT ... FROM customers ...")` — stored when an agent runs a query that succeeds.
|
||||
- **Pinned business questions** — questions you mark as canonical examples; these are weighted higher during recall.
|
||||
- **Schema and column descriptions** — extracted from your MDL so retrieval can match both questions and structure.
|
||||
- **Instructions** — content from `instructions.md` is indexed alongside the rest so retrieval can surface relevant rules.
|
||||
## Why memory matters
|
||||
|
||||
## How recall works
|
||||
Business questions repeat with small variations:
|
||||
|
||||
When the agent needs to answer a new question, it first asks the memory layer for the most relevant context:
|
||||
- "Top customers by revenue this month"
|
||||
- "Top accounts by ARR this quarter"
|
||||
- "Revenue by customer segment, excluding refunds"
|
||||
- "Monthly active users, but only for paid workspaces"
|
||||
|
||||
1. `wren memory fetch --query "..."` returns the most likely tables, columns, and relationships
|
||||
2. `wren memory recall --query "..."` returns the most similar past NL-SQL pairs
|
||||
3. The agent reads both and uses them as the grounding for its SQL generation
|
||||
An agent should not rediscover the same joins, filters, and metric definitions every time. It should be able to retrieve the relevant parts of the context layer and reuse proven examples.
|
||||
|
||||
The more queries you and your team run, the more reliable recall becomes.
|
||||
That is what Wren AI memory provides.
|
||||
|
||||
## What memory stores
|
||||
|
||||
Memory is local to a Wren project. It is stored under `.wren/memory/`, indexed with [LanceDB](https://lancedb.com/), and never leaves your machine unless you choose to share or commit it.
|
||||
|
||||
The memory layer has two main collections:
|
||||
|
||||
| Collection | What it stores | Why it matters |
|
||||
| --- | --- | --- |
|
||||
| `schema_items` | Models, columns, relationships, views, cubes, and indexed instructions | Lets the agent retrieve the right context for a question without sending the entire project into the prompt. |
|
||||
| `query_history` | Confirmed natural-language-to-SQL pairs | Gives the agent few-shot examples from your actual business, not generic examples. |
|
||||
|
||||
Memory may include:
|
||||
|
||||
- schema and column descriptions extracted from MDL
|
||||
- relevant content from `instructions.md`
|
||||
- successful natural-language-to-SQL pairs
|
||||
- imported examples from `queries.yml`
|
||||
- query history stored after successful agent workflows
|
||||
|
||||
## How memory is used
|
||||
|
||||
When an agent answers a question through Wren AI, memory usually participates before SQL is written:
|
||||
|
||||
```text
|
||||
User question
|
||||
|
|
||||
|-- wren memory recall -q "..." -> find similar accepted questions and SQL
|
||||
|-- wren memory fetch -q "..." -> find relevant models, columns, relationships, and instructions
|
||||
|-- Agent writes SQL against MDL objects
|
||||
|-- Wren AI plans and executes the query
|
||||
|-- wren memory store -> save confirmed NL-SQL pair
|
||||
```
|
||||
|
||||
This loop gives the agent two kinds of grounding:
|
||||
|
||||
- **Relevant context** - the parts of the model and instructions that matter for this question.
|
||||
- **Proven behavior** - examples of how similar questions were answered before.
|
||||
|
||||
## Memory is not a replacement for MDL
|
||||
|
||||
Memory does not define your semantic layer. MDL does.
|
||||
|
||||
Memory helps agents find and reuse context, but the durable contract still lives in project files: models, relationships, views, cubes, and instructions. If a definition is important enough to govern future behavior, put it in MDL or `instructions.md`, then re-index memory.
|
||||
|
||||
Think of memory as the retrieval and learning layer on top of the contract.
|
||||
|
||||
## What improves over time
|
||||
|
||||
A traditional text-to-SQL prompt has a fixed ceiling: the model sees the schema and tries its best.
|
||||
|
||||
Wren AI memory lets the system compound:
|
||||
|
||||
- common questions retrieve better examples
|
||||
- recurring metrics reuse accepted SQL patterns
|
||||
- schema retrieval becomes more targeted on large projects
|
||||
- corrections can become future grounding instead of disappearing after the chat
|
||||
- teams can seed memory with known-good `queries.yml` examples
|
||||
|
||||
The goal is not to memorize every answer. The goal is to make the agent better at finding the right context before it reasons.
|
||||
|
||||
## When to re-index
|
||||
|
||||
Memory is automatically updated when you store a new pair (`wren memory store`), but the full LanceDB index is only rebuilt when you run `wren memory index`. Re-index after:
|
||||
`wren memory store` adds a new confirmed NL-SQL pair to query history. But the schema and instruction index is rebuilt with:
|
||||
|
||||
- bulk-editing `instructions.md`
|
||||
- changing model descriptions in `models/*/metadata.yml`
|
||||
- importing a large batch of seed NL-SQL examples
|
||||
```bash
|
||||
wren memory index
|
||||
```
|
||||
|
||||
See `wren memory --help` for the full set of commands.
|
||||
Re-index after:
|
||||
|
||||
- editing model descriptions, columns, relationships, views, or cubes
|
||||
- changing `instructions.md`
|
||||
- importing or editing seed examples in `queries.yml`
|
||||
- running a major context enrichment pass
|
||||
|
||||
See the [Refine answer quality](/oss/guides/refine) recipe and [CLI reference](/oss/reference/cli#wren-memory--schema--query-memory) for command details.
|
||||
|
||||
## Sharing memory
|
||||
|
||||
By default, `.wren/memory/` is local runtime state and is usually gitignored.
|
||||
|
||||
If your team wants to share confirmed examples, prefer exporting them to `queries.yml` with `wren memory dump`, reviewing them like source files, and loading them back into memory in each environment. This keeps the useful behavioral context portable without turning binary index files into the main collaboration surface.
|
||||
|
||||
## In short
|
||||
|
||||
- **MDL** defines the business meaning.
|
||||
- **Instructions** define guidance and policy.
|
||||
- **Memory** retrieves relevant context and recalls proven examples.
|
||||
|
||||
Memory is how Wren AI gets better with use while keeping the source of truth inspectable and versionable.
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
# How agents use Wren AI (Skills)
|
||||
|
||||
Wren AI ships with a small set of **skills** — structured workflows that tell an AI coding agent (Claude Code, Openclaw, Hermes, Codex, etc.) how to operate the `wren` CLI without having to memorize commands.
|
||||
|
||||
A skill is a markdown file with metadata that the agent reads before acting. Skills are installed once per project with `npx skills add Canner/WrenAI --skill '*'`, and from then on the agent picks the right skill for each user request — generating an MDL from a new database, querying through the semantic layer, enriching context from your team docs, and so on.
|
||||
|
||||
Two skills are central to the workflow:
|
||||
|
||||
- `wren-generate-mdl` — one-time scaffolding. The agent explores your database, normalizes types, and writes an initial MDL project.
|
||||
- `wren-usage` — day-to-day querying. The agent gathers context, recalls past queries, writes SQL through the semantic layer, executes, and stores successful pairs back into memory.
|
||||
|
||||
A third skill, **`wren-enrich-context`**, is in active development. It is the second beat of the "scaffold fast, enrich deep" workflow — once your MDL covers structure, enrich-context fills in business meaning (what `status = 4` really means, which table is canonical, how internal project codenames map to data) by either grilling you one question at a time, or by ingesting your team's raw docs in auto-pilot mode.
|
||||
@@ -0,0 +1,84 @@
|
||||
---
|
||||
sidebar_label: Where does Wren AI sit in my stack?
|
||||
---
|
||||
|
||||
# Where does Wren AI sit in my stack?
|
||||
|
||||
> Wren AI does not replace your warehouse, your transformation pipeline, or your existing semantic layer. It sits **between** your data infrastructure and the agents querying it, providing the context they need to do it safely.
|
||||
|
||||
## The short version
|
||||
|
||||
```text
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ Your AI agents (Claude Code, Cursor, custom apps) │
|
||||
└────────────────────────┬─────────────────────────────┘
|
||||
│ ask questions, get context
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ Wren AI — open context layer │
|
||||
│ MDL · Memory · Skills · Governed execution │
|
||||
└────────────────────────┬─────────────────────────────┘
|
||||
│ planned, governed SQL
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ Your warehouse, transformation pipeline, files │
|
||||
│ (PostgreSQL, BigQuery, Snowflake, DuckDB, ...) │
|
||||
└──────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Three things sit above Wren AI: the **agents** that ask questions. Three things sit below: the **data infrastructure** that stores the answers. Wren AI is the layer in between that turns "I can see schema" into "I know what the business means."
|
||||
|
||||
## What it does NOT replace
|
||||
|
||||
**Your data warehouse.** Wren AI does not store rows. Your warehouse keeps storing rows. Wren AI sends planned SQL there for execution.
|
||||
|
||||
**Your transformation pipeline.** If you already model raw data into clean tables — dbt, custom Python, scheduled SQL — keep doing that. Wren AI reads the result, it does not own the upstream pipeline.
|
||||
|
||||
**Your existing semantic layer.** If you already have business-facing models, metrics, or a metric layer, Wren AI can layer on top to give agents the same definitions without rebuilding them. The MDL you author is the **agent-facing contract**; what you already have stays where it lives.
|
||||
|
||||
**Your BI or dashboard tool.** Wren AI is built for autonomous consumers (agents, scripts, embedded apps). Dashboards keep using whatever you already use.
|
||||
|
||||
## What it does provide
|
||||
|
||||
**The agent-facing context layer.** The five layers — structural, semantic, business, operational, behavioral — collected into one inspectable, version-controlled surface that any agent can query.
|
||||
|
||||
**A governed SQL plane.** The CLI plans modeled SQL into executable SQL, runs dry-plan / dry-run, applies access policies, and executes through your warehouse connectors. The agent does not need direct database credentials or unrestricted access.
|
||||
|
||||
**An agent-native interface.** Skills, an SDK for popular agent frameworks, and a CLI built to be driven by an LLM-based coding agent. None of it requires a new UI to maintain.
|
||||
|
||||
## Where Wren AI fits depending on what you already have
|
||||
|
||||
### You have no semantic layer
|
||||
|
||||
Wren AI can be your first one. The `wren-generate-mdl` skill scaffolds an MDL project from your warehouse schema in a few minutes. Enrich it over time with the grill / auto-pilot workflow.
|
||||
|
||||
### You have a transformation pipeline (dbt, Coalesce, in-house)
|
||||
|
||||
Keep it. Point Wren AI at the **output tables** of your pipeline. The MDL describes the agent-facing meaning of those tables — what columns to expose, which joins are approved, which calculations are reusable. The pipeline keeps owning ingestion and modeling logic. Wren AI owns the layer between modeled data and the agent.
|
||||
|
||||
### You have a semantic layer
|
||||
|
||||
Wren AI does not compete with it for the data team. It gives the **agents** the same definitions through a structure agents can read and reason about: MDL files, structured retrieval, memory of past answers, governed execution primitives. Think of it as the agent-native projection of the semantic layer you already use.
|
||||
|
||||
### You have multiple warehouses
|
||||
|
||||
Profiles separate connection credentials from project definitions. The same MDL project can be bound to dev / staging / prod profiles. The MDL stays portable; the profile carries the credentials.
|
||||
|
||||
## Where Wren AI does not fit
|
||||
|
||||
- **You only need a chat-driven BI app.** Wren AI is a primitive layer, not a chat UI. If you want a turnkey conversational dashboard, the commercial Wren AI product or another vendor will be a better fit.
|
||||
- **You want zero schema modeling.** Even the scaffold step asks for some review. If "auto-magic with no review" is the requirement, no context layer will be honest with you.
|
||||
- **You query mostly unstructured text.** Wren AI focuses on structured business data. RAG over docs is a separate problem.
|
||||
|
||||
## Why "layered, not replacing"
|
||||
|
||||
Replacing your stack to get an AI agent that queries it well is a fast way to make nobody happy. The pattern Wren AI was designed around is the inverse: **leave the existing stack in place, add one inspectable layer on top, give every agent the same governed surface**.
|
||||
|
||||
That is also why Wren AI is open source. Business context is too important to lock inside a vendor product — your MDL, examples, query history, and mapping decisions should live in your repo, under your team's review.
|
||||
|
||||
## See also
|
||||
|
||||
- [What does Wren AI mean by context?](./what_is_context.md) — the conceptual ground
|
||||
- [Architecture](/oss/reference/architecture) — the technical stack inside Wren AI
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at your warehouse
|
||||
- [Manage project](/oss/guides/manage_project) — multi-environment profile workflow
|
||||
@@ -1,80 +1,141 @@
|
||||
# What is context?
|
||||
|
||||
Your AI agent does not know what your data means. It reads schemas. It catches column names. It even reads your semantic-layer YAML. But it misses the things that actually decide whether an answer is right — that `status = 4` means refunded, that `loyalty_v3` is the table your team actually uses, that "monthly active users" excludes service accounts, that "Project Lighthouse" was renamed to `campaign_id = 4172` six months ago in a doc nobody linked to the warehouse.
|
||||
Context is the difference between an agent that can see your database and an agent that can understand your business.
|
||||
|
||||
So it picks the wrong table. It writes confident, plausible, wrong SQL. The demo looks fine. The pilot looks fine. Production is where it breaks.
|
||||
A schema tells an agent that a table has columns. Context tells it which table is canonical, what the columns mean, which joins are approved, which definitions your company trusts, and what has worked before.
|
||||
|
||||
**AI agents over business data are bottlenecked on context, not on intelligence.** Wren AI exists to close that gap.
|
||||
That distinction matters because AI agents do not fail on business data only because they are not smart enough. They fail because the meaning they need is scattered across warehouses, dashboards, SQL files, docs, decks, Slack threads, and people's heads.
|
||||
|
||||
Wren AI exists to turn that scattered meaning into an open, machine-readable context layer that humans, agents, dashboards, and applications can share.
|
||||
|
||||
## Why schema is not enough
|
||||
|
||||
Your agent sees schema. It reads column names, catches types, and may even parse semantic-layer YAML. But schema does not tell the whole story:
|
||||
|
||||
- `status = 4` means refunded
|
||||
- `loyalty_v3` is the table your team actually uses
|
||||
- "monthly active users" excludes service accounts
|
||||
- "Project Lighthouse" maps to `campaign_id = 4172`
|
||||
- some joins are approved, while others produce misleading numbers
|
||||
- some questions should be clarified before any SQL is written
|
||||
|
||||
Without that context, the agent guesses. It picks a plausible table, writes plausible SQL, and returns a plausible answer. The demo may look fine. Production is where the missing meaning shows up.
|
||||
|
||||
**AI agents over business data are bottlenecked on context, not on intelligence.**
|
||||
|
||||
## The five layers of context
|
||||
|
||||
For an AI agent to answer real business questions on real company data, it needs five layers of knowledge — not one.
|
||||
For an agent to answer real business questions on real company data, it needs five layers of context:
|
||||
|
||||
1. **Structured business semantics.** What your schema means in business terms — display names, descriptions, synonyms, enum labels, relationships, metrics, business rules. Today this lives in MDL.
|
||||
| Layer | What it answers | Examples | Status |
|
||||
| --- | --- | --- | --- |
|
||||
| **Structural** | What data exists? | Tables, columns, types, keys, relationships | Ships today |
|
||||
| **Semantic** | What does the data mean? | Models, metrics, calculated fields, enum labels, canonical tables | Ships today |
|
||||
| **Business** | What does this company mean? | Active customer, revenue, churn, internal project names, team-specific definitions | Ships today |
|
||||
| **Operational** | How should this data be used safely? | Approved join paths, sanctioned queries, query-time governance, things never to compute | In active development |
|
||||
| **Behavioral** | What worked before? | Successful natural-language-to-SQL pairs, examples, feedback, memory | In active development |
|
||||
|
||||
2. **Examples and memory.** The successful NL-SQL pairs, prior interactions, user feedback, and pinned business questions that teach the agent what *correct* looks like in your specific environment. Today this lives in the memory layer.
|
||||
The first layer lets an agent read the database. The next two layers let it understand the business. The last two layers help it act safely and improve over time.
|
||||
|
||||
3. **Governance and skills.** Access control, read-only enforcement, audit, query gating, agent skills, default query patterns. What makes context safe to expose to an autonomous system. Today this lives in profiles, skills, and the CLI's safety primitives.
|
||||
|
||||
4. **Unstructured corporate knowledge.** The docs, emails, chat threads, wikis, and SOPs where business definitions and project codenames live before they ever appear in a table. *(Actively in development — `wren-enrich-context` skill in auto-pilot mode.)*
|
||||
|
||||
5. **Cross-modal alignment.** The bridge between layer 4 and layer 1 — mappings from "Project Lighthouse" to `campaign_id = 4172`, from "Northstar metric" to a CTE the analytics team agreed on last quarter. *(Actively in development.)*
|
||||
|
||||
Layers 1–3 ship today. Layers 4–5 are gated by a synthetic-corpus validation experiment before they reach alpha.
|
||||
Together, these layers form the context layer.
|
||||
|
||||
## Context vs. semantic layer
|
||||
|
||||
The traditional **semantic layer** was the industry's answer to text-to-SQL for *dashboards*. The audience was a human — or a BI tool that tolerated a slow setup because the payoff lived in long-lived charts.
|
||||
A semantic layer is one important part of context. It defines business-facing models, relationships, calculations, and reusable logic so people and tools do not have to query raw tables directly.
|
||||
|
||||
In an AI-native world the audience is different: an agent, a coding assistant, an application that needs structured context in real time. Agents do not click buttons. Agents do not consult a metric catalogue. They need context delivered as primitives they can reason over — and they need it fast enough that the journey from "connect a database" to "first correct answer" is minutes, not weeks.
|
||||
A context layer is broader. It includes the semantic layer, then adds the knowledge an autonomous agent needs to behave well in the real world:
|
||||
|
||||
**Wren AI is a context layer.** The distinction from a semantic layer is small in words and large in consequence: a context layer is a *superset* of a semantic layer, adding the four other layers an autonomous system needs to act correctly.
|
||||
- which definitions are trusted
|
||||
- which tables should be preferred
|
||||
- which values mean what
|
||||
- which joins are allowed
|
||||
- when to ask a clarification
|
||||
- which past examples should guide the next query
|
||||
- how to validate, retry, repair, and evaluate generated SQL
|
||||
|
||||
## What Wren AI gives AI workflows
|
||||
Traditional semantic layers were designed mostly for dashboards and BI workflows. Wren AI is designed for a world where agents, applications, and humans all need the same trusted answer through different interfaces.
|
||||
|
||||
The five layers above turn into concrete benefits for any agent built on top of them:
|
||||
## How Wren AI represents context
|
||||
|
||||
### Shared business context (layer 1)
|
||||
Wren AI does not treat context as a single prompt or a hidden product feature. It stores context in explicit, reviewable pieces.
|
||||
|
||||
MDL captures the meaning of your data in a form both humans and AI agents can use — business entities, relationships, reusable calculations, curated dataset structure. An agent can map "top customers by revenue" to the right models, joins, and metrics without reconstructing logic from raw schema.
|
||||
### MDL: the semantic contract
|
||||
|
||||
### More reliable text-to-SQL planning (layers 1 + 5)
|
||||
[Modeling Definition Language (MDL)](/oss/concepts/what_is_mdl) is the core semantic contract. It describes models, relationships, calculated fields, views, and business-facing structure in files your team can read and version.
|
||||
|
||||
LLMs are good at pattern matching, weak at domain-specific modeling rules. Explicit structure cuts incorrect joins, misuse of similarly named columns, duplicated metric definitions, and brittle query generation based on incomplete schema interpretation.
|
||||
MDL helps an agent map a question like "top customers by revenue" to the right models, joins, and calculations instead of reconstructing logic from raw warehouse structure.
|
||||
|
||||
### Better RAG context (layers 1 + 2)
|
||||
### Instructions: business and operational guidance
|
||||
|
||||
RAG works when retrieved context is structured, relevant, and grounded in how the business actually defines data. Wren exposes modeled entities, documented relationships, and reusable logic — higher-quality fuel for retrieval than raw database metadata.
|
||||
Project instructions capture guidance that may not belong in a model definition: preferred terminology, default filters, table selection rules, caveats, and policies the agent should follow.
|
||||
|
||||
### Consistent answers across tools and agents (layer 1)
|
||||
This is where business meaning starts to become operational. The agent is not only told what exists; it is told how your team expects the data to be used.
|
||||
|
||||
When multiple AI agents or applications access the same modeled context, they reason from the same definitions. One place to define how metrics, dimensions, and relationships behave; consistency by design.
|
||||
### Queries and memory: examples that compound
|
||||
|
||||
### Governed access to data (layer 3)
|
||||
Most text-to-SQL systems treat every question like the first question. Wren AI adds a [memory layer](/oss/concepts/memory_system) so successful work can improve future work.
|
||||
|
||||
AI systems should not have unlimited freedom over every object in a warehouse. Operating against modeled data definitions instead of arbitrary warehouse exploration limits the working surface area, makes approved objects explicit, and keeps business logic in a reviewable form.
|
||||
Memory has two jobs:
|
||||
|
||||
### Memory and self-learning (layer 2)
|
||||
- **Schema context retrieval** - index MDL and instructions, then retrieve the relevant models, columns, relationships, and guidance for each question.
|
||||
- **Query recall** - store confirmed natural-language-to-SQL pairs so similar future questions can use proven examples.
|
||||
|
||||
Most text-to-SQL systems treat every question as if it were the first. Wren AI breaks that pattern with a built-in [memory layer](/oss/concepts/memory_system) that learns from successful queries:
|
||||
This turns usage into a learning loop. The context layer becomes more useful as your team asks, corrects, and confirms more questions.
|
||||
|
||||
- **Schema context retrieval** — the memory layer indexes your MDL and retrieves only the relevant models, columns, and relationships for each question. Embedding search for large schemas; full text for small.
|
||||
- **Query recall** — every confirmed NL-SQL pair is stored as a few-shot example. The more questions you ask, the more accurate future answers become — without retraining a model or writing custom prompts.
|
||||
### Skills: repeatable agent workflows
|
||||
|
||||
A traditional text-to-SQL pipeline has a fixed accuracy ceiling determined by the LLM. With memory, that ceiling rises with usage.
|
||||
[Skills](/oss/reference/skills) give AI coding agents structured workflows for working with Wren AI. Instead of asking an agent to improvise every step, skills guide it through repeatable actions such as onboarding, generating MDL, validating context, and querying safely.
|
||||
|
||||
## Why this cannot be solved one feature at a time
|
||||
Skills matter because context is not only data. Context is also procedure: when to inspect, when to validate, when to ask, when to store, and when to stop.
|
||||
|
||||
The temptation is to treat correctness like a setting. Add a metadata field. Add 100 examples. Flip a switch.
|
||||
## What context unlocks
|
||||
|
||||
That does not work. Correctness is the result of [six pieces working together](/oss/concepts/architecture): schema linking, value profiling, ambiguity detection, generation trace, retry and repair, and eval. Miss any one of them and the agent fails in that exact gap.
|
||||
When context is explicit and shared, the same governed layer can serve many surfaces:
|
||||
|
||||
That is why we build context as a system, not as a feature — and why Wren AI exposes **primitives**, not a closed product. The agent does the orchestration. The trace lives where the agent's reasoning lives.
|
||||
- **AI agents** can query business data without inventing joins or metrics.
|
||||
- **Data teams** can keep definitions in version-controlled files instead of scattered prompts and dashboard settings.
|
||||
- **Business users** can get answers that trace back to approved models and definitions.
|
||||
- **Product teams** can embed analytics into customer-facing apps without building a one-off data logic layer.
|
||||
- **Platform teams** can give agents access to data through a narrower, more governable surface.
|
||||
|
||||
The end state is not just faster answers. It is faster answers that your team can trust.
|
||||
|
||||
## Correctness needs a system
|
||||
|
||||
Context is the foundation, but correctness still requires a system around it.
|
||||
|
||||
Reliable text-to-SQL depends on several primitives working together:
|
||||
|
||||
- **Schema linking** - find the right models and columns for the question.
|
||||
- **Value profiling** - understand what values actually appear in the data.
|
||||
- **Ambiguity detection** - know when the question needs clarification.
|
||||
- **Generation trace** - show how the answer was built.
|
||||
- **Retry and repair** - recover when the first attempt fails.
|
||||
- **Eval** - detect regressions as definitions and schemas change.
|
||||
|
||||
Wren AI exposes these as primitives the agent can orchestrate instead of hiding correctness inside a closed product. See [How does Wren AI keep agents from hallucinating?](/oss/concepts/correctness) for the deeper view and [Architecture](/oss/reference/architecture) for the technical breakdown.
|
||||
|
||||
## Where context comes from
|
||||
|
||||
The first version of context usually comes from the database. Wren AI can scaffold MDL from tables, columns, types, and relationships so the agent has a working structural and semantic layer quickly.
|
||||
|
||||
The deeper context comes from everywhere else:
|
||||
|
||||
- analyst-written SQL
|
||||
- business glossaries
|
||||
- metric definitions
|
||||
- onboarding docs
|
||||
- product specs
|
||||
- decks and strategy docs
|
||||
- past questions and accepted answers
|
||||
- human corrections and review
|
||||
|
||||
That is why Wren AI is designed around the workflow **scaffold fast, then enrich deep**. Start with the structure, then bring in the business meaning that makes the answers trustworthy.
|
||||
|
||||
## In short
|
||||
|
||||
- **Context** = the full set of information an AI agent needs to operate reliably on business data.
|
||||
- **Semantic layer** = one slice of that picture (layer 1).
|
||||
- **Context layer** = all five layers, designed for autonomous agents instead of humans clicking buttons.
|
||||
- **Schema** tells an agent what exists.
|
||||
- **Semantic layer** tells an agent what the data means.
|
||||
- **Context layer** tells an agent how the business uses the data, how to act safely, and what has worked before.
|
||||
|
||||
That is the shift Wren AI is built around.
|
||||
Wren AI is the open context layer for AI agents: portable, inspectable, versionable, and shared across every agent and app that needs trusted business data.
|
||||
|
||||
@@ -1,67 +1,122 @@
|
||||
# What is Modeling Definition Language (MDL)?
|
||||
|
||||
Modeling Definition Language (MDL) is the way Wren AI describes business data in a structured, machine-readable form. It defines models, relationships, calculations, and views so that both humans and AI agents can work from the same business context.
|
||||
Modeling Definition Language (MDL) is the semantic contract at the center of Wren AI.
|
||||
|
||||
Instead of exposing only raw tables and columns, MDL gives your data a logical shape. It tells Wren AI how datasets relate to each other, how business metrics should be defined, and how analytical logic should be reused across queries.
|
||||
It is how you tell agents, applications, and humans what your business data means: which datasets exist, which fields are exposed, how entities relate, which calculations are reusable, and which query-shaped objects should be treated as stable interfaces.
|
||||
|
||||
## Why MDL matters
|
||||
Raw schemas describe storage. MDL describes meaning.
|
||||
|
||||
Raw schemas are not enough for reliable analytics or AI-driven querying. A warehouse may contain hundreds of tables, inconsistent naming, and business logic scattered across dashboards or SQL scripts. MDL helps centralize that logic into a form that is easier to understand, review, and execute.
|
||||
## Why MDL exists
|
||||
|
||||
With MDL, Wren AI can provide AI agents with the context they need to:
|
||||
Warehouses are optimized for systems that store data, not for people and agents trying to reason about the business.
|
||||
|
||||
- understand business entities and terminology
|
||||
- follow defined relationships between datasets
|
||||
- reuse approved calculations and aggregations
|
||||
- generate more reliable SQL from natural language
|
||||
A warehouse can tell an agent that a table has a column named `status`, but not that `status = 4` means refunded. It can expose `loyalty_v3`, but not explain that this is the canonical loyalty table. It can show foreign keys, but not always the join path your analytics team trusts.
|
||||
|
||||
Without MDL, every agent, dashboard, SQL script, and embedded analytics feature has to rediscover the same logic from raw structure. That leads to duplicated definitions, inconsistent metrics, brittle SQL, and answers no one fully trusts.
|
||||
|
||||
MDL makes the important parts explicit. It turns business logic into files your team can review, version, and share.
|
||||
|
||||
## MDL in the context layer
|
||||
|
||||
Wren AI is the open context layer for AI agents. MDL is the core layer where structural, semantic, and business meaning become machine-readable.
|
||||
|
||||
In the five-layer context model, MDL carries the first three layers:
|
||||
|
||||
| Context layer | How MDL helps |
|
||||
| --- | --- |
|
||||
| **Structural** | Defines the datasets, columns, types, keys, and relationships the agent can use. |
|
||||
| **Semantic** | Gives raw warehouse objects business-facing names, descriptions, calculations, views, and cubes. |
|
||||
| **Business** | Captures canonical tables, reusable metrics, relationship meaning, and agreed analytical interfaces. |
|
||||
|
||||
Operational guidance and behavioral memory live alongside MDL in project instructions, skills, and the memory layer. Together, they give agents the wider context they need to query safely and improve over time.
|
||||
|
||||
## What MDL defines
|
||||
|
||||
MDL is used to model the business-facing structure of your data. Depending on your use case, it can define:
|
||||
MDL models the business-facing shape of your data. A Wren project stores these definitions as readable YAML and compiles them into an engine-ready `target/mdl.json` manifest.
|
||||
|
||||
- models that reference physical tables or query results
|
||||
- columns and their expressions
|
||||
- relationships between models
|
||||
- calculated fields and reusable metrics
|
||||
- views built on top of modeled datasets
|
||||
Core MDL objects include:
|
||||
|
||||
This gives Wren AI a consistent representation of how your data should behave, rather than forcing every user or agent to rediscover that logic from scratch.
|
||||
- **Models** - logical datasets backed by physical tables or SQL definitions.
|
||||
- **Columns** - exposed fields, including renamed fields, expressions, primary keys, and calculated fields.
|
||||
- **Relationships** - reusable join logic between models.
|
||||
- **Calculated fields** - business logic defined once and reused across queries.
|
||||
- **Views** - named SQL statements that behave like stable virtual tables.
|
||||
- **Cubes** - structured aggregation objects with measures, dimensions, time dimensions, and hierarchies.
|
||||
|
||||
See the [MDL schema reference](/oss/reference/mdl) for the full field surface of every modeling object.
|
||||
|
||||
## MDL as a contract
|
||||
|
||||
The word contract matters.
|
||||
|
||||
MDL is not just documentation. It is the agreement between your data team, your agents, and your query engine.
|
||||
|
||||
- **For data teams**, MDL is a reviewable place to define business logic.
|
||||
- **For agents**, MDL is the structured context used to choose models, joins, and calculations.
|
||||
- **For applications**, MDL is a stable interface over changing warehouse structure.
|
||||
- **For the engine**, MDL is the source of truth for planning modeled SQL against the underlying data source.
|
||||
|
||||
When the contract changes, you can review the diff. When a query runs, Wren AI can plan against the contract. When another agent joins the workflow, it does not need to learn the business from scratch.
|
||||
|
||||
## How MDL helps AI agents
|
||||
|
||||
AI agents perform better when they can reason over structured context instead of guessing from raw schema alone. MDL helps by giving Wren AI an explicit description of your business layer.
|
||||
AI agents are good at pattern matching, but raw schemas leave too much room for interpretation. MDL narrows that space.
|
||||
|
||||
That improves agent behavior in several ways:
|
||||
With MDL, an agent can:
|
||||
|
||||
- better mapping from business questions to data models
|
||||
- fewer incorrect joins and ambiguous field selections
|
||||
- more consistent metric definitions across queries
|
||||
- clearer grounding for text-to-SQL and RAG workflows
|
||||
- map business questions to the right modeled datasets
|
||||
- prefer canonical tables over legacy or staging tables
|
||||
- follow defined relationships instead of inventing joins
|
||||
- reuse approved calculations instead of creating one-off metrics
|
||||
- query views and cubes as stable analytical interfaces
|
||||
- ground retrieval and text-to-SQL planning in explicit business structure
|
||||
|
||||
In this sense, MDL is one of the core building blocks that lets Wren AI act as an open context layer for AI agents.
|
||||
The result is not magic accuracy. It is better grounding. MDL gives the agent fewer reasons to guess.
|
||||
|
||||
## Benefits of MDL
|
||||
## Why files matter
|
||||
|
||||
### 1. Shared definitions
|
||||
MDL lives in files because business context should be portable.
|
||||
|
||||
MDL creates a single, reviewable place to define business logic. Teams can align on the meaning of models, relationships, and metrics instead of duplicating that logic across prompts, dashboards, and SQL files.
|
||||
Your definitions should not be trapped inside one BI tool, one prompt, or one vendor UI. They should be easy to inspect, commit, review, fork, and deploy across environments.
|
||||
|
||||
### 2. Reusable modeling logic
|
||||
A Wren project separates the parts that should move with the project from the parts that belong to an environment:
|
||||
|
||||
Once a relationship or calculation is defined in MDL, it can be reused across workflows. This reduces repeated SQL logic and makes analytical behavior more consistent.
|
||||
- Models, views, relationships, cubes, and instructions live in the project and can be version controlled.
|
||||
- Connection profiles live outside the project, so credentials and environment-specific settings do not leak into shared files.
|
||||
- The compiled `target/mdl.json` is derived from source YAML and can be rebuilt.
|
||||
|
||||
### 3. Better collaboration
|
||||
See [Manage project](/oss/guides/manage_project) for the project structure and lifecycle commands.
|
||||
|
||||
Because MDL is structured and explicit, it is easier for data teams to review, maintain, and improve over time. It also makes the business context more accessible to non-authors, including AI systems.
|
||||
## From raw schema to trusted context
|
||||
|
||||
### 4. More reliable execution
|
||||
MDL usually starts with scaffolding. The `wren-generate-mdl` skill can inspect a database, normalize types, detect structure, and generate an initial project so the agent can query through a modeled layer quickly.
|
||||
|
||||
Wren AI can plan and generate queries more reliably when it has modeled definitions to work from. This helps reduce errors caused by incomplete schema interpretation or one-off query logic.
|
||||
That first pass is useful, but it is only the beginning. The deeper value comes when your team enriches the model:
|
||||
|
||||
### 5. A stronger foundation for agentic analytics
|
||||
- add descriptions and business names
|
||||
- mark primary keys and relationships clearly
|
||||
- define reusable calculations
|
||||
- publish views for common analytical paths
|
||||
- define cubes for governed aggregations
|
||||
- hide or avoid fields that should not be exposed
|
||||
- document canonical sources and business rules
|
||||
|
||||
If you want AI agents to operate on business data safely and accurately, they need more than access. They need context. MDL gives Wren AI that context in a durable, portable form.
|
||||
This is the same philosophy as the broader Wren AI workflow: **scaffold fast, then enrich deep**.
|
||||
|
||||
## MDL and execution
|
||||
|
||||
MDL is not only metadata for prompts. Wren AI uses MDL during SQL planning.
|
||||
|
||||
When a query references modeled objects, Wren AI expands those models, relationships, calculated fields, and views into executable SQL for the target data source. The Rust semantic engine is the source of truth for how MDL semantics map to SQL.
|
||||
|
||||
This matters because agent reliability depends on more than generating SQL text. The query needs to be planned against the same definitions your team agreed on.
|
||||
|
||||
See [Architecture](/oss/reference/architecture) for how planning and execution work.
|
||||
|
||||
## In short
|
||||
|
||||
MDL is the modeling language that powers Wren AI. It turns raw data structures into usable business context, making analytics workflows easier to govern for people and easier to reason over for AI agents.
|
||||
- **Schema** describes how data is stored.
|
||||
- **MDL** describes how data should be understood and queried.
|
||||
- **Context** combines MDL with instructions, memory, skills, and governance so agents can operate reliably.
|
||||
|
||||
MDL is the durable semantic contract for Wren AI: readable by humans, usable by agents, enforceable by the engine, and portable across every app that needs trusted business data.
|
||||
|
||||
@@ -32,9 +32,7 @@ curl -fsSL https://raw.githubusercontent.com/Canner/WrenAI/main/skills/install.s
|
||||
|
||||
**Start a new agent session** (skills load at session start), open your project directory, and ask:
|
||||
|
||||
```text
|
||||
Use the wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
Use the `/wren-onboarding` skill to install and set up Wren AI.
|
||||
|
||||
The agent will check your environment, install Python dependencies, create a connection profile for your data source, scaffold the project, and run a first query — all in one flow.
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: AdaL
|
||||
---
|
||||
|
||||
# Install Wren AI with AdaL
|
||||
|
||||
A lightweight coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [AdaL](https://github.com/vercel-labs/skills) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent adal
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in AdaL, then start a new chat session.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: AiderDesk
|
||||
---
|
||||
|
||||
# Install Wren AI with AiderDesk
|
||||
|
||||
A desktop UI for the Aider coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [AiderDesk](https://github.com/hotovo/aider-desk) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent aider-desk
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Launch the AiderDesk app, then `File → Open Folder...` to open your project and start a new chat.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
sidebar_label: Amp
|
||||
---
|
||||
|
||||
# Install Wren AI with Amp
|
||||
|
||||
Sourcegraph's coding agent. Uses the shared `.agents/skills/` directory.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Amp](https://ampcode.com) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent amp
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
amp
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
sidebar_label: Antigravity
|
||||
---
|
||||
|
||||
# Install Wren AI with Antigravity
|
||||
|
||||
Google's AI development workspace.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Antigravity](https://antigravity.google) installed and authenticated.
|
||||
- A Google account login is required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent antigravity
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in Antigravity, then start a new agent session.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
sidebar_label: Augment
|
||||
---
|
||||
|
||||
# Install Wren AI with Augment
|
||||
|
||||
Augment Code coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Augment](https://www.augmentcode.com) installed and authenticated.
|
||||
- Augment account login required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent augment
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project in VS Code with the Augment extension installed, then open the Augment panel. Or use the CLI:
|
||||
|
||||
```bash
|
||||
auggie
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
sidebar_label: IBM Bob
|
||||
---
|
||||
|
||||
# Install Wren AI with IBM Bob
|
||||
|
||||
IBM watsonx coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [IBM Bob](https://www.ibm.com/watsonx) installed and authenticated.
|
||||
- IBM Cloud account required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent bob
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in IBM Bob (watsonx Code Assistant), then start a new chat.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
sidebar_label: Claude Code
|
||||
---
|
||||
|
||||
# Install Wren AI with Claude Code
|
||||
|
||||
Anthropic's official terminal coding assistant.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Claude Code](https://claude.com/code) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent claude-code
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
claude
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: Cline
|
||||
---
|
||||
|
||||
# Install Wren AI with Cline
|
||||
|
||||
Open-source autonomous coding agent for VS Code.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Cline](https://cline.bot) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent cline
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in VS Code with the Cline extension installed, then click the Cline icon in the Activity Bar to open the chat panel.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
sidebar_label: CodeArts Agent
|
||||
---
|
||||
|
||||
# Install Wren AI with CodeArts Agent
|
||||
|
||||
Huawei Cloud CodeArts Doer.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [CodeArts Agent](https://www.huaweicloud.com/product/codeartsdoer.html) installed and authenticated.
|
||||
- Huawei Cloud account required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent codearts-agent
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project in CodeArts IDE, then open the CodeArts Agent panel.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: CodeBuddy
|
||||
---
|
||||
|
||||
# Install Wren AI with CodeBuddy
|
||||
|
||||
Tencent CodeBuddy coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [CodeBuddy](https://www.codebuddy.ai) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent codebuddy
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project in CodeBuddy IDE (or the VS Code extension), then open the CodeBuddy chat panel.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: Codemaker
|
||||
---
|
||||
|
||||
# Install Wren AI with Codemaker
|
||||
|
||||
Codemaker AI coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Codemaker](https://github.com/vercel-labs/skills) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent codemaker
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in Codemaker, then start a new chat session.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: Code Studio
|
||||
---
|
||||
|
||||
# Install Wren AI with Code Studio
|
||||
|
||||
OPPO/Heytap coding IDE.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Code Studio](https://github.com/vercel-labs/skills) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent codestudio
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in Code Studio, then start a new chat session.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
sidebar_label: Codex
|
||||
---
|
||||
|
||||
# Install Wren AI with Codex
|
||||
|
||||
OpenAI Codex CLI.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Codex](https://developers.openai.com/codex) installed and authenticated.
|
||||
- OpenAI account login required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent codex
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
codex
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
sidebar_label: Command Code
|
||||
---
|
||||
|
||||
# Install Wren AI with Command Code
|
||||
|
||||
Command Code agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Command Code](https://commandcode.ai) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent command-code
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
cmd
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: Continue
|
||||
---
|
||||
|
||||
# Install Wren AI with Continue
|
||||
|
||||
Open-source IDE coding assistant.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Continue](https://continue.dev) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent continue
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in VS Code or a JetBrains IDE with the Continue extension installed, then open the Continue chat panel (`⌘L` / `Ctrl+L` on VS Code, `⌘J` / `Ctrl+J` on JetBrains).
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
sidebar_label: Cortex Code
|
||||
---
|
||||
|
||||
# Install Wren AI with Cortex Code
|
||||
|
||||
Snowflake Cortex coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Cortex Code](https://www.snowflake.com/cortex) installed and authenticated.
|
||||
- A Snowflake account is required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent cortex
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project in Snowflake's Cortex Code interface, then start a new agent session.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
sidebar_label: Crush
|
||||
---
|
||||
|
||||
# Install Wren AI with Crush
|
||||
|
||||
Charm's TUI coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Crush](https://github.com/charmbracelet/crush) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent crush
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
crush
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: Cursor
|
||||
---
|
||||
|
||||
# Install Wren AI with Cursor
|
||||
|
||||
The Cursor IDE.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Cursor](https://cursor.com) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent cursor
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in Cursor (`File → Open Folder...` or `⌘O` / `Ctrl+O`), then open the chat panel with `⌘L` / `Ctrl+L`.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
sidebar_label: Deep Agents
|
||||
---
|
||||
|
||||
# Install Wren AI with Deep Agents
|
||||
|
||||
LangChain Deep Agents framework.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Deep Agents](https://github.com/langchain-ai/deepagents) installed and authenticated.
|
||||
- Python environment setup required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent deepagents
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
dcode
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
sidebar_label: Devin for Terminal
|
||||
---
|
||||
|
||||
# Install Wren AI with Devin for Terminal
|
||||
|
||||
Cognition Devin CLI.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Devin for Terminal](https://devin.ai) installed and authenticated.
|
||||
- A Devin subscription is required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent devin
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
devin
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: Dexto
|
||||
---
|
||||
|
||||
# Install Wren AI with Dexto
|
||||
|
||||
Dexto coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Dexto](https://github.com/vercel-labs/skills) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent dexto
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in Dexto, then start a new chat session.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
sidebar_label: Droid
|
||||
---
|
||||
|
||||
# Install Wren AI with Droid
|
||||
|
||||
Factory AI Droid CLI.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Droid](https://docs.factory.ai/cli) installed and authenticated.
|
||||
- Factory login required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent droid
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
droid
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
sidebar_label: Firebender
|
||||
---
|
||||
|
||||
# Install Wren AI with Firebender
|
||||
|
||||
Android JetBrains coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Firebender](https://firebender.com) installed and authenticated.
|
||||
- A JetBrains IDE is required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent firebender
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project in a JetBrains IDE with the Firebender plugin installed, then open the Firebender chat panel.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
sidebar_label: ForgeCode
|
||||
---
|
||||
|
||||
# Install Wren AI with ForgeCode
|
||||
|
||||
Forge AI coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [ForgeCode](https://forgecode.dev) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent forgecode
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
forge
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
sidebar_label: Gemini CLI
|
||||
---
|
||||
|
||||
# Install Wren AI with Gemini CLI
|
||||
|
||||
Google's official Gemini CLI.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Gemini CLI](https://github.com/google-gemini/gemini-cli) installed and authenticated.
|
||||
- Google authentication is required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent gemini-cli
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
gemini
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
sidebar_label: GitHub Copilot
|
||||
---
|
||||
|
||||
# Install Wren AI with GitHub Copilot
|
||||
|
||||
GitHub Copilot CLI / Coding Agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [GitHub Copilot](https://github.com/features/copilot) installed and authenticated.
|
||||
- A Copilot subscription is required. Agent skills may be preview-gated for your account.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent github-copilot
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in VS Code (or another supported IDE) with GitHub Copilot installed, then open Copilot Chat with `⌃⌘I` / `Ctrl+Alt+I`.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
sidebar_label: Goose
|
||||
---
|
||||
|
||||
# Install Wren AI with Goose
|
||||
|
||||
Block's open-source coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Goose](https://block.github.io/goose) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent goose
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
goose session
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: Hermes Agent
|
||||
---
|
||||
|
||||
# Install Wren AI with Hermes Agent
|
||||
|
||||
Hermes coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Hermes Agent](https://github.com/vercel-labs/skills) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent hermes-agent
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in Hermes Agent, then start a new chat session.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
sidebar_label: iFlow CLI
|
||||
---
|
||||
|
||||
# Install Wren AI with iFlow CLI
|
||||
|
||||
iFlow CLI agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [iFlow CLI](https://platform.iflow.cn) installed and authenticated.
|
||||
- iFlow account required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent iflow-cli
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
iflow
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
sidebar_label: Junie
|
||||
---
|
||||
|
||||
# Install Wren AI with Junie
|
||||
|
||||
JetBrains Junie.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Junie](https://www.jetbrains.com/junie) installed and authenticated.
|
||||
- A JetBrains IDE is required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent junie
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project in a JetBrains IDE with the Junie plugin installed, then open the Junie tool window from the right sidebar.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
sidebar_label: Kilo Code
|
||||
---
|
||||
|
||||
# Install Wren AI with Kilo Code
|
||||
|
||||
VS Code coding agent (fork of Roo Code).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Kilo Code](https://kilocode.ai) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent kilo
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in VS Code with the Kilo Code extension installed, then click the Kilo icon in the Activity Bar. Or use the CLI:
|
||||
|
||||
```bash
|
||||
kilo
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
sidebar_label: Kimi Code CLI
|
||||
---
|
||||
|
||||
# Install Wren AI with Kimi Code CLI
|
||||
|
||||
Moonshot Kimi CLI. Uses the shared `.agents/skills/` directory.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Kimi Code CLI](https://moonshotai.github.io/kimi-cli) installed and authenticated.
|
||||
- Moonshot API key required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent kimi-cli
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
kimi
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
sidebar_label: Kiro CLI
|
||||
---
|
||||
|
||||
# Install Wren AI with Kiro CLI
|
||||
|
||||
AWS Kiro CLI.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Kiro CLI](https://kiro.dev) installed and authenticated.
|
||||
- If you use a custom agent, add `resources: ["skill://.kiro/skills/**/SKILL.md"]` to your `.kiro/agents/<agent>.json`. The default agent loads skills automatically.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent kiro-cli
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
kiro
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
sidebar_label: Kode
|
||||
---
|
||||
|
||||
# Install Wren AI with Kode
|
||||
|
||||
shareAI Kode coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Kode](https://github.com/shareAI-lab/kode) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent kode
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
kode
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: MCPJam
|
||||
---
|
||||
|
||||
# Install Wren AI with MCPJam
|
||||
|
||||
MCPJam development tool.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [MCPJam](https://github.com/vercel-labs/skills) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent mcpjam
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in MCPJam, then start a new chat session.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
sidebar_label: Mistral Vibe
|
||||
---
|
||||
|
||||
# Install Wren AI with Mistral Vibe
|
||||
|
||||
Mistral's Vibe coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Mistral Vibe](https://mistral.ai) installed and authenticated.
|
||||
- Mistral account login required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent mistral-vibe
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
vibe
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: Mux
|
||||
---
|
||||
|
||||
# Install Wren AI with Mux
|
||||
|
||||
Mux coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Mux](https://github.com/vercel-labs/skills) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent mux
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in Mux, then start a new chat session.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
sidebar_label: Neovate
|
||||
---
|
||||
|
||||
# Install Wren AI with Neovate
|
||||
|
||||
Neovate coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Neovate](https://github.com/vercel-labs/skills) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent neovate
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
neovate
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
sidebar_label: OpenClaw
|
||||
---
|
||||
|
||||
# Install Wren AI with OpenClaw
|
||||
|
||||
OpenClaw coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [OpenClaw](https://openclaw.ai) installed and authenticated.
|
||||
- Project-scope skills are installed under repo-root `skills/`, **not** under a hidden `.openclaw/` directory.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent openclaw
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
openclaw
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
sidebar_label: OpenCode
|
||||
---
|
||||
|
||||
# Install Wren AI with OpenCode
|
||||
|
||||
SST's open-source coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [OpenCode](https://opencode.ai) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent opencode
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
opencode
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
sidebar_label: OpenHands
|
||||
---
|
||||
|
||||
# Install Wren AI with OpenHands
|
||||
|
||||
All-Hands open-source coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [OpenHands](https://docs.openhands.ai) installed and authenticated.
|
||||
- A Docker runtime is typically required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent openhands
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
openhands
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
sidebar_label: Pi
|
||||
---
|
||||
|
||||
# Install Wren AI with Pi
|
||||
|
||||
Pi Mono coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Pi](https://github.com/badlogic/pi-mono) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent pi
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
pi
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: Pochi
|
||||
---
|
||||
|
||||
# Install Wren AI with Pochi
|
||||
|
||||
Pochi coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Pochi](https://github.com/vercel-labs/skills) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent pochi
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in Pochi, then start a new chat session.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
sidebar_label: Qoder
|
||||
---
|
||||
|
||||
# Install Wren AI with Qoder
|
||||
|
||||
Qoder coding IDE.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Qoder](https://qoder.com) installed and authenticated.
|
||||
- Qoder account login required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent qoder
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in Qoder IDE, then open the Qoder chat panel.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
sidebar_label: Qwen Code
|
||||
---
|
||||
|
||||
# Install Wren AI with Qwen Code
|
||||
|
||||
Alibaba Qwen Code CLI.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Qwen Code](https://qwenlm.github.io/qwen-code-docs) installed and authenticated.
|
||||
- Qwen API access required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent qwen-code
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
qwen
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: Roo Code
|
||||
---
|
||||
|
||||
# Install Wren AI with Roo Code
|
||||
|
||||
Open-source VS Code coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Roo Code](https://roocode.com) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent roo
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in VS Code with the Roo Code extension installed, then click the Roo icon in the Activity Bar to open the chat panel.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
sidebar_label: Rovo Dev
|
||||
---
|
||||
|
||||
# Install Wren AI with Rovo Dev
|
||||
|
||||
Atlassian Rovo Dev.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Rovo Dev](https://www.atlassian.com/software/rovo) installed and authenticated.
|
||||
- An Atlassian account is required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent rovodev
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
acli rovodev run
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
sidebar_label: Tabnine CLI
|
||||
---
|
||||
|
||||
# Install Wren AI with Tabnine CLI
|
||||
|
||||
Tabnine CLI coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Tabnine CLI](https://www.tabnine.com) installed and authenticated.
|
||||
- A Tabnine subscription is required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent tabnine-cli
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
```bash
|
||||
tabnine
|
||||
```
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
sidebar_label: Trae CN
|
||||
---
|
||||
|
||||
# Install Wren AI with Trae CN
|
||||
|
||||
Trae (China region).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Trae CN](https://trae.com.cn) installed and authenticated.
|
||||
- A China-region account is required.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent trae-cn
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in Trae CN IDE (`File → Open Folder...`), then open the chat panel.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: Trae
|
||||
---
|
||||
|
||||
# Install Wren AI with Trae
|
||||
|
||||
ByteDance Trae IDE.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Trae](https://trae.ai) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent trae
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in Trae IDE (`File → Open Folder...`), then open the chat panel with `⌘U` / `Ctrl+U`.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
sidebar_label: Warp
|
||||
---
|
||||
|
||||
# Install Wren AI with Warp
|
||||
|
||||
Warp terminal coding agent. Uses the shared `.agents/skills/` directory.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Warp](https://warp.dev) installed and authenticated.
|
||||
- Warp app installed; the skills feature must be enabled.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent warp
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open Warp, then press `⌘I` / `Ctrl+I` to enter Agent Mode.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_label: Windsurf
|
||||
---
|
||||
|
||||
# Install Wren AI with Windsurf
|
||||
|
||||
Codeium Windsurf IDE.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Windsurf](https://windsurf.com) installed and authenticated.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent windsurf
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in Windsurf (`File → Open Folder...`), then open the Cascade panel from the right sidebar (`⌘L` / `Ctrl+L`).
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
sidebar_label: Zencoder
|
||||
---
|
||||
|
||||
# Install Wren AI with Zencoder
|
||||
|
||||
Zencoder coding agent.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Zencoder](https://zencoder.ai) installed and authenticated.
|
||||
- Zencoder has limited skill features — `allowed-tools` frontmatter is not honored.
|
||||
|
||||
## Install Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent zencoder
|
||||
```
|
||||
|
||||
## Run onboarding
|
||||
|
||||
Open your project folder in VS Code or a JetBrains IDE with the Zencoder extension/plugin installed, then open the Zencoder chat panel.
|
||||
|
||||
Then ask:
|
||||
|
||||
```text
|
||||
Use the /wren-onboarding skill to install and set up Wren AI.
|
||||
```
|
||||
|
||||
The skill walks the agent through environment checks, profile creation, project scaffolding, and a first query.
|
||||
|
||||
## Next step
|
||||
|
||||
- [Quickstart with sample data](../quickstart) — walk through `jaffle_shop` end-to-end
|
||||
- [Connect your data](/oss/guides/connect) — point Wren AI at a real database
|
||||
@@ -11,9 +11,9 @@ Ask natural-language questions of the **jaffle_shop** dataset using **Wren AI CL
|
||||
This guide drops three things on you in the first few steps. Skim before you start:
|
||||
|
||||
- **Wren CLI (`wren`)** — the Python CLI that runs all of this. Connects to a database, holds your modeling files, executes SQL through the semantic layer, manages a local memory index. ([CLI reference →](/oss/reference/cli))
|
||||
- **MDL (Modeling Definition Language)** — YAML files under `models/`, `views/`, and `relationships.yml` that describe your tables, columns, and joins in business terms. The agent reads MDL instead of guessing from raw schema. ([MDL concept →](/oss/concepts/what_is_mdl) · [Wren project guide →](/oss/guides/modeling/wren_project))
|
||||
- **MDL (Modeling Definition Language)** — YAML files under `models/`, `views/`, and `relationships.yml` that describe your tables, columns, and joins in business terms. The agent reads MDL instead of guessing from raw schema. ([MDL concept →](/oss/concepts/what_is_mdl) · [Wren project guide →](/oss/reference/mdl))
|
||||
- **jaffle_shop** — a public sample database from dbt Labs. We use it so you do not need to bring your own database to follow this quickstart. It is a fictional ecommerce business with `customers`, `orders`, `products`, and `supplies`. *(Want to skip jaffle_shop and use your own database? Finish the install in step 2 then jump to [Connect your database](/oss/guides/connect).)*
|
||||
- **Skills** — markdown workflow guides that tell an AI coding agent (Claude Code, Openclaw, Hermes, Codex, etc.) how to operate the CLI. Two skills drive this quickstart: `wren-generate-mdl` (one-time scaffolding) and `wren-usage` (day-to-day querying). ([Skills concept →](/oss/concepts/skills))
|
||||
- **Skills** — markdown workflow guides that tell an AI coding agent (Claude Code, Openclaw, Hermes, Codex, etc.) how to operate the CLI. Two skills drive this quickstart: `wren-generate-mdl` (one-time scaffolding) and `wren-usage` (day-to-day querying). ([Skills concept →](/oss/reference/skills))
|
||||
|
||||
---
|
||||
|
||||
@@ -286,7 +286,7 @@ wren cube query \
|
||||
|
||||
Cube queries are the recommended path for aggregation when a cube covers the
|
||||
question. Lower error rate, especially on small / local models. See the
|
||||
[Cube guide](../guides/modeling/cube.md) for the YAML structure and the
|
||||
[Cube guide](../guides/cubes.md) for the YAML structure and the
|
||||
[CLI reference](../reference/cli.md#wren-cube--pre-aggregation-queries) for all flags.
|
||||
|
||||
---
|
||||
|
||||
@@ -98,6 +98,6 @@ This writes `profile: my-db` and `data_source: <ds>` into `wren_project.yml`. Fu
|
||||
|
||||
## Next steps
|
||||
|
||||
- [Generate MDL](/oss/guides/modeling/overview) — let the agent introspect your schema
|
||||
- [Memory](/oss/guides/memory) — how the index keeps your queries accurate
|
||||
- [Profiles](/oss/guides/profiles) — managing multiple profiles
|
||||
- [Model your business](/oss/guides/model) — let the agent scaffold MDL from your schema
|
||||
- [Refine answer quality](/oss/guides/refine) — close the loop with memory and instructions
|
||||
- [Manage project](/oss/guides/manage_project) — multi-environment profile workflow
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
---
|
||||
sidebar_label: Pre-aggregate with cubes
|
||||
---
|
||||
|
||||
# Pre-aggregate with cubes
|
||||
|
||||
Cubes are pre-aggregated semantic objects: a base model or view plus declared measures, dimensions, time dimensions, and hierarchies. They give agents a **structured aggregation API** instead of asking them to hand-write `GROUP BY`, `DATE_TRUNC`, and metric arithmetic — the SQL surface where small and local models fail most often.
|
||||
|
||||
## What you'll end up with
|
||||
|
||||
- A `cubes/<name>/metadata.yml` per cube, declaring its measures and dimensions
|
||||
- A queryable cube name in MDL — `wren cube query --cube revenue --measures total --dimensions month`
|
||||
- An agent that picks structured cube queries instead of inventing aggregation SQL
|
||||
|
||||
## Why this primitive matters
|
||||
|
||||
The most common failure mode for agents writing analytical SQL is:
|
||||
|
||||
- Joining wrong because they reconstructed the join from raw FKs
|
||||
- Double-counting because they aggregated on the wrong grain
|
||||
- Mis-truncating dates because the time grain was ambiguous
|
||||
- Inventing a metric that does not match the team's accepted definition
|
||||
|
||||
A cube collapses all four problems. The measures, dimensions, time grains, and join paths are declared once. The agent supplies a structured input. The engine produces correct SQL.
|
||||
|
||||
This is the **highest-leverage correctness primitive** for smaller models, where the gap between "knows what to ask" and "can write SQL correctly" is widest.
|
||||
|
||||
## Define a cube
|
||||
|
||||
Cubes live under `cubes/<name>/metadata.yml`. A simple cube over an existing `orders` model looks like:
|
||||
|
||||
```yaml
|
||||
name: revenue
|
||||
base_object: orders
|
||||
measures:
|
||||
- name: total
|
||||
expression: SUM(amount)
|
||||
type: DOUBLE
|
||||
- name: order_count
|
||||
expression: COUNT(*)
|
||||
type: BIGINT
|
||||
dimensions:
|
||||
- name: status
|
||||
expression: status
|
||||
type: VARCHAR
|
||||
time_dimensions:
|
||||
- name: month
|
||||
expression: order_date
|
||||
grain: month
|
||||
type: DATE
|
||||
hierarchies:
|
||||
- name: time
|
||||
levels: [year, quarter, month]
|
||||
```
|
||||
|
||||
See the [MDL schema reference](/oss/reference/mdl) for every cube field.
|
||||
|
||||
## Query a cube
|
||||
|
||||
The `wren cube query` CLI takes a structured input:
|
||||
|
||||
```bash
|
||||
wren cube query \
|
||||
--cube revenue \
|
||||
--measures total,order_count \
|
||||
--dimensions status \
|
||||
--time-dimension month \
|
||||
--filter "status = 'completed'"
|
||||
```
|
||||
|
||||
Or from an agent SDK:
|
||||
|
||||
```python
|
||||
result = wren.cube.query(
|
||||
cube="revenue",
|
||||
measures=["total"],
|
||||
dimensions=["status"],
|
||||
time_dimension="month",
|
||||
filter="status = 'completed'"
|
||||
)
|
||||
```
|
||||
|
||||
No hand-written `GROUP BY`. No `DATE_TRUNC`. No join inference.
|
||||
|
||||
## When to add a cube
|
||||
|
||||
Add a cube when:
|
||||
|
||||
- A metric is queried often (revenue, retention, MAU)
|
||||
- The metric has a clear team-agreed definition (don't model unsettled metrics)
|
||||
- Small or local models in your agent stack struggle with the aggregation
|
||||
- You want a stable interface that survives schema drift in the base model
|
||||
|
||||
Do **not** add a cube when:
|
||||
|
||||
- The metric is exploratory or one-off (a SQL query is fine)
|
||||
- The metric definition is still under debate (write it in `instructions.md` first)
|
||||
- There is no clear grain (cubes need explicit measures + dimensions)
|
||||
|
||||
## When to come back here
|
||||
|
||||
- A small or local model in your stack starts hallucinating aggregations
|
||||
- You promote a metric from "agreed on Slack" to "in the MDL"
|
||||
- A new business KPI gets formal sign-off
|
||||
- You want to expose a metric to a customer-facing app via the SDK
|
||||
|
||||
## See also
|
||||
|
||||
- [MDL schema reference](/oss/reference/mdl) — full cube field reference, including hierarchies and pre-aggregations
|
||||
- [How does Wren AI keep agents from hallucinating?](/oss/concepts/correctness) — why cubes matter as a correctness primitive
|
||||
- [Model your business](./model.md) — the modeling step that precedes cubes
|
||||
@@ -0,0 +1,211 @@
|
||||
---
|
||||
sidebar_label: Manage project
|
||||
---
|
||||
|
||||
# Manage project
|
||||
|
||||
A Wren project is the unit of authoring, version control, and deployment for MDL. This recipe covers the lifecycle — initialization, validation, build, profile management, multi-environment workflow, and migration.
|
||||
|
||||
## What you'll end up with
|
||||
|
||||
- A clean understanding of which files live in the project vs. globally in `~/.wren/`
|
||||
- The lifecycle commands wired into your editor / CI
|
||||
- Multiple profiles set up for dev / staging / prod against the same project
|
||||
- A safe pattern for switching environments without touching secrets
|
||||
|
||||
## Project lifecycle
|
||||
|
||||
```bash
|
||||
wren context init # scaffold a new project in cwd
|
||||
wren context validate # check YAML structure (no DB required)
|
||||
wren context build # compile YAML to target/mdl.json
|
||||
wren context upgrade # upgrade to the latest schema_version
|
||||
wren context set-profile pg # bind a connection profile to the project
|
||||
wren memory index # index schema + instructions into .wren/memory/
|
||||
```
|
||||
|
||||
A typical first-time setup:
|
||||
|
||||
```bash
|
||||
mkdir my_project && cd my_project
|
||||
wren context init
|
||||
# (edit models/, relationships.yml, instructions.md — usually agent-driven)
|
||||
wren context validate
|
||||
wren context build
|
||||
wren profile add pg-dev --from-file dev.yml --activate
|
||||
wren context set-profile pg-dev
|
||||
wren memory index
|
||||
wren --sql "SELECT 1"
|
||||
```
|
||||
|
||||
After editing models, rebuild and re-index:
|
||||
|
||||
```bash
|
||||
wren context build
|
||||
wren memory index
|
||||
```
|
||||
|
||||
## `wren_project.yml` at the project root
|
||||
|
||||
```yaml
|
||||
schema_version: 3
|
||||
name: my_project
|
||||
version: "1.0"
|
||||
catalog: wren
|
||||
schema: public
|
||||
data_source: postgres
|
||||
profile: pg-dev
|
||||
```
|
||||
|
||||
| Field | Purpose |
|
||||
|---|---|
|
||||
| `schema_version` | Directory layout version. Owned by the CLI — use `wren context upgrade` to bump. |
|
||||
| `name` | Project identifier. |
|
||||
| `version` | Your own project version (free-form). |
|
||||
| `catalog` / `schema` | **Wren AI namespace**, not your database catalog/schema. Defaults: `wren` / `public`. |
|
||||
| `data_source` | Data source type — `postgres`, `bigquery`, etc. Set by `wren context set-profile`. |
|
||||
| `profile` | The bound connection profile. Set by `wren context set-profile`. |
|
||||
|
||||
> The same field names `catalog` and `schema` appear inside each model's `table_reference` to point at the database. Do not confuse the two — see the [MDL schema reference](/oss/reference/mdl) for the full distinction.
|
||||
|
||||
## Profile management
|
||||
|
||||
Profiles separate connection credentials from project definitions. The same MDL project can connect to multiple databases by switching profiles.
|
||||
|
||||
```bash
|
||||
wren profile list # list all profiles (* marks active)
|
||||
wren profile add pg-prod --ui # create via browser form
|
||||
wren profile switch pg-prod # change the globally active profile
|
||||
wren profile debug # show resolved config (secrets masked)
|
||||
wren profile rm old-db # remove a profile
|
||||
```
|
||||
|
||||
### Where profiles live
|
||||
|
||||
```text
|
||||
~/.wren/profiles.yml # global, all profiles + active pointer
|
||||
~/.wren/config.yml # global CLI preferences, default_project
|
||||
```
|
||||
|
||||
The file is written with `0600` permissions. Secrets use `${ENV_VAR}` interpolation — see [Secrets and `.env` files](#secrets-and-env-files) below.
|
||||
|
||||
### Profile vs project at a glance
|
||||
|
||||
| | Profile | Project |
|
||||
|---|---|---|
|
||||
| **What** | Connection credentials | MDL model definitions |
|
||||
| **Where** | `~/.wren/profiles.yml` (global) | `<project>/wren_project.yml` + `models/` |
|
||||
| **Scope** | Shared across all projects | Per-project — version controlled |
|
||||
| **Secrets** | Contains them | None — safe to commit |
|
||||
|
||||
## Multi-environment workflow
|
||||
|
||||
A single MDL project can be bound to different profiles for different environments.
|
||||
|
||||
### Pattern 1: switch profile globally
|
||||
|
||||
```bash
|
||||
wren profile switch pg-dev # work against dev
|
||||
wren profile switch pg-prod # switch to prod for one query
|
||||
wren profile switch pg-dev # back to dev
|
||||
```
|
||||
|
||||
### Pattern 2: bind a profile per project
|
||||
|
||||
```bash
|
||||
cd ~/projects/sales
|
||||
wren context set-profile pg-prod # writes profile + data_source into wren_project.yml
|
||||
```
|
||||
|
||||
After binding, every command in this project uses `pg-prod` regardless of the globally active profile. Useful when you have multiple projects open at once.
|
||||
|
||||
### Pattern 3: per-shell override
|
||||
|
||||
```bash
|
||||
export WREN_PROJECT_HOME=~/projects/sales
|
||||
wren --connection-file ./connection.yml --sql "SELECT 1"
|
||||
```
|
||||
|
||||
Useful for CI jobs that need to point at a specific database without touching `~/.wren/profiles.yml`.
|
||||
|
||||
## Secrets and `.env` files
|
||||
|
||||
Any profile value can reference `${VAR_NAME}` placeholders. Resolution order (first match wins):
|
||||
|
||||
1. `os.environ` — variables exported in your shell
|
||||
2. `$CWD/.env` — directory you run `wren` from
|
||||
3. `<project>/.env` — co-located with `wren_project.yml`
|
||||
4. `~/.wren/.env` — user-global fallback
|
||||
|
||||
```yaml
|
||||
# ~/.wren/profiles.yml
|
||||
profiles:
|
||||
pg-prod:
|
||||
datasource: postgres
|
||||
host: db.example.com
|
||||
port: '5432'
|
||||
database: wren
|
||||
user: ${POSTGRES_USER}
|
||||
password: ${POSTGRES_PASSWORD}
|
||||
```
|
||||
|
||||
```bash
|
||||
# .env (in project root, gitignored)
|
||||
POSTGRES_USER=paul
|
||||
POSTGRES_PASSWORD=s3cr3t
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- Names must be **UPPERCASE** (`[A-Z_][A-Z0-9_]*`)
|
||||
- `$$` escapes a literal dollar sign
|
||||
- Missing vars fail early with a clear error — no cryptic driver errors
|
||||
|
||||
AI coding agents should **never** ask for credentials in chat. The agent writes a profile referencing `${POSTGRES_PASSWORD}` and instructs you to fill the value in `.env` via your editor.
|
||||
|
||||
## Migrate from an existing `mdl.json`
|
||||
|
||||
If you have an older `mdl.json` from a previous Wren setup or another tool:
|
||||
|
||||
```bash
|
||||
wren context init --from-mdl /path/to/mdl.json --path my_project
|
||||
```
|
||||
|
||||
This converts camelCase JSON to snake_case YAML and writes the full directory structure. Then:
|
||||
|
||||
```bash
|
||||
wren context validate --path my_project
|
||||
wren context build --path my_project
|
||||
```
|
||||
|
||||
If the target directory already has project files, use `--force` to overwrite.
|
||||
|
||||
## Upgrade an existing project
|
||||
|
||||
When new MDL features ship (the `dialect` field, new cube semantics), upgrade with:
|
||||
|
||||
```bash
|
||||
wren context upgrade # bumps to the latest schema_version
|
||||
wren context upgrade --to 3 # bump to a specific version
|
||||
wren context upgrade --dry-run # preview without writing
|
||||
```
|
||||
|
||||
After upgrade, re-validate and re-build:
|
||||
|
||||
```bash
|
||||
wren context validate
|
||||
wren context build
|
||||
```
|
||||
|
||||
## When to come back here
|
||||
|
||||
- Adding a new environment (staging / preview / customer X)
|
||||
- Onboarding a new teammate (point them at `~/.wren/profiles.yml` setup)
|
||||
- A schema_version bump shows up in a release
|
||||
- Migrating from another semantic layer manifest
|
||||
|
||||
## See also
|
||||
|
||||
- [MDL schema reference](/oss/reference/mdl) — every field in the project's YAML files
|
||||
- [Operational reference](/oss/reference/operational) — paths, env vars, and discovery rules
|
||||
- [Connect your data](./connect.md) — the initial connection step
|
||||
@@ -1,362 +0,0 @@
|
||||
# Memory
|
||||
|
||||
Wren AI ships an optional **memory layer** — a LanceDB-backed semantic index that gives AI agents the context they need to write accurate SQL. Instead of sending the entire schema to an LLM on every question, the memory layer provides targeted context: relevant tables, columns, and past query examples.
|
||||
|
||||
> **Memory is opt-in.** It is not bundled with the base CLI — install the `memory` extra to enable it. Without memory, the agent can still query through MDL, but features like NL-SQL recall, embedding-based schema retrieval, and the self-learning loop will be unavailable.
|
||||
|
||||
## Why memory matters
|
||||
|
||||
Without memory, an AI agent must either:
|
||||
|
||||
- Receive the **full schema** in every prompt — works for small databases but quickly exceeds context limits
|
||||
- Guess which tables are relevant — leads to hallucinated column names and wrong joins
|
||||
|
||||
The memory layer solves both problems by indexing the MDL schema and storing confirmed NL-SQL pairs. At query time it retrieves only what the agent needs.
|
||||
|
||||
## What gets indexed
|
||||
|
||||
The memory layer manages two collections:
|
||||
|
||||
| Collection | Contents | Source | Rebuildable? |
|
||||
|------------|----------|--------|-------------|
|
||||
| **schema_items** | Models, columns, relationships, views, instructions | MDL manifest + `instructions.md` | Yes — `wren memory index` |
|
||||
| **query_history** | Natural-language → SQL pairs | Stored after successful queries | No — built up over time |
|
||||
|
||||
Both collections live in `<project>/.wren/memory/` (or `~/.wren/memory/` outside a project).
|
||||
|
||||
## Installation
|
||||
|
||||
Memory is a separate optional extra — it is **not** included in the base install:
|
||||
|
||||
```bash
|
||||
pip install "wren-engine[memory]"
|
||||
```
|
||||
|
||||
Combine with your data source extra:
|
||||
|
||||
```bash
|
||||
pip install "wren-engine[memory,postgres]"
|
||||
pip install "wren-engine[memory,bigquery]"
|
||||
```
|
||||
|
||||
If you skip the `memory` extra, memory commands (`wren memory index`, `fetch`, `recall`, `store`, etc.) will not be available.
|
||||
|
||||
## Indexing the schema
|
||||
|
||||
After creating or updating your MDL project, index the schema:
|
||||
|
||||
```bash
|
||||
wren memory index
|
||||
```
|
||||
|
||||
This parses the compiled `target/mdl.json`, generates local embeddings for every schema item, and stores them in LanceDB. Re-index whenever you change models, columns, relationships, or instructions:
|
||||
|
||||
```bash
|
||||
wren context build
|
||||
wren memory index
|
||||
```
|
||||
|
||||
Check the index status:
|
||||
|
||||
```bash
|
||||
wren memory status
|
||||
# Path: /Users/you/my-project/.wren/memory
|
||||
# schema_items: 47 rows
|
||||
# query_history: 12 rows
|
||||
```
|
||||
|
||||
## Fetching schema context
|
||||
|
||||
`wren memory fetch` is the primary way agents get schema context. It automatically picks the best retrieval strategy based on schema size:
|
||||
|
||||
| Schema size | Strategy | What the agent sees |
|
||||
|-------------|----------|---------------------|
|
||||
| Below 30,000 chars (~8K tokens) | **Full text** | Complete schema with all model-column relationships, join paths, and primary keys |
|
||||
| Above 30,000 chars | **Embedding search** | Top-k most relevant fragments for the query |
|
||||
|
||||
```bash
|
||||
wren memory fetch -q "customer order price"
|
||||
wren memory fetch -q "revenue" --type column --model orders
|
||||
wren memory fetch -q "order date" --threshold 50000 --output json
|
||||
```
|
||||
|
||||
### Why hybrid?
|
||||
|
||||
Small schemas give better results as full text — the LLM sees the complete structure rather than isolated fragments. Large schemas don't fit in a single prompt, so embedding search retrieves only what's relevant.
|
||||
|
||||
The threshold is measured in characters (not tokens) because character counting is free. The 4:1 chars-to-tokens ratio holds for English; CJK text compresses less (~1.5:1), so CJK-heavy schemas switch to search sooner — the conservative direction.
|
||||
|
||||
Override with `--threshold`:
|
||||
|
||||
```bash
|
||||
wren memory fetch -q "revenue" --threshold 50000 # raise for larger context windows
|
||||
```
|
||||
|
||||
### Full schema without search
|
||||
|
||||
`wren memory describe` prints the entire schema as structured plain text — no embeddings or LanceDB required:
|
||||
|
||||
```bash
|
||||
wren memory describe
|
||||
```
|
||||
|
||||
## Storing and recalling queries
|
||||
|
||||
Every successful query can be stored as a natural-language → SQL pair. These pairs serve as **few-shot examples** for future questions — the more you store, the better the agent gets at writing SQL for your domain.
|
||||
|
||||
### Storing a query
|
||||
|
||||
```bash
|
||||
wren memory store \
|
||||
--nl "top 5 customers by revenue last quarter" \
|
||||
--sql "SELECT c.first_name, SUM(o.amount) AS revenue FROM customers c JOIN orders o ON c.customer_id = o.customer_id WHERE o.order_date >= '2024-10-01' GROUP BY 1 ORDER BY 2 DESC LIMIT 5" \
|
||||
--datasource duckdb
|
||||
```
|
||||
|
||||
**When to store:**
|
||||
- Query executed successfully and the result is correct
|
||||
- There is a clear natural-language question behind the query
|
||||
|
||||
**When NOT to store:**
|
||||
- The query failed or returned wrong results
|
||||
- The query is exploratory / throwaway (`SELECT * FROM orders LIMIT 5`)
|
||||
- There is no natural-language question — just raw SQL
|
||||
|
||||
### Recalling similar queries
|
||||
|
||||
Before writing new SQL, search for similar past queries:
|
||||
|
||||
```bash
|
||||
wren memory recall -q "best customers"
|
||||
wren memory recall -q "monthly revenue" --datasource mysql --limit 5 --output json
|
||||
```
|
||||
|
||||
Results are returned ranked by semantic similarity. Use them as few-shot examples — adapt the SQL pattern to the current question.
|
||||
|
||||
## Browsing and managing pairs
|
||||
|
||||
### Listing pairs
|
||||
|
||||
Browse all stored NL-SQL pairs with `wren memory list`:
|
||||
|
||||
```bash
|
||||
wren memory list # default: 20 rows, table format
|
||||
wren memory list --source seed # filter by source tag
|
||||
wren memory list --limit 50 --offset 20 # pagination
|
||||
wren memory list --output json # JSON output (includes _row_id)
|
||||
```
|
||||
|
||||
| Flag | Default | Description |
|
||||
|------|---------|-------------|
|
||||
| `--source` / `-s` | (all) | Filter by source: `seed`, `user`, `view` |
|
||||
| `--limit` / `-n` | 20 | Max rows to show |
|
||||
| `--offset` | 0 | Skip first N rows (pagination) |
|
||||
| `--output` / `-o` | `table` | Output format: `json` or `table` |
|
||||
|
||||
### Forgetting pairs
|
||||
|
||||
Remove incorrect or outdated NL-SQL pairs with `wren memory forget`. Three modes:
|
||||
|
||||
| Mode | Flags | Behavior |
|
||||
|------|-------|----------|
|
||||
| **Interactive** | (none) or `--source` | Checkbox UI — browse, select, confirm |
|
||||
| **By ID** | `--id N [--id M ...]` | Delete specific rows (from `list --output json`) |
|
||||
| **Batch** | `--source TAG --force` | Delete all pairs matching a source tag |
|
||||
|
||||
```bash
|
||||
# Interactive: checkbox UI (requires wren-engine[interactive])
|
||||
wren memory forget
|
||||
wren memory forget --source seed
|
||||
|
||||
# Non-interactive: delete by ID
|
||||
wren memory forget --id 3 --force
|
||||
wren memory forget --id 3 --id 7 --id 12 --force
|
||||
|
||||
# Batch: delete all seed pairs (re-index will regenerate)
|
||||
wren memory forget --source seed --force
|
||||
```
|
||||
|
||||
The interactive mode requires the `interactive` extra:
|
||||
|
||||
```bash
|
||||
pip install "wren-engine[memory,interactive]"
|
||||
```
|
||||
|
||||
If InquirerPy is not installed, the command prints a hint and suggests using `--id` mode instead.
|
||||
|
||||
**Note on `_row_id`:** Row IDs come from `wren memory list --output json`. They are positional indices and may change after deletions — always re-list before using them.
|
||||
|
||||
## Exporting and importing pairs
|
||||
|
||||
### Dump: export to YAML
|
||||
|
||||
Export NL-SQL pairs to a human-readable YAML file:
|
||||
|
||||
```bash
|
||||
wren memory dump # write to project queries.yml (or stdout)
|
||||
wren memory dump --source user # only user-confirmed pairs
|
||||
wren memory dump -o queries.yml # explicit output path
|
||||
wren memory dump -o - # force stdout (for piping)
|
||||
```
|
||||
|
||||
Output format:
|
||||
|
||||
```yaml
|
||||
version: 1
|
||||
exported_at: "2026-04-08T10:30:00+00:00"
|
||||
pairs:
|
||||
- nl: "monthly revenue by product category"
|
||||
sql: |
|
||||
SELECT category, SUM(revenue)
|
||||
FROM orders
|
||||
GROUP BY category
|
||||
source: user
|
||||
datasource: postgres-prod
|
||||
created_at: "2026-04-01T08:15:00+00:00"
|
||||
```
|
||||
|
||||
When run inside a project directory without `-o`, dump defaults to writing `<project>/queries.yml`.
|
||||
|
||||
### Load: import from YAML
|
||||
|
||||
Import NL-SQL pairs from a YAML file:
|
||||
|
||||
```bash
|
||||
wren memory load queries.yml # skip duplicates (idempotent)
|
||||
wren memory load queries.yml --upsert # update sql for existing nl_query
|
||||
wren memory load queries.yml --overwrite # clear same-source pairs first
|
||||
wren memory load queries.yml --dry-run # validate only, don't write
|
||||
```
|
||||
|
||||
| Mode | Flag | On duplicate | Use case |
|
||||
|------|------|-------------|----------|
|
||||
| **Skip** | (default) | Same `(nl, sql)` → skip | Safe idempotent load |
|
||||
| **Upsert** | `--upsert` | Same `nl_query` → replace sql | Iterating on SQL quality |
|
||||
| **Overwrite** | `--overwrite` | Clear same-source pairs first | Full sync from file |
|
||||
|
||||
`--upsert` and `--overwrite` are mutually exclusive.
|
||||
|
||||
Embeddings are recalculated on import — the YAML file only stores text, not vectors.
|
||||
|
||||
## Project integration: `queries.yml`
|
||||
|
||||
NL-SQL pairs can be managed as part of your project, alongside models, views, and instructions:
|
||||
|
||||
```text
|
||||
project_root/
|
||||
├── wren_project.yml
|
||||
├── models/
|
||||
├── views/
|
||||
├── relationships.yml
|
||||
├── instructions.md
|
||||
├── queries.yml ← curated NL-SQL pairs
|
||||
└── target/
|
||||
└── mdl.json
|
||||
```
|
||||
|
||||
### Scaffolding
|
||||
|
||||
`wren context init` creates an empty `queries.yml`:
|
||||
|
||||
```yaml
|
||||
# Curated NL-SQL pairs for this project.
|
||||
# These are auto-loaded into memory on `wren memory index`.
|
||||
# Use `wren memory dump` to export pairs from memory to this file.
|
||||
# Format: same as `wren memory dump` output.
|
||||
version: 1
|
||||
pairs: []
|
||||
```
|
||||
|
||||
### Auto-loading on index
|
||||
|
||||
`wren memory index` automatically loads `queries.yml` from the project root after indexing the schema and generating seeds. Duplicate pairs are skipped (idempotent).
|
||||
|
||||
```bash
|
||||
wren memory index # indexes schema + seeds + loads queries.yml
|
||||
wren memory index --no-queries # skip auto-loading queries.yml
|
||||
```
|
||||
|
||||
### Typical workflow
|
||||
|
||||
```bash
|
||||
# 1. Agent accumulates pairs during usage
|
||||
wren memory store --nl "..." --sql "..."
|
||||
|
||||
# 2. Export user-confirmed pairs to project
|
||||
wren memory dump --source user
|
||||
|
||||
# 3. Review, edit SQL, commit
|
||||
git add queries.yml && git commit -m "curate query pairs"
|
||||
|
||||
# 4. New environment: index loads everything
|
||||
wren memory index
|
||||
```
|
||||
|
||||
## Agent workflow
|
||||
|
||||
The memory layer fits into the agent's query workflow like this:
|
||||
|
||||
```
|
||||
User asks a question
|
||||
│
|
||||
├── 1. wren memory recall -q "..." → find similar past queries (few-shot examples)
|
||||
├── 2. wren memory fetch -q "..." → get relevant schema context
|
||||
├── 3. Write SQL using examples + context
|
||||
├── 4. wren --sql "..." → execute
|
||||
│
|
||||
└── 5. wren memory store --nl "..." --sql "..." → save for future recall
|
||||
```
|
||||
|
||||
Each stored query improves future recall accuracy — the system learns from usage.
|
||||
|
||||
### Memory hygiene (for agents)
|
||||
|
||||
Agents should use non-interactive mode (`--id` + `--force`) for memory management:
|
||||
|
||||
```bash
|
||||
# Review stored pairs
|
||||
wren memory list --output json
|
||||
|
||||
# After confirming a query is WRONG: forget then store corrected version
|
||||
wren memory forget --id <id> --force
|
||||
wren memory store --nl "..." --sql "..."
|
||||
|
||||
# Batch cleanup: remove all seed pairs (re-index will regenerate)
|
||||
wren memory forget --source seed --force
|
||||
|
||||
# Backup before destructive ops
|
||||
wren memory dump -o /tmp/backup.yml
|
||||
```
|
||||
|
||||
## Housekeeping
|
||||
|
||||
```bash
|
||||
wren memory status # show index stats
|
||||
wren memory reset # drop all tables (prompts for confirmation)
|
||||
wren memory reset --force # drop without confirmation
|
||||
```
|
||||
|
||||
## Command reference
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `memory index` | Index MDL schema + seeds + auto-load `queries.yml` |
|
||||
| `memory fetch` | Get schema context (full text or embedding search) |
|
||||
| `memory describe` | Print full schema as plain text (no LanceDB needed) |
|
||||
| `memory store` | Store a single NL-SQL pair |
|
||||
| `memory recall` | Search past pairs by semantic similarity |
|
||||
| `memory list` | Browse all pairs with filtering and pagination |
|
||||
| `memory forget` | Delete pairs (interactive, by ID, or by source) |
|
||||
| `memory dump` | Export pairs to YAML |
|
||||
| `memory load` | Import pairs from YAML |
|
||||
| `memory status` | Show index statistics |
|
||||
| `memory reset` | Drop all memory tables |
|
||||
|
||||
## Storage and version control
|
||||
|
||||
Memory files are binary (LanceDB format) and stored in `<project>/.wren/memory/`. By default this directory is gitignored.
|
||||
|
||||
- **schema_items** — fully rebuildable from `wren memory index`, safe to delete
|
||||
- **query_history** — accumulated NL-SQL pairs, exportable via `wren memory dump`
|
||||
|
||||
Use `queries.yml` to version-control curated pairs instead of committing binary LanceDB files. The dump/load workflow avoids merge conflicts and enables code review of NL-SQL pairs.
|
||||
@@ -0,0 +1,83 @@
|
||||
---
|
||||
sidebar_label: Model your business
|
||||
---
|
||||
|
||||
# Model your business
|
||||
|
||||
Turn your warehouse schema into an agent-readable MDL project that captures your business logic.
|
||||
|
||||
## What you'll end up with
|
||||
|
||||
- A Wren project directory with `wren_project.yml`, `models/`, `views/`, `relationships.yml`, and `instructions.md`
|
||||
- A compiled `target/mdl.json` ready for the engine
|
||||
- A memory index over the modeled schema, so agents can fetch relevant context per question
|
||||
- A first query that runs through MDL — not against raw tables
|
||||
|
||||
## The flow
|
||||
|
||||
1. **Connect your data source.** See [Connect your data](./connect.md) for profile setup.
|
||||
2. **Open your agent in a fresh project directory and ask:**
|
||||
> Use the `wren-generate-mdl` skill to scaffold an MDL project for this database.
|
||||
3. **Review the scaffold.** The agent introspects schema, normalizes types, detects relationships, and writes one model per table. It will ask one focused question whenever it cannot decide alone — naming, canonical tables, ambiguous foreign keys.
|
||||
4. **Build and index.** The skill finishes with:
|
||||
```bash
|
||||
wren context build
|
||||
wren memory index
|
||||
```
|
||||
5. **Run a first modeled query.**
|
||||
```bash
|
||||
wren --sql "SELECT * FROM customers LIMIT 5"
|
||||
```
|
||||
|
||||
## What scaffolding gives you
|
||||
|
||||
The first pass is rough but functional. The agent produces:
|
||||
|
||||
- **One model per physical table** with explicit column declarations (no `SELECT *` ambiguity)
|
||||
- **Type normalization** through `wren utils parse-type` so the manifest types are canonical
|
||||
- **Primary keys and relationships** inferred from foreign-key metadata where the connector exposes them
|
||||
- **Empty `instructions.md`** for you to fill with business rules
|
||||
|
||||
Everything is YAML you can review and version. Nothing is locked behind a UI.
|
||||
|
||||
## What scaffolding cannot give you
|
||||
|
||||
The hard meaning lives outside the database. Scaffolding cannot tell you:
|
||||
|
||||
- Which of `customers` / `customers_v3` / `loyalty_v3` is canonical
|
||||
- Why `status = 4` means refunded
|
||||
- Whether `active customer` excludes service accounts
|
||||
- That "Project Lighthouse" maps to `campaign_id = 4172`
|
||||
|
||||
Bring those in with [Refine answer quality](./refine.md) — the grill / auto-pilot loop that fills the semantic gaps.
|
||||
|
||||
## Enrich as you go
|
||||
|
||||
Once you have a baseline, add depth incrementally:
|
||||
|
||||
- **Descriptions and business names** on models and columns — memory uses these for retrieval
|
||||
- **Calculated fields** for metrics the team agrees on (`revenue = net_total - refunds`)
|
||||
- **Relationship columns** so agents can write `orders.customer.first_name` without manual joins
|
||||
- **Views** for stable, pre-built query shapes (`completed_orders`, `monthly_revenue`)
|
||||
- **Cubes** for governed aggregations — see [Pre-aggregate with cubes](./cubes.md)
|
||||
- **Selective column exposure** to keep PII columns invisible to agents — omit them from the model and they cannot be queried
|
||||
|
||||
Each time you edit, rebuild and re-index:
|
||||
|
||||
```bash
|
||||
wren context build
|
||||
wren memory index
|
||||
```
|
||||
|
||||
## When to come back here
|
||||
|
||||
- A new table or domain enters your warehouse
|
||||
- Schema drift breaks an existing model
|
||||
- Your team agrees on a new metric definition worth promoting from `instructions.md` into a calculated field
|
||||
- An AI coding agent suggests a structural change worth reviewing
|
||||
|
||||
## See also
|
||||
|
||||
- [MDL schema reference](/oss/reference/mdl) — every field accepted in MDL files
|
||||
- [Refine answer quality](./refine.md) — close the loop with memory and instructions
|
||||
- [What does MDL do for the agent?](/oss/concepts/what_is_mdl) — the design idea behind MDL
|
||||
@@ -1,188 +0,0 @@
|
||||
# Cube
|
||||
|
||||
A **Cube** is a pre-aggregation semantic layer object that defines reusable
|
||||
aggregations on top of a Model or View. Clients send a structured `CubeQuery`
|
||||
(measures, dimensions, optional time bucket + filters); the engine produces
|
||||
`SELECT … GROUP BY` SQL and runs it through the same path as `wren --sql`.
|
||||
|
||||
## When to use
|
||||
|
||||
Define a cube when you want to:
|
||||
|
||||
- run aggregation queries (`SUM`, `COUNT`, `AVG`) grouped by dimensions
|
||||
- group by time (`year` / `quarter` / `month` / `week` / `day` / `hour` / `minute`)
|
||||
- share business metrics between AI agents, BI dashboards, and the browser SDK
|
||||
- expose drill-down hierarchies for dashboard navigation
|
||||
|
||||
Cubes are particularly useful for AI agents: instead of writing `GROUP BY` and
|
||||
`DATE_TRUNC` SQL by hand (and getting it wrong on small / local models), an
|
||||
agent picks a measure + dimension + granularity from the cube definition and
|
||||
the translator builds the SQL.
|
||||
|
||||
## Structure
|
||||
|
||||
Each cube lives in its own file under `cubes/` as `cubes/<name>.yml`. The
|
||||
YAML uses `snake_case`; `wren context build` converts to `camelCase` for
|
||||
the engine.
|
||||
|
||||
```yaml
|
||||
# cubes/order_metrics.yml
|
||||
name: order_metrics
|
||||
base_object: orders # name of a defined Model or View
|
||||
|
||||
measures:
|
||||
- name: revenue
|
||||
expression: "SUM(o_totalprice)"
|
||||
type: DOUBLE
|
||||
- name: order_count
|
||||
expression: "COUNT(*)"
|
||||
type: BIGINT
|
||||
- name: avg_order_value
|
||||
expression: "revenue / order_count" # ← derived measure (auto-inlined)
|
||||
type: DOUBLE
|
||||
|
||||
dimensions:
|
||||
- name: status
|
||||
expression: "o_orderstatus"
|
||||
type: VARCHAR
|
||||
|
||||
time_dimensions:
|
||||
- name: created_at
|
||||
expression: "o_orderdate"
|
||||
type: DATE
|
||||
|
||||
hierarchies:
|
||||
time_drill:
|
||||
- created_at # add finer-grained levels here for drill-down
|
||||
```
|
||||
|
||||
### JSON format (MDL manifest)
|
||||
|
||||
After `wren context build`, the same cube serialises to camelCase:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "order_metrics",
|
||||
"baseObject": "orders",
|
||||
"measures": [
|
||||
{ "name": "revenue", "expression": "SUM(o_totalprice)", "type": "DOUBLE" }
|
||||
],
|
||||
"dimensions": [
|
||||
{ "name": "status", "expression": "o_orderstatus", "type": "VARCHAR" }
|
||||
],
|
||||
"timeDimensions": [
|
||||
{ "name": "created_at", "expression": "o_orderdate", "type": "DATE" }
|
||||
],
|
||||
"hierarchies": { "time_drill": ["created_at"] }
|
||||
}
|
||||
```
|
||||
|
||||
## Fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `name` | Yes | Unique cube identifier (used by `wren cube describe`, `cubeQuery.cube`, …) |
|
||||
| `base_object` | Yes | Name of a defined Model or View; becomes `FROM <base_object>` in the generated SQL |
|
||||
| `measures` | Yes | List of `{ name, expression, type }`. `expression` may reference physical columns or other measure names (derived measure) |
|
||||
| `dimensions` | No | List of `{ name, expression, type }` used for `GROUP BY` and filters |
|
||||
| `time_dimensions` | No | List of `{ name, expression, type }`. Granularity is picked at query time, not in the cube definition |
|
||||
| `hierarchies` | No | Map of `name → [dimension_names]`, for BI drill-down navigation. Levels must reference declared dimensions or time dimensions. |
|
||||
|
||||
## Time granularity
|
||||
|
||||
Supported values at query time: `year`, `quarter`, `month`, `week`, `day`,
|
||||
`hour`, `minute`.
|
||||
|
||||
When a query specifies a time dimension with a granularity, the translator
|
||||
emits `DATE_TRUNC(granularity, expr)` in the projection and `GROUP BY`. The
|
||||
column alias is `<name>__<granularity>` (e.g., `created_at__month`). An
|
||||
optional `dateRange: [start, end]` becomes a half-open `[start, end)` `WHERE`
|
||||
clause.
|
||||
|
||||
## Derived measures
|
||||
|
||||
A measure's `expression` may reference other measures by name:
|
||||
|
||||
```yaml
|
||||
- name: avg_order_value
|
||||
expression: "revenue / order_count"
|
||||
```
|
||||
|
||||
The translator inlines `revenue` and `order_count` before emitting SQL:
|
||||
|
||||
```text
|
||||
avg_order_value → (SUM(o_totalprice)) / (COUNT(*))
|
||||
```
|
||||
|
||||
Substitution is longest-prefix-first to avoid partial-token replacement
|
||||
(e.g., `revenue_2` substitutes before `revenue`). At query time the
|
||||
translator resolves only the transitive closure of the measures that the
|
||||
request actually names. Cube validity — including cycle detection across
|
||||
all derived measures — is enforced earlier during MDL analysis (see
|
||||
[Validation](#validation) below), so an invalid cube is rejected at load
|
||||
time regardless of which measures a later query references.
|
||||
|
||||
Expressions containing `$` (Postgres `$1` placeholders or `$$tag$$`
|
||||
dollar-quoted strings) are preserved literally — the translator does not
|
||||
treat them as regex capture-group templates.
|
||||
|
||||
## Filter operators
|
||||
|
||||
`cubeQuery.filters` accepts these operators:
|
||||
|
||||
`eq` · `neq` · `in` · `not_in` · `gt` · `gte` · `lt` · `lte` ·
|
||||
`contains` · `starts_with` · `is_null` · `is_not_null`
|
||||
|
||||
`in` / `not_in` take an array value. `is_null` / `is_not_null` take no value.
|
||||
`contains` / `starts_with` produce `LIKE` patterns.
|
||||
|
||||
## Cube vs. View vs. Model
|
||||
|
||||
| Use case | Use |
|
||||
|---|---|
|
||||
| Expose raw rows (optionally with calculated fields) | [Model](./model.md) |
|
||||
| Name a complex `SELECT` for reuse | [View](./view.md) |
|
||||
| Predefined aggregation API (measures × dimensions) for agents / BI | **Cube** |
|
||||
|
||||
## CLI
|
||||
|
||||
- `wren cube list` — list every cube in the loaded MDL
|
||||
- `wren cube describe <name>` — pretty-print the cube schema
|
||||
- `wren cube query` — build a CubeQuery (CLI flags or `--from <json>`) and run it
|
||||
- `wren cube query --sql-only ...` — print the generated SQL without executing
|
||||
|
||||
See the [CLI reference](../../reference/cli.md#wren-cube--pre-aggregation-queries).
|
||||
|
||||
## WASM (browser)
|
||||
|
||||
The same translator is exposed in `@wrenai/wren-core-wasm`:
|
||||
|
||||
```javascript
|
||||
const cubes = engine.listCubes();
|
||||
const rows = await engine.cubeQuery({
|
||||
cube: "order_metrics",
|
||||
measures: ["revenue"],
|
||||
timeDimensions: [{ dimension: "created_at", granularity: "month" }],
|
||||
});
|
||||
```
|
||||
|
||||
See the [WASM SDK doc](../../sdk/wasm.md) for setup, the
|
||||
[WASM Agent Guide](https://github.com/Canner/WrenAI/blob/main/core/wren-core-wasm/AGENT_GUIDE.md)
|
||||
for embedding-in-an-agent patterns, and
|
||||
[`cube-explorer.html`](https://github.com/Canner/WrenAI/blob/main/core/wren-core-wasm/examples/cube-explorer.html)
|
||||
for an interactive form-driven builder.
|
||||
|
||||
## Validation
|
||||
|
||||
Wren-core validates cubes during `AnalyzedWrenMDL::analyze` — i.e., when the
|
||||
manifest is loaded into the engine, not just at query time:
|
||||
|
||||
- `base_object` must resolve to a defined Model or View
|
||||
- Derived measures must not form a cycle within the transitive closure of
|
||||
requested measures
|
||||
- Levels in `hierarchies` must reference a declared `dimension` or
|
||||
`time_dimension`
|
||||
|
||||
The CLI's `wren context validate` also runs structural checks on cube YAML
|
||||
(unique names, `base_object` exists, hierarchy levels) before the manifest
|
||||
reaches the engine, so common mistakes surface at edit time.
|
||||
@@ -1,473 +0,0 @@
|
||||
# Model
|
||||
|
||||
A **Model** is the core building block of Wren MDL. It maps a physical table (or a SQL expression) to a named semantic entity that AI agents and SQL clients query by name. Models define which columns are exposed and how columns relate to other models.
|
||||
|
||||
## Defining a Model
|
||||
|
||||
Every model requires three things:
|
||||
|
||||
1. A **name** — the identifier used in queries (`SELECT * FROM customers`)
|
||||
2. A **data source** — where the data lives (`table_reference` or `ref_sql`)
|
||||
3. **Columns** — the fields that are exposed
|
||||
|
||||
### YAML format (wren project)
|
||||
|
||||
Each model lives in its own directory under `models/` as `models/<name>/metadata.yml`.
|
||||
|
||||
```yaml
|
||||
# models/customers/metadata.yml
|
||||
name: customers
|
||||
table_reference:
|
||||
catalog: jaffle_shop
|
||||
schema: main
|
||||
table: customers
|
||||
primary_key: customer_id
|
||||
columns:
|
||||
- name: customer_id
|
||||
type: INTEGER
|
||||
is_calculated: false
|
||||
not_null: true
|
||||
is_primary_key: true
|
||||
properties: {}
|
||||
- name: first_name
|
||||
type: VARCHAR
|
||||
is_calculated: false
|
||||
not_null: false
|
||||
properties: {}
|
||||
- name: last_name
|
||||
type: VARCHAR
|
||||
is_calculated: false
|
||||
not_null: false
|
||||
properties: {}
|
||||
- name: number_of_orders
|
||||
type: BIGINT
|
||||
is_calculated: false
|
||||
not_null: false
|
||||
properties: {}
|
||||
- name: customer_lifetime_value
|
||||
type: DOUBLE
|
||||
is_calculated: false
|
||||
not_null: false
|
||||
properties: {}
|
||||
cached: false
|
||||
properties: {}
|
||||
```
|
||||
|
||||
### JSON format (MDL manifest)
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "customers",
|
||||
"tableReference": {
|
||||
"catalog": "jaffle_shop",
|
||||
"schema": "main",
|
||||
"table": "customers"
|
||||
},
|
||||
"primaryKey": "customer_id",
|
||||
"columns": [
|
||||
{ "name": "customer_id", "type": "INTEGER", "isPrimaryKey": true, "isCalculated": false },
|
||||
{ "name": "first_name", "type": "VARCHAR", "isCalculated": false },
|
||||
{ "name": "last_name", "type": "VARCHAR", "isCalculated": false },
|
||||
{ "name": "number_of_orders", "type": "BIGINT", "isCalculated": false },
|
||||
{ "name": "customer_lifetime_value", "type": "DOUBLE", "isCalculated": false }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Model Fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `name` | Yes | Unique identifier used in SQL queries |
|
||||
| `table_reference` | One of two | Points to an existing physical table (`catalog.schema.table`) |
|
||||
| `ref_sql` | One of two | A SQL SELECT statement used as the model's data source |
|
||||
| `columns` | Yes | List of columns to expose (see [Column Fields](#column-fields)) |
|
||||
| `primary_key` | No | Column name that uniquely identifies a row; required for relationships |
|
||||
| `cached` | No | Whether query results for this model should be cached; `false` by default |
|
||||
| `dialect` | No | SQL dialect of the model's `ref_sql` (e.g. `bigquery`, `postgres`). Overrides the project-level `data_source` for this model. Requires `schema_version: 3`. See [Dialect Override](./wren_project.md#dialect-override). |
|
||||
| `properties` | No | Arbitrary key-value metadata (description, tags, etc.) |
|
||||
|
||||
## Data Source: Two Ways to Point at Data
|
||||
|
||||
A model must define its source in exactly one of two ways. Using both `table_reference` and `ref_sql` in the same model is a validation error.
|
||||
|
||||
### 1. `table_reference` — map to a physical table
|
||||
|
||||
Used when the underlying table already exists in the database.
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `catalog` | Database catalog. Empty string if not applicable. For DuckDB, use the DB file name without extension (e.g. `jaffle_shop.duckdb` → `jaffle_shop`). |
|
||||
| `schema` | Database schema (e.g. `public`, `main`). |
|
||||
| `table` | Physical table name. |
|
||||
|
||||
**jaffle_shop example** — the `orders` model maps directly to `jaffle_shop.main.orders`:
|
||||
|
||||
```yaml
|
||||
name: orders
|
||||
table_reference:
|
||||
catalog: jaffle_shop
|
||||
schema: main
|
||||
table: orders
|
||||
```
|
||||
|
||||
When a query like `SELECT * FROM orders` is executed, Wren rewrites it to the fully-qualified physical table.
|
||||
|
||||
### 2. `ref_sql` — define the model with SQL
|
||||
|
||||
Used when the model is derived — for example, a staging transform or a complex join that doesn't exist as a physical table.
|
||||
|
||||
The SQL can be inline in `metadata.yml` or in a separate `ref_sql.sql` file. The `.sql` file takes precedence if both exist.
|
||||
|
||||
**Inline in metadata.yml:**
|
||||
|
||||
```yaml
|
||||
name: revenue_summary
|
||||
ref_sql: >
|
||||
SELECT DATE_TRUNC('month', order_date) AS month,
|
||||
SUM(total) AS total_revenue
|
||||
FROM orders
|
||||
GROUP BY 1
|
||||
columns:
|
||||
- name: month
|
||||
type: DATE
|
||||
is_calculated: false
|
||||
not_null: true
|
||||
properties: {}
|
||||
- name: total_revenue
|
||||
type: DECIMAL
|
||||
is_calculated: false
|
||||
not_null: false
|
||||
properties: {}
|
||||
```
|
||||
|
||||
**Separate SQL file:**
|
||||
|
||||
```yaml
|
||||
# models/revenue_summary/metadata.yml
|
||||
name: revenue_summary
|
||||
columns:
|
||||
- name: month
|
||||
type: DATE
|
||||
is_calculated: false
|
||||
not_null: true
|
||||
properties: {}
|
||||
- name: total_revenue
|
||||
type: DECIMAL
|
||||
is_calculated: false
|
||||
not_null: false
|
||||
properties: {}
|
||||
```
|
||||
|
||||
```sql
|
||||
-- models/revenue_summary/ref_sql.sql
|
||||
SELECT DATE_TRUNC('month', order_date) AS month,
|
||||
SUM(total) AS total_revenue
|
||||
FROM orders
|
||||
GROUP BY 1
|
||||
```
|
||||
|
||||
## Column Fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `name` | Yes | Column name used in SQL |
|
||||
| `type` | Yes | SQL data type (`VARCHAR`, `INTEGER`, `DOUBLE`, `DATE`, `TIMESTAMP`, etc.) |
|
||||
| `is_calculated` | No | If `true`, the column value is derived from `expression` at query time |
|
||||
| `expression` | No | SQL expression for calculated columns |
|
||||
| `relationship` | No | Name of a [Relationship](./relation.md) — makes this column a join handle |
|
||||
| `not_null` | No | Constraint hint; `false` by default |
|
||||
| `is_primary_key` | No | Marks the column as the model's primary key |
|
||||
| `is_hidden` | No | Engine-internal flag; column is excluded from the symbol table and invisible to all clients |
|
||||
| `properties` | No | Arbitrary metadata |
|
||||
|
||||
### Regular columns
|
||||
|
||||
A regular column maps to a field in the underlying table. These are called **source columns** — the engine registers them in the physical schema so DataFusion can read them directly.
|
||||
|
||||
By default, the model column name is used as the physical field name. If the physical column has a different name, use `expression` to declare a simple rename:
|
||||
|
||||
```yaml
|
||||
- name: order_date # model name (exposed to clients)
|
||||
type: DATE
|
||||
is_calculated: false
|
||||
|
||||
- name: customer_id # renamed from the physical column "usr_id"
|
||||
type: INTEGER
|
||||
is_calculated: false
|
||||
expression: usr_id
|
||||
```
|
||||
|
||||
The `expression` on a non-calculated column must be a single column reference — it cannot contain operators or function calls. See [Engine Internals](#engine-internals) for the full resolution rules.
|
||||
|
||||
### Calculated columns
|
||||
|
||||
A calculated column is computed from a SQL expression at query time. Wren inlines the expression into the generated SQL.
|
||||
|
||||
```yaml
|
||||
- name: is_large_order
|
||||
type: BOOLEAN
|
||||
is_calculated: true
|
||||
expression: "amount > 100"
|
||||
```
|
||||
|
||||
Calculated columns can reference other columns in the same model or traverse relationships:
|
||||
|
||||
```yaml
|
||||
- name: customer_name
|
||||
type: VARCHAR
|
||||
is_calculated: true
|
||||
expression: "customers.first_name || ' ' || customers.last_name"
|
||||
relationship: orders_customers
|
||||
```
|
||||
|
||||
### Relationship columns
|
||||
|
||||
A relationship column declares a join path to another model. The `relationship` field names a [Relationship](./relation.md) defined elsewhere in the MDL.
|
||||
|
||||
```yaml
|
||||
# In the orders model
|
||||
- name: customer
|
||||
type: customers # the related model name
|
||||
relationship: orders_customers
|
||||
```
|
||||
|
||||
This makes `orders.customer.first_name` valid SQL — Wren resolves the join automatically.
|
||||
|
||||
## jaffle_shop Example
|
||||
|
||||
The jaffle_shop dataset has three layers of models that illustrate the full range of modeling patterns:
|
||||
|
||||
```
|
||||
raw_orders ──► stg_orders ──► orders
|
||||
raw_customers ──► stg_customers ──► customers
|
||||
raw_payments ──► stg_payments
|
||||
```
|
||||
|
||||
### Raw layer — `table_reference`
|
||||
|
||||
Raw models point directly at source tables with minimal transformation:
|
||||
|
||||
```yaml
|
||||
name: raw_orders
|
||||
table_reference:
|
||||
catalog: jaffle_shop
|
||||
schema: main
|
||||
table: raw_orders
|
||||
primary_key: id
|
||||
columns:
|
||||
- { name: id, type: INTEGER, is_primary_key: true }
|
||||
- { name: user_id, type: INTEGER }
|
||||
- { name: order_date, type: DATE }
|
||||
- { name: status, type: VARCHAR }
|
||||
```
|
||||
|
||||
### Staging layer — renamed and typed
|
||||
|
||||
Staging models clean column names and enforce types. They use `ref_sql` or point at staging tables:
|
||||
|
||||
```yaml
|
||||
name: stg_orders
|
||||
table_reference:
|
||||
catalog: jaffle_shop
|
||||
schema: main
|
||||
table: stg_orders
|
||||
primary_key: order_id
|
||||
columns:
|
||||
- { name: order_id, type: INTEGER, is_primary_key: true }
|
||||
- { name: customer_id, type: INTEGER }
|
||||
- { name: order_date, type: DATE }
|
||||
- { name: status, type: VARCHAR }
|
||||
```
|
||||
|
||||
### Mart layer — enriched with metrics
|
||||
|
||||
Mart models expose business-ready fields, including pre-aggregated metrics:
|
||||
|
||||
```yaml
|
||||
name: customers
|
||||
table_reference:
|
||||
catalog: jaffle_shop
|
||||
schema: main
|
||||
table: customers
|
||||
primary_key: customer_id
|
||||
columns:
|
||||
- { name: customer_id, type: INTEGER, is_primary_key: true }
|
||||
- { name: first_name, type: VARCHAR }
|
||||
- { name: last_name, type: VARCHAR }
|
||||
- { name: first_order, type: DATE }
|
||||
- { name: most_recent_order, type: DATE }
|
||||
- { name: number_of_orders, type: BIGINT }
|
||||
- { name: customer_lifetime_value, type: DOUBLE }
|
||||
```
|
||||
|
||||
### Cross-model relationships
|
||||
|
||||
The `orders_customers` relationship (defined in `relationships.yml`) links `orders.customer_id → customers.customer_id`. With this in place, you can query across models without writing any JOIN:
|
||||
|
||||
```sql
|
||||
-- Wren resolves the join automatically
|
||||
SELECT
|
||||
order_id,
|
||||
orders.customer.first_name,
|
||||
orders.customer.last_name,
|
||||
amount
|
||||
FROM orders
|
||||
WHERE orders.customer.number_of_orders > 3
|
||||
```
|
||||
|
||||
See [Relationship](./relation.md) for full details on defining join paths.
|
||||
|
||||
## Using Models in SQL
|
||||
|
||||
Once defined, models are first-class SQL table names:
|
||||
|
||||
```sql
|
||||
SELECT * FROM customers;
|
||||
|
||||
SELECT o.order_id, o.amount, c.first_name
|
||||
FROM orders o
|
||||
JOIN customers c ON o.customer_id = c.customer_id;
|
||||
|
||||
-- Or let Wren handle the join via a relationship column:
|
||||
SELECT order_id, customer.first_name, amount
|
||||
FROM orders;
|
||||
```
|
||||
|
||||
Wren translates these queries to the appropriate dialect SQL for the connected data source before execution.
|
||||
|
||||
## Column-Level Access Control via Selective Exposure
|
||||
|
||||
A model does not have to expose every column in the underlying table. By explicitly listing only the columns a client should see, you create a hard boundary at the semantic layer — columns that are not declared in the model simply do not exist from the client's perspective.
|
||||
|
||||
This is especially valuable in the AI era. When an AI coding agent connects through Wren, it can only discover and query the columns that are declared in the model. Sensitive fields that are omitted from the model are physically invisible to the agent — no prompt injection or accidental exposure can retrieve them.
|
||||
|
||||
### Example: hiding PII from AI agents
|
||||
|
||||
Suppose the physical `customers` table contains PII columns that should never reach an AI agent:
|
||||
|
||||
| Physical column | Expose to AI? |
|
||||
|-----------------|--------------|
|
||||
| `customer_id` | Yes |
|
||||
| `first_name` | Yes |
|
||||
| `last_name` | Yes |
|
||||
| `email` | **No** |
|
||||
| `phone_number` | **No** |
|
||||
| `date_of_birth` | **No** |
|
||||
| `number_of_orders` | Yes |
|
||||
| `customer_lifetime_value` | Yes |
|
||||
|
||||
Define the model with only the safe columns:
|
||||
|
||||
```yaml
|
||||
name: customers
|
||||
table_reference:
|
||||
catalog: jaffle_shop
|
||||
schema: main
|
||||
table: customers
|
||||
primary_key: customer_id
|
||||
columns:
|
||||
- { name: customer_id, type: INTEGER, is_primary_key: true }
|
||||
- { name: first_name, type: VARCHAR }
|
||||
- { name: last_name, type: VARCHAR }
|
||||
- { name: number_of_orders, type: BIGINT }
|
||||
- { name: customer_lifetime_value, type: DOUBLE }
|
||||
```
|
||||
|
||||
The AI agent sees a `customers` model with five columns. `email`, `phone_number`, and `date_of_birth` do not appear in schema introspection, cannot be referenced in SQL, and are never included in query results — regardless of what the agent asks.
|
||||
|
||||
### Summary
|
||||
|
||||
| Technique | Column reachable via SQL | Visible in schema |
|
||||
|-----------|--------------------------|-------------------|
|
||||
| Declared column | Yes | Yes |
|
||||
| Omitted from model | **No** | **No** |
|
||||
|
||||
Use **omission** to enforce hard boundaries for AI agents.
|
||||
|
||||
## Engine Internals
|
||||
|
||||
### Physical schema registration (`infer_and_register_remote_table`)
|
||||
|
||||
When the engine initialises a model, it builds an Arrow schema that represents the physical table as DataFusion sees it. Only **source columns** — columns that map directly to a field in the underlying table — are registered in this schema. The engine uses `infer_source_column` to decide whether each column qualifies, following these rules in order:
|
||||
|
||||
| Column configuration | Source column? | Physical field name |
|
||||
|----------------------|---------------|---------------------|
|
||||
| `is_calculated: true` | No | — computed at query time from `expression` |
|
||||
| has `relationship` | No | — resolved as a join at query time |
|
||||
| no `expression` | **Yes** | same as `name` |
|
||||
| `expression` is a simple column reference | **Yes** | inferred from the expression (supports rename) |
|
||||
| `expression` is a complex SQL expression | No | — cannot be resolved statically |
|
||||
| `is_hidden: true` | **excluded** | stripped from the symbol table before this step |
|
||||
|
||||
### `is_hidden` — engine-internal columns
|
||||
|
||||
`is_hidden: true` is an engine-internal flag. The engine strips hidden columns from its symbol table during MDL initialisation (`get_visible_columns`), so they never appear in schema introspection, lineage analysis, or access-control checks. They are invisible to every client — AI agents, SQL clients, and the metadata API alike.
|
||||
|
||||
This is used for columns the engine generates internally (e.g. join keys added automatically for relationship resolution) that should not be addressable by user queries.
|
||||
|
||||
### `expression` on a non-calculated column — column rename
|
||||
|
||||
When `is_calculated` is `false` but an `expression` is present, the expression must be a **simple column reference**. The engine uses it to resolve which physical column to read and registers the model column name as an alias.
|
||||
|
||||
```yaml
|
||||
# Physical table has column "usr_id"; expose it as "customer_id" in the model
|
||||
- name: customer_id
|
||||
type: INTEGER
|
||||
is_calculated: false
|
||||
expression: usr_id
|
||||
```
|
||||
|
||||
At query time `SELECT customer_id FROM stg_orders` becomes `SELECT usr_id AS customer_id FROM ...` in the generated SQL.
|
||||
|
||||
If the expression is **compound** (`table.column`), the engine takes the last identifier as the physical column name:
|
||||
|
||||
```yaml
|
||||
- name: customer_id
|
||||
type: INTEGER
|
||||
is_calculated: false
|
||||
expression: raw_orders.user_id # physical name resolved as "user_id"
|
||||
```
|
||||
|
||||
If the expression cannot be reduced to a single identifier (e.g. `amount * 1.1`), the column is not registered as a source column — it must use `is_calculated: true` instead.
|
||||
|
||||
### `is_calculated` + `expression` — computed column
|
||||
|
||||
A calculated column is **never** registered as a source column. The engine inlines the `expression` SQL directly into the generated query at plan time:
|
||||
|
||||
```yaml
|
||||
- name: total_with_tax
|
||||
type: DOUBLE
|
||||
is_calculated: true
|
||||
expression: "amount * 1.1"
|
||||
```
|
||||
|
||||
Generated SQL: `SELECT amount * 1.1 AS total_with_tax FROM orders`
|
||||
|
||||
Calculated columns can also traverse relationship joins:
|
||||
|
||||
```yaml
|
||||
- name: customer_name
|
||||
type: VARCHAR
|
||||
is_calculated: true
|
||||
expression: "customers.first_name || ' ' || customers.last_name"
|
||||
relationship: orders_customers
|
||||
```
|
||||
|
||||
The engine resolves `customers.*` references by expanding the `orders_customers` join automatically.
|
||||
|
||||
### Summary
|
||||
|
||||
```
|
||||
Column definition
|
||||
│
|
||||
├── is_hidden: true → stripped from symbol table; invisible to all clients
|
||||
│
|
||||
├── is_calculated: true → inlined as SQL expression at query time
|
||||
│ └── relationship → join is expanded before inlining
|
||||
│
|
||||
├── no expression → direct physical column (name = physical name)
|
||||
│
|
||||
└── expression (simple) → rename: physical name from expression, model name as alias
|
||||
expression (complex) → must use is_calculated: true
|
||||
```
|
||||
@@ -1,124 +0,0 @@
|
||||
# Overview
|
||||
|
||||
## Data modeling in Wren AI
|
||||
|
||||
Wren AI uses Modeling Definition Language (MDL) to describe business data in a structured, queryable form. Modeling is how you turn physical tables and raw schemas into context that can be reused by SQL clients and AI agents.
|
||||
|
||||
In practice, the modeling layer defines:
|
||||
|
||||
- which datasets are exposed
|
||||
- how tables relate to each other
|
||||
- which calculations should be reused
|
||||
- which query interfaces should be published as stable objects
|
||||
|
||||
This guide provides a high-level map of the core modeling primitives in Wren AI.
|
||||
|
||||
## Core modeling objects
|
||||
|
||||
### Model
|
||||
|
||||
A **Model** is the primary building block in MDL. It represents a logical dataset backed by a physical table or query definition.
|
||||
|
||||
Use a model when you need to:
|
||||
|
||||
- expose a curated set of columns
|
||||
- rename physical fields into business-facing names
|
||||
- define primary keys
|
||||
- attach relationships to other models
|
||||
- define calculated fields on top of source columns
|
||||
|
||||
Models are the foundation for the rest of the modeling system.
|
||||
|
||||
See [Model](./model.md).
|
||||
|
||||
### Relationship
|
||||
|
||||
A **Relationship** defines how two models are connected. Wren AI uses relationship metadata to plan joins and enable relationship-aware expressions.
|
||||
|
||||
Use a relationship when you need to:
|
||||
|
||||
- navigate from one model to another
|
||||
- define reusable join logic once
|
||||
- support calculated fields that reference related models
|
||||
- preserve consistent join behavior across queries
|
||||
|
||||
Relationships are especially important for context-aware querying, because they encode how business entities connect to each other.
|
||||
|
||||
See [Relationship](./relation.md).
|
||||
|
||||
### Calculated field
|
||||
|
||||
A **Calculated Field** is a model column whose value is derived from an expression rather than read directly from the underlying source.
|
||||
|
||||
Use a calculated field when you need to:
|
||||
|
||||
- define reusable business logic once
|
||||
- derive values from existing columns
|
||||
- reference fields on related models
|
||||
- reduce repeated SQL across downstream queries
|
||||
|
||||
Calculated fields let you move commonly repeated logic into the modeling layer instead of rewriting it in every query.
|
||||
|
||||
Calculated fields are defined in [Model](./model.md#calculated-columns) definitions.
|
||||
|
||||
### View
|
||||
|
||||
A **View** is a named SQL statement stored in the MDL. It behaves like a virtual table and can be queried by name.
|
||||
|
||||
Use a view when you need to:
|
||||
|
||||
- publish a reusable query result
|
||||
- expose a filtered or aggregated dataset
|
||||
- compose queries across multiple models
|
||||
- provide a stable interface for downstream consumers
|
||||
|
||||
Views are useful when the object you want to expose is query-shaped rather than column-modeled.
|
||||
|
||||
See [View](./view.md).
|
||||
|
||||
### Cube
|
||||
|
||||
A **Cube** is a pre-aggregated semantic object: a `baseObject` (a Model or
|
||||
View), plus declared measures, dimensions, time dimensions, and optional
|
||||
hierarchies.
|
||||
|
||||
Use a cube when you need to:
|
||||
|
||||
- expose pre-defined aggregations (e.g., total revenue by month)
|
||||
- give AI agents a structured aggregation API (no hand-written `GROUP BY`)
|
||||
- define drill-down hierarchies (year → quarter → month) for BI dashboards
|
||||
- share business metrics across CLI, browser (WASM), and downstream consumers
|
||||
|
||||
Cubes complement models: a model exposes the rows; a cube exposes the metrics
|
||||
defined on top of those rows.
|
||||
|
||||
See [Cube](./cube.md).
|
||||
|
||||
### Memory
|
||||
|
||||
The **Memory** layer is a LanceDB-backed semantic index that gives AI agents targeted schema context and few-shot query examples — without sending the entire schema in every prompt.
|
||||
|
||||
Use memory when you need to:
|
||||
|
||||
- provide relevant schema context to an AI agent per question
|
||||
- store confirmed NL-SQL pairs as few-shot examples for future queries
|
||||
- improve query accuracy over time as more examples are stored
|
||||
|
||||
Memory sits alongside the modeling layer: models define *what* the data looks like, memory helps agents *find* the right parts of it.
|
||||
|
||||
See [Memory](../memory.md).
|
||||
|
||||
## Choosing the right object
|
||||
|
||||
Use this rule of thumb:
|
||||
|
||||
- Use a **Model** to expose a business-facing dataset.
|
||||
- Use a **Relationship** to define how models join to each other.
|
||||
- Use a **Calculated Field** to define reusable expression logic inside a model.
|
||||
- Use a **View** to publish a reusable query result.
|
||||
- Use a **Cube** to publish a structured aggregation API (measures × dimensions).
|
||||
- Use **Memory** to give AI agents targeted context and learning from past queries.
|
||||
|
||||
## Why this matters
|
||||
|
||||
Good modeling is not only about query convenience. It is how Wren AI turns raw warehouse structure into durable business context. Once models, relationships, and calculations are defined centrally, queries become easier to write, easier to review, and more consistent across users, applications, and AI agents.
|
||||
@@ -1,172 +0,0 @@
|
||||
# Relationship
|
||||
|
||||
A **Relationship** defines a join path between two models. Once declared, the engine resolves the join automatically whenever a query traverses a relationship column — no explicit `JOIN` syntax required.
|
||||
|
||||
## Structure
|
||||
|
||||
```yaml
|
||||
# relationships.yml
|
||||
relationships:
|
||||
- name: orders_customers
|
||||
models:
|
||||
- orders
|
||||
- customers
|
||||
join_type: MANY_TO_ONE
|
||||
condition: orders.customer_id = customers.customer_id
|
||||
```
|
||||
|
||||
### JSON format (MDL manifest)
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "orders_customers",
|
||||
"models": ["orders", "customers"],
|
||||
"joinType": "MANY_TO_ONE",
|
||||
"condition": "orders.customer_id = customers.customer_id"
|
||||
}
|
||||
```
|
||||
|
||||
## Fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `name` | Yes | Unique identifier referenced by relationship columns |
|
||||
| `models` | Yes | Exactly two model names: `[from_model, to_model]` |
|
||||
| `join_type` | Yes | Cardinality of the join (see below) |
|
||||
| `condition` | Yes | SQL equality expression linking the two models |
|
||||
|
||||
## Join Types
|
||||
|
||||
| Value | Meaning |
|
||||
|-------|---------|
|
||||
| `ONE_TO_ONE` | Each row in the left model matches at most one row in the right model |
|
||||
| `ONE_TO_MANY` | One row in the left model matches many rows in the right model |
|
||||
| `MANY_TO_ONE` | Many rows in the left model match one row in the right model |
|
||||
| `MANY_TO_MANY` | Many rows on both sides |
|
||||
|
||||
The join type affects how the engine handles aggregation in calculated columns that traverse the relationship. For `TO_ONE` joins (`ONE_TO_ONE`, `MANY_TO_ONE`), the engine uses a simple join. For `TO_MANY` joins, the engine wraps the traversal in an aggregate subquery to avoid row multiplication.
|
||||
|
||||
## The `condition` Field
|
||||
|
||||
The condition is an equality expression using fully-qualified `model.column` references:
|
||||
|
||||
```yaml
|
||||
condition: orders.customer_id = customers.customer_id
|
||||
```
|
||||
|
||||
- Always use `model_name.column_name` on both sides
|
||||
- Only equality conditions are supported
|
||||
- The first model in `models` should appear on the left side of the condition
|
||||
|
||||
## jaffle_shop Example
|
||||
|
||||
The jaffle_shop workspace defines five relationships across its three model layers:
|
||||
|
||||
```yaml
|
||||
relationships:
|
||||
# mart layer
|
||||
- name: orders_customers
|
||||
models: [orders, customers]
|
||||
join_type: MANY_TO_ONE
|
||||
condition: orders.customer_id = customers.customer_id
|
||||
|
||||
# raw layer
|
||||
- name: raw_orders_raw_customers
|
||||
models: [raw_orders, raw_customers]
|
||||
join_type: MANY_TO_ONE
|
||||
condition: raw_orders.user_id = raw_customers.id
|
||||
|
||||
- name: raw_payments_raw_orders
|
||||
models: [raw_payments, raw_orders]
|
||||
join_type: MANY_TO_ONE
|
||||
condition: raw_payments.order_id = raw_orders.id
|
||||
|
||||
# staging layer
|
||||
- name: stg_orders_stg_customers
|
||||
models: [stg_orders, stg_customers]
|
||||
join_type: MANY_TO_ONE
|
||||
condition: stg_orders.customer_id = stg_customers.customer_id
|
||||
|
||||
- name: stg_payments_stg_orders
|
||||
models: [stg_payments, stg_orders]
|
||||
join_type: MANY_TO_ONE
|
||||
condition: stg_payments.order_id = stg_orders.order_id
|
||||
```
|
||||
|
||||
## Using Relationships in Queries
|
||||
|
||||
### Implicit join via relationship column
|
||||
|
||||
Declare a relationship column in a model to expose a join path:
|
||||
|
||||
```yaml
|
||||
# orders model — add a relationship column pointing to customers
|
||||
columns:
|
||||
- name: customer
|
||||
type: customers
|
||||
relationship: orders_customers
|
||||
```
|
||||
|
||||
Then query across models without writing a JOIN:
|
||||
|
||||
```sql
|
||||
-- Wren expands the join automatically
|
||||
SELECT order_id, customer.first_name, customer.last_name, amount
|
||||
FROM orders
|
||||
WHERE customer.number_of_orders > 3
|
||||
ORDER BY amount DESC;
|
||||
```
|
||||
|
||||
The engine resolves `customer.*` by expanding the `orders_customers` join, pushing it only as far as the referenced columns require.
|
||||
|
||||
### Calculated columns that traverse relationships
|
||||
|
||||
Relationship columns can be referenced inside `is_calculated` expressions:
|
||||
|
||||
```yaml
|
||||
- name: customer_name
|
||||
type: VARCHAR
|
||||
is_calculated: true
|
||||
expression: "customer.first_name || ' ' || customer.last_name"
|
||||
relationship: orders_customers
|
||||
```
|
||||
|
||||
For `TO_MANY` relationships, aggregate functions are required to avoid row multiplication:
|
||||
|
||||
```yaml
|
||||
# In the customers model — count orders per customer
|
||||
- name: order_count
|
||||
type: BIGINT
|
||||
is_calculated: true
|
||||
expression: "count(orders.order_id)"
|
||||
relationship: orders_customers
|
||||
```
|
||||
|
||||
The engine detects the aggregate and automatically wraps the join in a subquery.
|
||||
|
||||
## Engine Internals
|
||||
|
||||
### Relationship resolution pipeline
|
||||
|
||||
When the query planner encounters a column reference like `orders.customer.first_name`:
|
||||
|
||||
1. **`ExpandWrenViewRule`** runs first to inline any view definitions
|
||||
2. **`ModelAnalyzeRule`** identifies the `customer` column as a relationship column pointing to `orders_customers`
|
||||
3. **`relation_chain`** resolves the join path, building a `LEFT JOIN customers ON orders.customer_id = customers.customer_id`
|
||||
4. The join is pushed only as far as the referenced columns require — unreferenced relationship columns do not produce joins
|
||||
|
||||
### `TO_MANY` and aggregate subqueries
|
||||
|
||||
The `primary_key` of the base model is required when the relationship is `TO_MANY`. The engine wraps the join in an aggregate subquery keyed on the primary key to prevent row multiplication:
|
||||
|
||||
```sql
|
||||
-- expression: count(orders.order_id) on customers model
|
||||
SELECT
|
||||
customers.customer_id,
|
||||
(SELECT count(orders.order_id)
|
||||
FROM orders
|
||||
WHERE orders.customer_id = customers.customer_id) AS order_count
|
||||
FROM customers
|
||||
```
|
||||
|
||||
If `primary_key` is not declared on the base model, the engine returns an error when a `TO_MANY` calculated column is used.
|
||||
@@ -1,179 +0,0 @@
|
||||
# View
|
||||
|
||||
A **View** is a named SQL query stored in the MDL. It behaves like a virtual table — clients can query it by name, and the engine inlines the `statement` SQL before execution. Unlike a Model, a View does not declare columns explicitly; its schema is inferred from the `statement` at query time.
|
||||
|
||||
## Structure
|
||||
|
||||
Each view lives in its own directory under `views/` as `views/<name>/metadata.yml`.
|
||||
|
||||
The `statement` SQL can be inline in `metadata.yml` or in a separate `sql.yml` file. The `sql.yml` file takes precedence if both exist.
|
||||
|
||||
**Inline statement:**
|
||||
|
||||
```yaml
|
||||
# views/top_customers/metadata.yml
|
||||
name: top_customers
|
||||
statement: >
|
||||
SELECT customer_id, SUM(total) AS lifetime_value
|
||||
FROM wren.public.orders GROUP BY 1 ORDER BY 2 DESC LIMIT 100
|
||||
properties:
|
||||
description: "Top customers by lifetime value"
|
||||
```
|
||||
|
||||
**Separate SQL file:**
|
||||
|
||||
```yaml
|
||||
# views/monthly_revenue/metadata.yml
|
||||
name: monthly_revenue
|
||||
properties:
|
||||
description: "Monthly revenue aggregation"
|
||||
```
|
||||
|
||||
```yaml
|
||||
# views/monthly_revenue/sql.yml
|
||||
statement: >
|
||||
SELECT DATE_TRUNC('month', order_date) AS month,
|
||||
SUM(total) AS total_revenue
|
||||
FROM wren.public.orders
|
||||
GROUP BY 1
|
||||
```
|
||||
|
||||
### JSON format (MDL manifest)
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "top_customers",
|
||||
"statement": "SELECT customer_id, SUM(total) AS lifetime_value FROM wren.public.orders GROUP BY 1 ORDER BY 2 DESC LIMIT 100"
|
||||
}
|
||||
```
|
||||
|
||||
## Fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `name` | Yes | Unique identifier used in SQL queries |
|
||||
| `statement` | Yes | A complete SQL SELECT statement; may reference other models or views |
|
||||
| `dialect` | No | SQL dialect of the view's `statement` (e.g. `bigquery`, `postgres`). Currently metadata only — the engine always parses view statements with its generic SQL parser. Requires `schema_version: 3`. See [Dialect Override](./wren_project.md#dialect-override). |
|
||||
| `properties` | No | Arbitrary key-value metadata (use `properties.description` for a human-readable description) |
|
||||
|
||||
## Model vs View
|
||||
|
||||
| | Model | View |
|
||||
|-|-------|------|
|
||||
| Data source | `table_reference` or `ref_sql` | SQL `statement` |
|
||||
| Column declarations | Explicit (with types) | Inferred from `statement` |
|
||||
| Relationship columns | Supported | Not supported |
|
||||
| Calculated columns | Supported | Not supported |
|
||||
| Primary key | Supported | Not applicable |
|
||||
| Access control | Column omission, RLAC/CLAC | Column omission via `statement` |
|
||||
|
||||
Use a **Model** when you need typed columns, relationships, or calculated fields. Use a **View** for pre-built queries — dashboards, saved filters, or cross-model aggregations — that you want to expose as a named table.
|
||||
|
||||
## jaffle_shop Example
|
||||
|
||||
The jaffle_shop workspace ships with an empty `views.yml` (`views: []`), but views become useful once you have mart-layer models in place. Here are representative examples:
|
||||
|
||||
### Simple filter view
|
||||
|
||||
```yaml
|
||||
# views/completed_orders/metadata.yml
|
||||
name: completed_orders
|
||||
statement: >
|
||||
SELECT order_id, customer_id, order_date, amount
|
||||
FROM orders
|
||||
WHERE status = 'completed'
|
||||
properties:
|
||||
description: "Orders with completed status"
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT * FROM completed_orders WHERE amount > 50;
|
||||
```
|
||||
|
||||
### Cross-model aggregation view
|
||||
|
||||
```yaml
|
||||
# views/customer_order_summary/metadata.yml
|
||||
name: customer_order_summary
|
||||
statement: >
|
||||
SELECT
|
||||
c.customer_id,
|
||||
c.first_name,
|
||||
c.last_name,
|
||||
COUNT(o.order_id) AS total_orders,
|
||||
SUM(o.amount) AS lifetime_value
|
||||
FROM customers c
|
||||
JOIN orders o ON c.customer_id = o.customer_id
|
||||
GROUP BY c.customer_id, c.first_name, c.last_name
|
||||
properties:
|
||||
description: "Per-customer order counts and lifetime value"
|
||||
```
|
||||
|
||||
The `statement` references `customers` and `orders` by their model names. The engine resolves them through the normal model pipeline after expanding the view.
|
||||
|
||||
### View referencing another view
|
||||
|
||||
```yaml
|
||||
# views/vip_customers/metadata.yml
|
||||
name: vip_customers
|
||||
statement: >
|
||||
SELECT customer_id, first_name, last_name, lifetime_value
|
||||
FROM customer_order_summary
|
||||
WHERE lifetime_value > 500
|
||||
properties:
|
||||
description: "Customers with lifetime value over 500"
|
||||
```
|
||||
|
||||
Views can reference other views. The engine expands all view references recursively before resolving model references.
|
||||
|
||||
## Querying a View
|
||||
|
||||
Once defined, a view is a first-class table name:
|
||||
|
||||
```sql
|
||||
SELECT * FROM completed_orders;
|
||||
|
||||
SELECT customer_id, total_orders
|
||||
FROM customer_order_summary
|
||||
ORDER BY total_orders DESC
|
||||
LIMIT 10;
|
||||
```
|
||||
|
||||
The view name can be qualified with catalog and schema:
|
||||
|
||||
```sql
|
||||
SELECT * FROM wren.main.completed_orders;
|
||||
```
|
||||
|
||||
## Engine Internals
|
||||
|
||||
### Session registration
|
||||
|
||||
At session initialisation, each view's `statement` is parsed into a DataFusion `LogicalPlan` and wrapped in a `ViewTable`. The `ViewTable` is registered under the view's fully-qualified name (`catalog.schema.name`) in the DataFusion catalog.
|
||||
|
||||
```
|
||||
view.statement → ctx.state().create_logical_plan()
|
||||
→ ViewTable::new(plan, statement)
|
||||
→ ctx.register_table(catalog.schema.name, view_table)
|
||||
```
|
||||
|
||||
### Query-time expansion: `ExpandWrenViewRule`
|
||||
|
||||
`ExpandWrenViewRule` runs as the **first** analyzer pass — before `ModelAnalyzeRule` and all other rules. It performs a bottom-up walk of the logical plan tree. Whenever it encounters a `TableScan` whose name belongs to the MDL and matches a registered view, it replaces the scan node with the view's `LogicalPlan` wrapped in a subquery alias:
|
||||
|
||||
```
|
||||
TableScan("completed_orders")
|
||||
↓ ExpandWrenViewRule
|
||||
Subquery(
|
||||
Filter(status = 'completed', TableScan("orders")),
|
||||
alias = "completed_orders"
|
||||
)
|
||||
```
|
||||
|
||||
After the view is inlined, the remaining `TableScan("orders")` nodes are processed by `ModelAnalyzeRule` in the next pass, which resolves them to physical tables.
|
||||
|
||||
This ordering ensures that a view's `statement` can freely reference other models or views — all references are resolved in subsequent passes after expansion.
|
||||
|
||||
### Recursive view expansion
|
||||
|
||||
If a view references another view, `ExpandWrenViewRule` handles the recursion automatically. The `transform_up_with_subqueries` traversal processes the tree from leaves to root, so inner views are expanded before outer views reference them.
|
||||
@@ -1,449 +0,0 @@
|
||||
# Wren Project
|
||||
|
||||
A Wren project is a directory of YAML files that define a semantic layer (models, relationships, views, and instructions) over a database. It is the unit of authoring, version control, and deployment for MDL (Model Definition Language) definitions.
|
||||
|
||||
Instead of managing a single `mdl.json` by hand, you author each model in its own directory as human-readable YAML. The CLI compiles them into a deployable JSON manifest when needed.
|
||||
|
||||
YAML files use **snake_case** field names for readability. The compiled `target/mdl.json` uses **camelCase**, which is the wire format expected by the engine.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```text
|
||||
my_project/
|
||||
├── wren_project.yml # project metadata
|
||||
├── models/
|
||||
│ ├── orders/
|
||||
│ │ └── metadata.yml # table_reference mode (physical table)
|
||||
│ ├── customers/
|
||||
│ │ └── metadata.yml
|
||||
│ └── revenue_summary/
|
||||
│ ├── metadata.yml # ref_sql mode (SQL-defined model)
|
||||
│ └── ref_sql.sql # SQL in separate file (optional)
|
||||
├── views/
|
||||
│ ├── monthly_revenue/
|
||||
│ │ ├── metadata.yml
|
||||
│ │ └── sql.yml # statement in separate file (optional)
|
||||
│ └── top_customers/
|
||||
│ └── metadata.yml # statement inline
|
||||
├── relationships.yml # all relationships
|
||||
├── instructions.md # user instructions for LLM (optional)
|
||||
├── .wren/ # runtime state (gitignored)
|
||||
│ └── memory/ # LanceDB index files
|
||||
└── target/
|
||||
└── mdl.json # build output (gitignored)
|
||||
```
|
||||
|
||||
Each model and view lives in its own subdirectory under `models/` and `views/` respectively.
|
||||
|
||||
---
|
||||
|
||||
## What Lives Where
|
||||
|
||||
A Wren project keeps schema artifacts together in the project directory. Global configuration lives separately in `~/.wren/`.
|
||||
|
||||
| Artifact | Location | Scope |
|
||||
|----------|----------|-------|
|
||||
| Models, views, relationships | `<project>/models/`, `<project>/views/`, `<project>/relationships.yml` | Project — version controlled |
|
||||
| Instructions | `<project>/instructions.md` | Project — references this project's model/column names |
|
||||
| Compiled MDL | `<project>/target/mdl.json` | Project — derived from YAML, gitignored |
|
||||
| Memory (LanceDB) | `<project>/.wren/memory/` | Project — indexes this project's schema, gitignored |
|
||||
| Profiles (connections) | `~/.wren/profiles.yml` | Global — environment-specific (dev/prod credentials) |
|
||||
| Global config | `~/.wren/config.yml` | Global — CLI preferences |
|
||||
|
||||
**Why this separation?** Schema definitions are project-specific — they describe a particular data model. Connection credentials are environment-specific — the same project connects to different databases in dev vs. prod. Keeping them separate means projects are portable and safe to commit without leaking secrets.
|
||||
|
||||
---
|
||||
|
||||
## Project Discovery
|
||||
|
||||
When you run a wren command that needs the project (query, memory fetch, etc.), the CLI resolves the project root in this order:
|
||||
|
||||
1. `--path` flag (explicit)
|
||||
2. `WREN_PROJECT_HOME` environment variable
|
||||
3. Walk up from the current directory looking for `wren_project.yml`
|
||||
4. `default_project` in `~/.wren/config.yml`
|
||||
|
||||
If no project is found, the CLI exits with an error and suggests running `wren context init` or setting `WREN_PROJECT_HOME`.
|
||||
|
||||
Once the project root is resolved, all paths (MDL, instructions, memory) are determined relative to it.
|
||||
|
||||
For running wren commands outside the project directory:
|
||||
|
||||
```bash
|
||||
# option A: environment variable
|
||||
export WREN_PROJECT_HOME=~/projects/sales
|
||||
wren --sql "SELECT ..."
|
||||
|
||||
# option B: global config (~/.wren/config.yml)
|
||||
default_project: ~/projects/sales
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Project Files
|
||||
|
||||
### `wren_project.yml`
|
||||
|
||||
```yaml
|
||||
schema_version: 3
|
||||
name: my_project
|
||||
version: "1.0"
|
||||
catalog: wren
|
||||
schema: public
|
||||
data_source: postgres
|
||||
```
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `schema_version` | Directory layout version. `2` = folder-per-entity, `3` = adds `dialect` field support (current). Owned by the CLI — do not bump manually. |
|
||||
| `name` | Project name |
|
||||
| `version` | User's own project version (free-form, no effect on parsing) |
|
||||
| `catalog` | **Wren AI namespace** — NOT your database catalog. Identifies this MDL project within the engine. Default: `wren`. |
|
||||
| `schema` | **Wren AI namespace** — NOT your database schema. Default: `public`. |
|
||||
| `data_source` | Data source type (e.g. `postgres`, `bigquery`, `snowflake`) |
|
||||
|
||||
> **`catalog` / `schema` are NOT database settings.**
|
||||
>
|
||||
> These two fields define the Wren AI's internal namespace for addressing models in SQL. They exist to support future multi-project querying. For single-project use, keep the defaults (`catalog: wren`, `schema: public`).
|
||||
>
|
||||
> Your database's actual catalog and schema are specified per-model in the `table_reference` section of each model's `metadata.yml`.
|
||||
|
||||
#### Two levels of catalog/schema
|
||||
|
||||
The same field names appear in two places with completely different meanings:
|
||||
|
||||
| Location | Refers to | Example | When to change |
|
||||
|----------|-----------|---------|----------------|
|
||||
| `wren_project.yml` → `catalog`, `schema` | Wren AI namespace | `wren`, `public` | Only for multi-project setups |
|
||||
| `models/*/metadata.yml` → `table_reference.catalog`, `table_reference.schema` | Database location | `""`, `main` | Must match your actual database |
|
||||
|
||||
### Model (`models/<name>/metadata.yml`)
|
||||
|
||||
A model must define its source in exactly one of two ways:
|
||||
|
||||
**table_reference** — maps to a physical table:
|
||||
|
||||
```yaml
|
||||
name: orders
|
||||
table_reference:
|
||||
catalog: ""
|
||||
schema: public
|
||||
table: orders
|
||||
columns:
|
||||
- name: order_id
|
||||
type: INTEGER
|
||||
is_calculated: false
|
||||
not_null: true
|
||||
is_primary_key: true
|
||||
properties: {}
|
||||
- name: total
|
||||
type: DECIMAL
|
||||
is_calculated: false
|
||||
not_null: false
|
||||
properties: {}
|
||||
primary_key: order_id
|
||||
cached: false
|
||||
properties: {}
|
||||
```
|
||||
|
||||
**`dialect`** — optional field declaring which SQL dialect the model's `ref_sql` is written in. When omitted, the project-level `data_source` is used. This lets a single project contain models whose SQL targets different databases:
|
||||
|
||||
```yaml
|
||||
name: revenue
|
||||
ref_sql: "SELECT * FROM `project.dataset.table`"
|
||||
dialect: bigquery
|
||||
columns:
|
||||
- name: amount
|
||||
type: DECIMAL
|
||||
```
|
||||
|
||||
Requires `schema_version: 3`. See [Dialect Override](#dialect-override) for details.
|
||||
|
||||
**ref_sql** — defines the model via a SQL query. SQL can be inline in `metadata.yml` or in a separate `ref_sql.sql` file (the `.sql` file takes precedence if both exist):
|
||||
|
||||
```yaml
|
||||
name: revenue_summary
|
||||
columns:
|
||||
- name: month
|
||||
type: DATE
|
||||
is_calculated: false
|
||||
not_null: true
|
||||
properties: {}
|
||||
- name: total_revenue
|
||||
type: DECIMAL
|
||||
is_calculated: false
|
||||
not_null: false
|
||||
properties: {}
|
||||
```
|
||||
|
||||
```sql
|
||||
-- models/revenue_summary/ref_sql.sql
|
||||
SELECT DATE_TRUNC('month', order_date) AS month,
|
||||
SUM(total) AS total_revenue
|
||||
FROM orders
|
||||
GROUP BY 1
|
||||
```
|
||||
|
||||
Using both `table_reference` and `ref_sql` in the same model is a validation error.
|
||||
|
||||
### View (`views/<name>/metadata.yml`)
|
||||
|
||||
Views have a `statement` field. Like ref_sql models, the SQL can be inline in `metadata.yml` or in a separate `sql.yml` file (the `sql.yml` takes precedence if both exist):
|
||||
|
||||
```yaml
|
||||
name: top_customers
|
||||
statement: >
|
||||
SELECT customer_id, SUM(total) AS lifetime_value
|
||||
FROM wren.public.orders GROUP BY 1 ORDER BY 2 DESC LIMIT 100
|
||||
properties:
|
||||
description: "Top customers by lifetime value"
|
||||
```
|
||||
|
||||
Like models, views support an optional **`dialect`** field (requires `schema_version: 3`):
|
||||
|
||||
```yaml
|
||||
name: monthly_summary
|
||||
statement: "SELECT date_trunc('month', created_at) FROM orders"
|
||||
dialect: postgres
|
||||
```
|
||||
|
||||
When set, the dialect is stored as metadata for downstream consumers. It does not currently affect how the engine parses the view's statement — view statements are always normalized into a logical plan via DataFusion's generic SQL parser. See [Dialect Override](#dialect-override) for details.
|
||||
|
||||
### `relationships.yml`
|
||||
|
||||
```yaml
|
||||
relationships:
|
||||
- name: orders_customers
|
||||
models:
|
||||
- orders
|
||||
- customers
|
||||
join_type: MANY_TO_ONE
|
||||
condition: orders.customer_id = customers.customer_id
|
||||
```
|
||||
|
||||
### `instructions.md`
|
||||
|
||||
Free-form Markdown with rules and guidelines for LLM-based query generation. Organize by topic with `##` headings:
|
||||
|
||||
```markdown
|
||||
## Business rules
|
||||
- Revenue queries must use net_revenue, not gross_revenue
|
||||
- All queries must filter status = 'completed'
|
||||
|
||||
## Formatting
|
||||
- Currency is TWD, display with thousand separators
|
||||
- Timestamps are UTC+8
|
||||
```
|
||||
|
||||
Instructions are consumed by agents, not by the engine. They are intentionally excluded from `target/mdl.json` — the wren-core rewrite pipeline has no use for them. Agents access instructions through two paths:
|
||||
|
||||
- `wren context instructions` — returns full text, run once at session start to capture global constraints
|
||||
- `wren memory fetch -q "..."` — returns relevant instruction chunks alongside schema context per query
|
||||
|
||||
---
|
||||
|
||||
## Lifecycle
|
||||
|
||||
```text
|
||||
wren context init → scaffold project in current directory
|
||||
(edit models/, relationships.yml, instructions.md)
|
||||
wren context validate → check YAML structure (no DB needed)
|
||||
wren context build → compile to target/mdl.json
|
||||
wren context upgrade → upgrade project to latest schema_version
|
||||
wren profile add my-pg ... → save connection to ~/.wren/profiles.yml
|
||||
wren memory index → index schema + instructions into .wren/memory/
|
||||
wren --sql "SELECT 1" → verify connection
|
||||
wren --sql "SELECT ..." → start querying
|
||||
```
|
||||
|
||||
After editing models, rebuild and re-index:
|
||||
|
||||
```text
|
||||
wren context build
|
||||
wren memory index
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Migrating from MDL JSON
|
||||
|
||||
If you already have an `mdl.json` (from an earlier Wren setup or an AI agent that generated one), use `--from-mdl` to convert it into a v2 YAML project in one step:
|
||||
|
||||
```bash
|
||||
wren context init --from-mdl /path/to/mdl.json --path my_project
|
||||
```
|
||||
|
||||
This reads the camelCase JSON, converts all fields to snake_case YAML, and writes out the full project structure:
|
||||
|
||||
```text
|
||||
my_project/
|
||||
├── wren_project.yml # catalog, schema, data_source from the manifest
|
||||
├── models/
|
||||
│ ├── orders/
|
||||
│ │ └── metadata.yml # one directory per model
|
||||
│ └── customers/
|
||||
│ └── metadata.yml
|
||||
├── views/
|
||||
│ └── top_customers/
|
||||
│ └── metadata.yml # one directory per view
|
||||
├── relationships.yml
|
||||
└── instructions.md
|
||||
```
|
||||
|
||||
After import, validate and build:
|
||||
|
||||
```bash
|
||||
wren context validate --path my_project
|
||||
wren context build --path my_project
|
||||
```
|
||||
|
||||
If the target directory already contains project files, add `--force` to overwrite:
|
||||
|
||||
```bash
|
||||
wren context init --from-mdl mdl.json --path my_project --force
|
||||
```
|
||||
|
||||
> **When to use this:** You have an existing `mdl.json` that was authored by hand or generated by an older workflow, and you want to adopt the YAML project format for version control and CLI-driven workflows.
|
||||
>
|
||||
> The import is `layoutVersion`-aware: manifests with `layoutVersion: 2` produce a `schema_version: 3` project with `dialect` fields preserved. Manifests without `layoutVersion` (or `layoutVersion: 1`) produce a `schema_version: 2` project.
|
||||
|
||||
---
|
||||
|
||||
## Upgrading an Existing Project
|
||||
|
||||
When new features are added to the project format (e.g. the `dialect` field in schema_version 3), use `wren context upgrade` to bring your project up to date:
|
||||
|
||||
```bash
|
||||
wren context upgrade --path my_project
|
||||
```
|
||||
|
||||
This upgrades to the latest `schema_version`. The command handles all intermediate steps automatically — for example, upgrading from v1 to v3 applies v1→v2 (restructure flat files into directories) then v2→v3 (enable dialect support).
|
||||
|
||||
### What each upgrade does
|
||||
|
||||
| Upgrade | File changes |
|
||||
|---------|-------------|
|
||||
| v1 → v2 | `models/*.yml` flat files → `models/<name>/metadata.yml` directories; `ref_sql` extracted to `ref_sql.sql`; `views.yml` → `views/<name>/metadata.yml` directories; old files deleted |
|
||||
| v2 → v3 | No file layout changes — only bumps `schema_version` in `wren_project.yml` to enable `dialect` field support |
|
||||
|
||||
### Options
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--to N` | Upgrade to a specific schema_version instead of the latest |
|
||||
| `--dry-run` | Preview what files would be created, deleted, or modified — without writing anything |
|
||||
|
||||
### Preview before upgrading
|
||||
|
||||
```bash
|
||||
wren context upgrade --path my_project --dry-run
|
||||
```
|
||||
|
||||
```text
|
||||
Dry run — no files will be changed.
|
||||
|
||||
Would create:
|
||||
models/orders/metadata.yml
|
||||
models/orders/ref_sql.sql
|
||||
views/summary/metadata.yml
|
||||
|
||||
Would delete:
|
||||
models/orders.yml
|
||||
views.yml
|
||||
|
||||
Would modify:
|
||||
wren_project.yml (schema_version 1 -> 3)
|
||||
```
|
||||
|
||||
### After upgrading
|
||||
|
||||
```bash
|
||||
wren context validate --path my_project
|
||||
wren context build --path my_project
|
||||
```
|
||||
|
||||
> **When to use this:** Your project was created with an older CLI version and you want to use new features (like per-model `dialect`). If your project is already at the latest schema_version, the command exits with a "nothing to do" message.
|
||||
|
||||
---
|
||||
|
||||
## Field Mapping
|
||||
|
||||
The `build` step converts all YAML keys from snake_case to camelCase:
|
||||
|
||||
| YAML | JSON |
|
||||
|------|------|
|
||||
| `table_reference` | `tableReference` |
|
||||
| `ref_sql` | `refSql` |
|
||||
| `is_calculated` | `isCalculated` |
|
||||
| `not_null` | `notNull` |
|
||||
| `is_primary_key` | `isPrimaryKey` |
|
||||
| `primary_key` | `primaryKey` |
|
||||
| `join_type` | `joinType` |
|
||||
| `data_source` | `dataSource` |
|
||||
| `layout_version` | `layoutVersion` |
|
||||
| `refresh_time` | `refreshTime` |
|
||||
| `base_object` | `baseObject` |
|
||||
|
||||
Generic rule: split on `_`, capitalize each word after the first, join. All other fields (`name`, `type`, `catalog`, `schema`, `table`, `condition`, `models`, `columns`, `cached`, `dialect`, `properties`) are identical in both formats.
|
||||
|
||||
The `layoutVersion` field is stamped automatically by `wren context build` based on the project's `schema_version`. You do not set it manually in YAML.
|
||||
|
||||
---
|
||||
|
||||
## Dialect Override
|
||||
|
||||
Models and views support an optional `dialect` field that declares which SQL dialect their embedded SQL is written in. This requires `schema_version: 3`.
|
||||
|
||||
### Semantics
|
||||
|
||||
- **`dialect` omitted (or `null`)** — falls back to the project-level `data_source`. This is the default and matches the behavior of all existing projects.
|
||||
- **`dialect` set** — the embedded SQL is written in the specified dialect, which may differ from the project's `data_source`.
|
||||
|
||||
### Model dialect
|
||||
|
||||
When a model has `dialect: bigquery` but the project's `data_source` is `postgres`, the engine knows the model's `ref_sql` contains BigQuery-flavored SQL (e.g. backtick-quoted identifiers, BigQuery functions). The engine uses this to select the correct SQL parser for the ref_sql.
|
||||
|
||||
```yaml
|
||||
# models/revenue/metadata.yml
|
||||
name: revenue
|
||||
ref_sql: "SELECT * FROM `my-project.dataset.table`"
|
||||
dialect: bigquery
|
||||
columns:
|
||||
- name: amount
|
||||
type: DECIMAL
|
||||
```
|
||||
|
||||
### View dialect
|
||||
|
||||
For views, the `dialect` field is currently **metadata only**. The engine normalizes view statements into a logical plan using DataFusion's generic SQL parser regardless of the dialect setting. The field is still valuable because:
|
||||
|
||||
- It documents the author's intent (which dialect the SQL was written in).
|
||||
- Downstream consumers (ibis-server, agent clients) can use it for dialect-aware processing.
|
||||
- When dialect-aware view parsing is added in the future, the field will already be in place.
|
||||
|
||||
### Valid dialect values
|
||||
|
||||
`athena`, `bigquery`, `canner`, `clickhouse`, `databricks`, `datafusion`, `doris`, `duckdb`, `gcs_file`, `local_file`, `minio_file`, `mssql`, `mysql`, `oracle`, `postgres`, `redshift`, `s3_file`, `snowflake`, `spark`, `trino`
|
||||
|
||||
### Version requirements
|
||||
|
||||
The `dialect` field requires `schema_version: 3` in `wren_project.yml`. Using `dialect` in a `schema_version: 2` project produces a validation warning. The `schema_version` also controls the `layoutVersion` stamped in the compiled `target/mdl.json`:
|
||||
|
||||
| `schema_version` | `layoutVersion` | Capabilities |
|
||||
|-------------------|-----------------|--------------|
|
||||
| 1 | 1 | Legacy flat-file project format |
|
||||
| 2 | 1 | Folder-per-entity project format |
|
||||
| 3 | 2 | `dialect` field on models and views |
|
||||
|
||||
---
|
||||
|
||||
## .gitignore
|
||||
|
||||
```text
|
||||
target/
|
||||
.wren/
|
||||
```
|
||||
|
||||
Source YAML and `instructions.md` are committed. Build output (`target/`) is always gitignored — it is derived from source YAML and can be regenerated with `wren context build`.
|
||||
|
||||
`.wren/memory/` contains both schema indexes (derived, rebuildable) and query history (NL-SQL pairs confirmed by users, not rebuildable). If your team wants to share confirmed query history as few-shot examples across members, you can commit `.wren/memory/` — but be aware that LanceDB files are binary and may produce merge conflicts when multiple people index or store concurrently.
|
||||
@@ -1,224 +0,0 @@
|
||||
# Profiles
|
||||
|
||||
A **profile** is a named database connection configuration stored in `~/.wren/profiles.yml`. Profiles work like dbt profiles — they separate connection credentials from project definitions so the same MDL project can connect to different databases in dev, staging, and production.
|
||||
|
||||
## Why profiles
|
||||
|
||||
Without profiles, every `wren` command needs explicit connection flags:
|
||||
|
||||
```bash
|
||||
wren --sql "SELECT 1" --connection-info '{"datasource":"postgres","host":"localhost","port":5432,...}'
|
||||
```
|
||||
|
||||
With profiles, you configure the connection once and every command uses it automatically:
|
||||
|
||||
```bash
|
||||
wren profile add my-db --ui
|
||||
wren --sql "SELECT 1"
|
||||
```
|
||||
|
||||
Profiles also keep credentials out of shell history and command-line arguments.
|
||||
|
||||
## How profiles work
|
||||
|
||||
Profiles are stored in `~/.wren/profiles.yml` with `0600` permissions (readable only by the owner). The file structure:
|
||||
|
||||
```yaml
|
||||
active: my-db
|
||||
profiles:
|
||||
my-db:
|
||||
datasource: postgres
|
||||
host: localhost
|
||||
port: 5432
|
||||
database: analytics
|
||||
user: analyst
|
||||
password: secret
|
||||
prod:
|
||||
datasource: bigquery
|
||||
project_id: my-gcp-project
|
||||
dataset_id: production
|
||||
credentials: <base64-encoded service account key>
|
||||
```
|
||||
|
||||
Only one profile can be **active** at a time. All `wren` commands use the active profile unless overridden with explicit flags.
|
||||
|
||||
### Resolution order
|
||||
|
||||
When you run a `wren` command, the CLI resolves connection info in this order:
|
||||
|
||||
1. **Explicit flags** — `--connection-info` or `--connection-file` (highest priority)
|
||||
2. **Active profile** — from `~/.wren/profiles.yml`
|
||||
3. **Legacy fallback** — `~/.wren/connection_info.json` (for backward compatibility)
|
||||
|
||||
If none are found, the command fails with a connection error.
|
||||
|
||||
## Creating a profile
|
||||
|
||||
### Option A: Browser UI (recommended)
|
||||
|
||||
```bash
|
||||
wren profile add my-db --ui
|
||||
```
|
||||
|
||||
Opens a browser form with data-source-specific fields. Select the data source type, fill in the fields, and submit. Requires the `ui` extra:
|
||||
|
||||
```bash
|
||||
pip install "wren-engine[main]" # includes ui + interactive (add 'memory' separately if needed)
|
||||
```
|
||||
|
||||
### Option B: Interactive CLI
|
||||
|
||||
```bash
|
||||
wren profile add my-db --interactive
|
||||
```
|
||||
|
||||
Walks through prompts for data source type and all required fields. Sensitive fields (passwords, tokens) are hidden during input.
|
||||
|
||||
### Option C: From file
|
||||
|
||||
Import from an existing JSON or YAML connection file:
|
||||
|
||||
```bash
|
||||
wren profile add my-db --from-file connection.json
|
||||
```
|
||||
|
||||
Both flat and envelope formats are accepted:
|
||||
|
||||
```json
|
||||
// Flat format
|
||||
{"datasource": "postgres", "host": "localhost", "port": 5432, "database": "mydb", "user": "root", "password": "secret"}
|
||||
|
||||
// Envelope format (auto-unwrapped)
|
||||
{"datasource": "duckdb", "properties": {"url": "/data", "format": "duckdb"}}
|
||||
```
|
||||
|
||||
### Option D: Minimal (datasource only)
|
||||
|
||||
```bash
|
||||
wren profile add my-db --datasource postgres
|
||||
```
|
||||
|
||||
Creates a profile with only the datasource field. Edit `~/.wren/profiles.yml` manually to add connection fields.
|
||||
|
||||
## Managing profiles
|
||||
|
||||
```bash
|
||||
wren profile list # list all profiles (* = active)
|
||||
wren profile switch prod # change active profile
|
||||
wren profile debug # show resolved config (secrets masked)
|
||||
wren profile debug prod # debug a specific profile
|
||||
wren profile rm old-db # remove a profile
|
||||
wren profile rm old-db --force # remove without confirmation
|
||||
```
|
||||
|
||||
### Activating on creation
|
||||
|
||||
Add `--activate` to set the profile as active immediately:
|
||||
|
||||
```bash
|
||||
wren profile add prod --from-file prod.json --activate
|
||||
```
|
||||
|
||||
If no profile is active when you add the first one, it becomes active automatically.
|
||||
|
||||
## Supported data sources
|
||||
|
||||
| Data source | Datasource value | Extra to install |
|
||||
|-------------|-----------------|------------------|
|
||||
| PostgreSQL | `postgres` | `wren-engine[postgres]` |
|
||||
| MySQL | `mysql` | `wren-engine[mysql]` |
|
||||
| BigQuery | `bigquery` | `wren-engine[bigquery]` |
|
||||
| Snowflake | `snowflake` | `wren-engine[snowflake]` |
|
||||
| DuckDB | `duckdb` | _(included by default)_ |
|
||||
| ClickHouse | `clickhouse` | `wren-engine[clickhouse]` |
|
||||
| Trino | `trino` | `wren-engine[trino]` |
|
||||
| SQL Server | `mssql` | `wren-engine[mssql]` |
|
||||
| Databricks | `databricks` | `wren-engine[databricks]` |
|
||||
| Redshift | `redshift` | `wren-engine[redshift]` |
|
||||
| Oracle | `oracle` | `wren-engine[oracle]` |
|
||||
| Athena | `athena` | `wren-engine[athena]` |
|
||||
| Apache Spark | `spark` | `wren-engine[spark]` |
|
||||
|
||||
Install the extra for your data source before creating a profile:
|
||||
|
||||
```bash
|
||||
pip install "wren-engine[postgres,main]"
|
||||
```
|
||||
|
||||
## Secrets: `${VAR}` references and `.env` files
|
||||
|
||||
Any profile value can contain `${VAR_NAME}` placeholders that are
|
||||
resolved from the environment at connection time. The stored
|
||||
profile keeps the placeholder, so `profiles.yml` (and `wren profile
|
||||
debug`) never shows a plaintext secret:
|
||||
|
||||
```yaml
|
||||
# ~/.wren/profiles.yml
|
||||
profiles:
|
||||
prod:
|
||||
datasource: postgres
|
||||
host: db.example.com
|
||||
port: '5432'
|
||||
database: wren
|
||||
user: ${POSTGRES_USER}
|
||||
password: ${POSTGRES_PASSWORD}
|
||||
```
|
||||
|
||||
wren looks for values in this order (first match wins; process env
|
||||
wins over any `.env`):
|
||||
|
||||
1. `os.environ` — variables already exported in your shell.
|
||||
2. `$CWD/.env` — the directory you run `wren` from (typical agent
|
||||
workflow drops the file here).
|
||||
3. `<project_root>/.env` — co-located with `wren_project.yml`.
|
||||
4. `~/.wren/.env` — user-global fallback for operators running many
|
||||
projects against the same secret bundle.
|
||||
|
||||
### Rules
|
||||
|
||||
- Names must be **UPPERCASE** (`[A-Z_][A-Z0-9_]*`). Lowercase
|
||||
`${foo}` is treated as a literal string so it doesn't collide with
|
||||
real passwords or URL encodings.
|
||||
- `$$` escapes a literal dollar sign (`a$$b` stores as `a$b`).
|
||||
- Missing vars fail **early** with a clear error referencing the
|
||||
variable name — no cryptic driver-level auth errors.
|
||||
|
||||
### `.env` example
|
||||
|
||||
```bash
|
||||
# .env — add to .gitignore
|
||||
POSTGRES_USER=paul
|
||||
POSTGRES_PASSWORD=s3cr3t
|
||||
```
|
||||
|
||||
### Agents and secrets
|
||||
|
||||
AI coding agents should **never** ask for passwords in chat. See
|
||||
[Installation](../get_started/installation.md) for the recommended
|
||||
agent flow: the agent writes a profile referencing `${POSTGRES_PASSWORD}`
|
||||
and instructs the user to put the actual value in `.env` via their
|
||||
editor.
|
||||
|
||||
## Profile vs project
|
||||
|
||||
Profiles and projects serve different purposes and are stored separately:
|
||||
|
||||
| | Profile | Project |
|
||||
|-|---------|---------|
|
||||
| **What** | Database connection credentials | MDL model definitions |
|
||||
| **Where** | `~/.wren/profiles.yml` | `<project>/wren_project.yml` + `models/` |
|
||||
| **Scope** | Global — shared across all projects | Per-project — version controlled |
|
||||
| **Secrets** | Contains passwords, tokens, keys | No secrets — safe to commit |
|
||||
| **Switching** | `wren profile switch <name>` | `cd <project>` or `--path` flag |
|
||||
|
||||
This separation means:
|
||||
- The same project can connect to dev, staging, or prod by switching profiles
|
||||
- Projects are safe to commit to git without leaking credentials
|
||||
- Credentials are centralized in one file with restricted permissions
|
||||
|
||||
## Security
|
||||
|
||||
- `profiles.yml` is written with `0600` permissions (owner-only read/write)
|
||||
- Writes are atomic (temp file + rename) to prevent corruption
|
||||
- `wren profile debug` masks sensitive fields (`password`, `credentials`, `secret`, `token`)
|
||||
- Credentials never appear in CLI output, shell history (when using profiles), or MDL manifests
|
||||
@@ -0,0 +1,124 @@
|
||||
---
|
||||
sidebar_label: Refine answer quality
|
||||
---
|
||||
|
||||
# Refine answer quality
|
||||
|
||||
Scaffolding gives you a baseline MDL. This recipe is how you close the loop — bring in the business meaning that lives outside the database, store proven examples, and let the agent compound from every confirmed answer.
|
||||
|
||||
## What you'll end up with
|
||||
|
||||
- An `instructions.md` that captures business rules, canonical tables, and team conventions
|
||||
- A memory index over MDL + instructions so agents retrieve relevant context per question
|
||||
- A `queries.yml` of confirmed natural-language-to-SQL pairs, committable to your repo
|
||||
- An agent that gets better at your business each time someone confirms an answer
|
||||
|
||||
## Prerequisite — install the `memory` extra
|
||||
|
||||
The memory layer is an optional extra. It is **not** included in the base CLI. Install it before running any `wren memory ...` command:
|
||||
|
||||
```bash
|
||||
pip install "wren-engine[memory]"
|
||||
```
|
||||
|
||||
Combine with your data source extra as needed:
|
||||
|
||||
```bash
|
||||
pip install "wren-engine[memory,postgres]"
|
||||
pip install "wren-engine[memory,bigquery]"
|
||||
```
|
||||
|
||||
Without the `memory` extra, the memory commands below will not be available.
|
||||
|
||||
## The flow today
|
||||
|
||||
The day-to-day refinement loop runs entirely on the `wren-usage` skill plus a few `wren memory` and `instructions.md` edits. Nothing requires a separate enrichment skill — that is on the roadmap (see [Coming soon](#coming-soon-wren-enrich-context) below).
|
||||
|
||||
### 1. Capture business rules in `instructions.md`
|
||||
|
||||
`instructions.md` is the place to write down the rules that are not visible from the schema:
|
||||
|
||||
```markdown
|
||||
## Business rules
|
||||
- Revenue queries must use `net_revenue`, not `gross_revenue`.
|
||||
- All active-customer queries exclude rows where `is_internal = true`.
|
||||
|
||||
## Canonical tables
|
||||
- Use `customers` for analytics, not `customers_v3` or `loyalty_v3`.
|
||||
|
||||
## Formatting
|
||||
- Currency is USD; display with thousand separators and 2 decimals.
|
||||
- Timestamps are stored in UTC.
|
||||
```
|
||||
|
||||
Organize by topic with `##` headings — each heading and its body becomes a retrievable chunk in memory. Edit by hand, or have your agent propose changes when it spots a recurring confusion.
|
||||
|
||||
### 2. Let `wren-usage` compound from every confirmed answer
|
||||
|
||||
The day-to-day `wren-usage` skill stores confirmed answers automatically:
|
||||
|
||||
```text
|
||||
User asks a question
|
||||
→ wren memory recall (find similar past pairs)
|
||||
→ wren memory fetch (retrieve relevant schema)
|
||||
→ write SQL, dry-plan, execute
|
||||
→ wren memory store (persist the confirmed pair)
|
||||
```
|
||||
|
||||
Each stored pair makes future similar questions faster and more accurate. The loop runs on every turn — no separate enrichment phase needed.
|
||||
|
||||
### 3. Re-index after each change
|
||||
|
||||
Whenever you edit `instructions.md`, MDL, or `queries.yml`, rebuild the memory index so the agent's retrieval reflects the new context:
|
||||
|
||||
```bash
|
||||
wren memory index
|
||||
```
|
||||
|
||||
This re-reads MDL + `instructions.md` + `queries.yml` into the memory store. Targeted retrieval (`wren memory fetch -q "..."`) and recall (`wren memory recall -q "..."`) now see the new context.
|
||||
|
||||
### 4. Export learned context to your repo
|
||||
|
||||
Curate the team's accumulated learning into `queries.yml`:
|
||||
|
||||
```bash
|
||||
wren memory dump --source user -o queries.yml
|
||||
git add queries.yml
|
||||
git commit -m "curate query pairs from this sprint"
|
||||
```
|
||||
|
||||
A new environment picks them up automatically on the next `wren memory index`.
|
||||
|
||||
## When to come back here
|
||||
|
||||
- A user complains the agent picked the wrong table
|
||||
- A new business term shows up (a project name, a metric, a customer segment)
|
||||
- You import a new dataset and need to teach the agent its quirks
|
||||
- You want a teammate's environment to inherit accumulated learning
|
||||
|
||||
## Memory hygiene
|
||||
|
||||
Three commands to keep memory tidy:
|
||||
|
||||
| Command | When |
|
||||
|---|---|
|
||||
| `wren memory list` | Browse stored pairs |
|
||||
| `wren memory forget --id <n> --force` | Remove an incorrect pair |
|
||||
| `wren memory dump --source user` | Export confirmed pairs to `queries.yml` for commit |
|
||||
|
||||
See the [CLI reference](/oss/reference/cli) for the full memory command surface.
|
||||
|
||||
## Coming soon: `wren-enrich-context`
|
||||
|
||||
A dedicated `wren-enrich-context` skill is in **active development**. It will surface two structured modes for going deeper than `instructions.md` edits:
|
||||
|
||||
- **Grill mode** — the agent walks the MDL one piece at a time and asks focused questions ("Which of `customers`, `customers_v3`, `loyalty_v3` is canonical?", "What does `status = 4` mean?"). You answer in plain language; the agent patches MDL, `instructions.md`, `queries.yml`, or memory based on the answer category.
|
||||
- **Auto-pilot mode** — drop docs, glossaries, SQL history, or a metric handbook into `<project>/raw/` and the agent reads them, proposes context changes with evidence, and surfaces a diff for review. Nothing writes to production context without your approval.
|
||||
|
||||
Until that ships, the flow above (manual `instructions.md` edits + `wren-usage` loop + `queries.yml` curation) covers the same ground. Watch the [WrenAI repo](https://github.com/Canner/WrenAI) for updates.
|
||||
|
||||
## See also
|
||||
|
||||
- [How does the agent learn from your context?](/oss/concepts/agent_learning) — the design behind the loop
|
||||
- [How does memory get smarter over time?](/oss/concepts/memory_system) — what's indexed and how recall works
|
||||
- [Model your business](./model.md) — the scaffolding step before you start refining
|
||||
@@ -1,51 +0,0 @@
|
||||
# Use with Claude Code
|
||||
|
||||
Wren AI is designed to work as Claude Code's grounding layer for any database it needs to query. With the Wren skills installed, Claude Code stops guessing about your schema — it discovers tables, looks up canonical models, recalls similar past queries, and generates SQL through the semantic layer.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview) installed and authenticated
|
||||
- A [Wren AI project](/oss/get_started/quickstart) with at least one profile
|
||||
|
||||
## Install the Wren skills
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*'
|
||||
```
|
||||
|
||||
Or via the install script:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/Canner/WrenAI/main/skills/install.sh | bash
|
||||
```
|
||||
|
||||
The CLI auto-detects Claude Code. If you have multiple agents installed and want to target Claude Code specifically:
|
||||
|
||||
```bash
|
||||
npx skills add Canner/WrenAI --skill '*' --agent claude-code
|
||||
```
|
||||
|
||||
## What each skill does
|
||||
|
||||
| Skill | When to use |
|
||||
|-------|------|
|
||||
| `wren-generate-mdl` | One-time setup — explore a new database and write the initial MDL project. |
|
||||
| `wren-usage` | Day-to-day querying — fetch context, recall similar queries, write and execute SQL, store the result for future recall. |
|
||||
| `wren-onboarding` | First-time install — set up the environment, scaffold a project, run a first query. |
|
||||
| `wren-dlt-connector` | Connect a SaaS data source via [dlt](https://dlthub.com/) and scaffold a Wren project from the loaded data. |
|
||||
|
||||
## Typical workflow
|
||||
|
||||
1. **Open Claude Code in your Wren project directory** — `cd ~/my-wren-project && claude`
|
||||
2. **Ask a question in natural language**:
|
||||
|
||||
```text
|
||||
How many customers placed more than one order this month?
|
||||
```
|
||||
|
||||
3. **Claude Code uses `wren-usage`** to fetch context, recall examples, write SQL, execute via `wren --sql "..."`, and store the result.
|
||||
|
||||
## Tips
|
||||
|
||||
- Re-run `wren memory index` after editing `instructions.md` or model descriptions so the new content is searchable.
|
||||
- If Claude Code picks the wrong table, add a `## Canonical tables` section to `instructions.md` and rebuild.
|
||||
+76
-91
@@ -2,151 +2,136 @@
|
||||
|
||||
<iframe src="https://ghbtns.com/github-btn.html?user=Canner&repo=WrenAI&type=star&count=true&size=large" frameborder="0" scrolling="0" height="50" title="Wren AI"></iframe>
|
||||
|
||||
**Wren AI is the open context layer for AI agents.** It lets any agent — coding assistants, internal copilots, customer-facing apps, or your in-house BI surface — query your warehouse through the same governed semantic layer your analysts use.
|
||||
**Wren AI is the open context layer for AI agents.** It sits between your data sources and any agent or application that needs to query them: coding assistants, internal copilots, customer-facing apps, and BI surfaces.
|
||||
|
||||
In practice, Wren AI sits between your data sources and the agent or application that needs to query them. It provides a modeled, governed, and execution-aware layer so agents can reason over business concepts such as customers, revenue, relationships, and reusable calculations.
|
||||
The goal is simple: **one governed semantic layer for every data consumer**. Humans and agents should not rebuild business logic from scratch, argue over which number is right, or bypass governance just because the interface changed.
|
||||
|
||||
## What problem Wren AI solves
|
||||
Wren AI gives them the same machine-readable understanding of your business data: what the data means, how it should be joined, which definitions are approved, and how queries should be planned against the underlying database.
|
||||
|
||||
Your AI agent does not know what your data means. It reads schemas. It catches column names. It even reads your semantic-layer YAML. But it misses the things that actually decide whether an answer is right — that `status = 4` means refunded, that `loyalty_v3` is the table your team actually uses, that "monthly active users" excludes service accounts, that "Project Lighthouse" was renamed to `campaign_id = 4172` six months ago in a doc nobody linked to the warehouse.
|
||||
## Why Wren AI exists
|
||||
|
||||

|
||||
The bottleneck for AI on business data is not intelligence. It is context.
|
||||
|
||||
So it picks the wrong table. It writes confident, plausible, wrong SQL. The demo looks fine. The pilot looks fine. Production is where it breaks.
|
||||
Your agent sees schema. It reads column names, catches types, and may even parse semantic-layer YAML. But it still misses the meaning that decides whether an answer is right:
|
||||
|
||||
**AI agents over business data are bottlenecked on context, not on intelligence.** The missing piece is **context** — a machine-readable description of what the data means and how it should be used. Wren AI is designed to provide that context.
|
||||
- `status = 4` means refunded
|
||||
- `loyalty_v3` is the table your team actually uses
|
||||
- "monthly active users" excludes service accounts
|
||||
- "Project Lighthouse" was renamed to `campaign_id = 4172` in a planning doc nobody linked to the warehouse
|
||||
|
||||
## What Wren AI does
|
||||

|
||||
|
||||
Wren AI combines modeling, context packaging, and query execution foundations in one open system. For an AI agent to answer real business questions on real company data, it needs **five layers of knowledge**:
|
||||
So the agent picks the wrong table. It writes confident, plausible, wrong SQL. The demo looks fine. The pilot looks fine. Production is where it breaks.
|
||||
|
||||

|
||||
Wren AI exists to make that missing context explicit, portable, inspectable, and shared across every agent and app you ship.
|
||||
|
||||
Layers 1–3 ship today. Layers 4–5 are in active development. See [What is context](/oss/concepts/what_is_context) for the full breakdown.
|
||||
## What Wren AI provides
|
||||
|
||||
### 1. Models business context with MDL
|
||||
Wren AI turns raw database structure into a reusable context layer. It helps agents move from "I can see tables" to "I know what this business means by revenue, customer, refund, churn, and active account."
|
||||
|
||||
Wren AI uses [Modeling Definition Language (MDL)](/oss/concepts/what_is_mdl) to describe:
|
||||
For real business questions on real company data, an agent needs five layers of context:
|
||||
|
||||
- models that map to tables or query results
|
||||
- relationships between datasets
|
||||
- calculated fields and reusable logic
|
||||
- views and business-facing abstractions
|
||||
| Layer | What it gives the agent | Status |
|
||||
| --- | --- | --- |
|
||||
| **Structural** | Tables, columns, types, keys, and relationships | Ships today |
|
||||
| **Semantic** | Business-facing models, reusable calculations, canonical tables, enum meaning | Ships today |
|
||||
| **Business** | Company definitions such as active customer, revenue, churn, and internal naming | Ships today |
|
||||
| **Operational** | Approved join paths, sanctioned queries, governance rules, and things never to compute | In active development |
|
||||
| **Behavioral** | Memory of past questions, successful SQL, user feedback, and examples | In active development |
|
||||
|
||||
This turns warehouse structure into a layer that is easier for both humans and AI agents to understand.
|
||||

|
||||
|
||||
### 2. Gives agents structured context, not raw schema alone
|
||||
See [What does Wren AI mean by context?](/oss/concepts/what_is_context) for the full breakdown.
|
||||
|
||||
Wren AI is built around the idea that agents need more than semantics alone. They need [context](/oss/concepts/what_is_context) — trusted definitions, reusable logic, and a consistent way to navigate business data.
|
||||
## What is in the open core
|
||||
|
||||
That context helps agents:
|
||||
The open core includes:
|
||||
|
||||
- choose the right datasets
|
||||
- follow approved join paths
|
||||
- reuse shared calculations
|
||||
- generate more reliable SQL
|
||||
- **[MDL (Modeling Definition Language)](/oss/concepts/what_is_mdl)** - the semantic contract. MDL defines models, relationships, calculated fields, views, and agent-oriented metadata in files you can read, review, version, and fork. See [What does MDL do for the agent?](/oss/concepts/what_is_mdl) for the deeper view.
|
||||
- **Rust semantic engine** - powered by Apache DataFusion. It plans and executes modeled SQL across supported data sources such as PostgreSQL, MySQL, BigQuery, Snowflake, DuckDB, ClickHouse, Trino, SQL Server, Databricks, Redshift, Oracle, Athena, Apache Spark, and more.
|
||||
- **[`wren` CLI](/oss/reference/cli)** - commands for querying, planning, validating, building context, profiling data, and managing memory.
|
||||
- **[Skills](/oss/reference/skills)** - structured workflows such as `wren-generate-mdl` and `wren-onboarding` that let AI coding agents operate Wren AI safely and reproducibly.
|
||||
- **Framework SDKs** - [LangChain](/oss/sdk/langchain) and [Pydantic AI](/oss/sdk/pydantic) integrations for attaching a Wren project to agent frameworks.
|
||||
- **[wren-core-wasm](/oss/sdk/wasm)** - the semantic engine compiled to WebAssembly, so MDL-aware SQL can run in the browser.
|
||||
|
||||
### 3. Connects context to execution
|
||||
## Why open source matters
|
||||
|
||||
Wren AI is not only a metadata layer. It also serves as the execution foundation for modeled queries. Once data is described in MDL, Wren AI can plan and generate queries against supported data sources — the same engine powers both interactive analytics and AI agent workflows that need grounded text-to-SQL behavior.
|
||||
Context cannot be locked inside someone else's product. Your business definitions outlive your tools, and they deserve a format your team can inspect, version, fork, and share.
|
||||
|
||||
### 4. Works with the AI coding agents you already use
|
||||
Agents are everywhere: Claude Code, Cursor, ChatGPT, Aider, LangChain pipelines, Pydantic AI flows, in-house copilots, and customer-facing apps. None of them should have to rediscover your business logic from raw schema every time.
|
||||
|
||||
Wren AI exposes business context in a form that can be shared with agent systems, so agents operate on governed data definitions instead of rediscovering logic from scratch on every request.
|
||||
## Correctness is a system
|
||||
|
||||
## What's in Wren AI
|
||||
It is tempting to treat correctness like a switch: add metadata, add examples, flip it on. That does not work.
|
||||
|
||||
- **CLI (`wren`)** — query, plan, validate, build, profile, and memory commands
|
||||
- **MDL (Modeling Definition Language)** — the semantic contract that powers governed agent access. It captures models, relationships, and reusable logic in a form humans and agents share, with agent-oriented extensions like confidence, intent grain, and governance-as-data.
|
||||
- **Skills** — structured workflows that let any AI coding agent operate the CLI safely
|
||||
Correct answers come from several primitives working together:
|
||||
|
||||
## Key ideas behind the project
|
||||
|
||||
### Open context layer
|
||||
|
||||
Wren AI is an open context layer because its job is to make business context portable, inspectable, and usable by different agentic systems. Instead of locking meaning inside one application, it provides a reusable foundation that other tools and workflows can build on.
|
||||
|
||||
### Business-first modeling
|
||||
|
||||
The project focuses on modeling data the way people ask questions about it, not only the way the warehouse stores it. That makes it easier to define entities, metrics, and relationships in a form that aligns with business usage.
|
||||
|
||||
### Better reliability for AI
|
||||
|
||||
Text-to-SQL systems fail when they guess incorrectly about definitions, joins, or source-of-truth tables. Wren AI improves reliability by making those assumptions explicit in the model.
|
||||
|
||||
### Versionable, maintainable definitions
|
||||
|
||||
Wren AI projects are stored as files, which makes modeling logic easy to review, version, and improve over time. See the [Wren Project](/oss/guides/modeling/wren_project) guide for how MDL projects are organized.
|
||||
|
||||
## Use cases
|
||||
|
||||
Wren AI powers many agent-facing workflows. The flagship reference application is **Wren AI GenBI**, a chat-first BI app, but Wren AI is also used to wire governed warehouse access into chat bots, AI coding agent workflows, internal copilots, customer-facing analytics agents, and downstream BI surfaces that can talk to a SQL endpoint.
|
||||
|
||||
## Correctness is a system, not a switch
|
||||
|
||||
The temptation is to treat correctness like a setting — add a metadata field, add 100 examples, flip a switch. That does not work. Correctness is the result of six pieces working together: schema linking, value profiling, ambiguity detection, generation trace, retry and repair, and eval. Miss any one and the agent fails in that exact gap.
|
||||
- schema linking
|
||||
- value profiling
|
||||
- ambiguity detection
|
||||
- generation trace
|
||||
- retry and repair
|
||||
- eval
|
||||
|
||||

|
||||
|
||||
That is why we build context as a system, not as a feature — and why Wren AI exposes **primitives**, not a closed product. See [Architecture](/oss/concepts/architecture) for the six pillars in detail.
|
||||
If one primitive is missing, the agent fails in that gap. Wren AI exposes these pieces so you can compose the correctness system your business needs instead of trusting a closed black box. See [How does Wren AI keep agents from hallucinating?](/oss/concepts/correctness) for the deeper view.
|
||||
|
||||
## How you actually use it — scaffold fast, enrich deep
|
||||
## How you use it
|
||||
|
||||
A context layer fails if the on-ramp is painful. Wren AI works in two beats:
|
||||
Wren AI does not replace your warehouse, your transformation pipeline, or your existing semantic layer. It sits between your data infrastructure and the agents querying it — one inspectable layer that gives every agent the same governed surface. See [Where does Wren AI sit in my stack?](/oss/concepts/stack_position) for the layering map.
|
||||
|
||||

|
||||
A context layer fails if the on-ramp is painful. Wren AI is designed to work in two beats: **scaffold fast, then enrich deep**.
|
||||
|
||||
**Scaffold first.** Connect a database; scaffold a Wren project. The `wren-generate-mdl` skill drives an agent through your schema, normalizes types, and writes an initial MDL covering structure — tables, columns, relationships. The agent can already query through it.
|
||||
**First, scaffold.** Connect a database and create a Wren project. The `wren-generate-mdl` skill guides an agent through schema discovery, type normalization, relationship detection, and initial MDL generation. At this point, the agent can already query through the modeled layer.
|
||||
|
||||
**Then enrich.** Structure isn't enough. The hard meaning — what `status = 4` really means, which table is canonical, what counts as "active", how internal project codenames map to data rows — lives outside `INFORMATION_SCHEMA`. The `wren-enrich-context` skill (in active development) covers this in two modes:
|
||||
**Then, enrich.** Structure is only the start. The hard meaning lives in docs, decks, Slack threads, SQL history, and tribal memory. Wren AI stores that context in MDL, `instructions.md`, `queries.yml`, and [memory](/oss/concepts/memory_system) so it stays reviewable and versionable.
|
||||
|
||||
- **Grill mode** — one question at a time, you in the loop. High precision; you stay in control.
|
||||
- **Auto-pilot mode** — drop PDFs, glossaries, handbooks, code, and NL→SQL pairs in `<project>/raw/`. The agent reads everything, proposes changes, and escalates only on conflicts.
|
||||
The `wren-enrich-context` workflow is in active development and is designed around two modes:
|
||||
|
||||
Both modes write to the same places: MDL, `instructions.md`, `queries.yml`, memory. Reviewable, versionable, Git-friendly.
|
||||
- **Grill mode** - the agent asks one question at a time, and you stay in control.
|
||||
- **Auto-pilot mode** - you drop PDFs, glossaries, handbooks, code, and natural-language-to-SQL pairs into `<project>/raw/`; the agent proposes context changes and escalates real conflicts.
|
||||
|
||||
See [How does the agent learn from your context?](/oss/concepts/agent_learning) for the full learning loop.
|
||||
|
||||
## Where this is going
|
||||
|
||||
The next twelve months focus on three pillars:
|
||||
The next arc of Wren AI focuses on three pillars:
|
||||
|
||||
1. **Context enrichment, end to end** — `wren-enrich-context` brings grill and auto-pilot into a single skill across MDL, instructions, queries, and memory.
|
||||
2. **An end-to-end correctness system** — built as primitives the agent orchestrates: rich schema retrieval, dry-plan validation, structured error responses, value profiling, a small golden NL-SQL eval runner. No black-box dashboard, no "trust us, it's accurate" claim.
|
||||
3. **Agent-native distribution** — first-class SDKs for the agent frameworks where engineers already work. **LangChain** and **Pydantic AI** are supported today; other frameworks (LangGraph, Claude, Codex, and more) are on the roadmap.
|
||||
|
||||
See the [Wren AI vision paper](https://getwren.ai/post/fueling-the-next-wave-of-ai-agents-building-the-foundation-for-future-mcp-clients-and-enterprise-data-access) for the full story.
|
||||
|
||||
## Open and yours
|
||||
|
||||
Wren AI is Apache 2.0. Self-hosted is a first-class deployment, not a teaser. We build this in the open because the context layer for AI must be inspectable, composable, and community-owned — your MDL is too important to live inside someone else's product.
|
||||
|
||||
## Start here
|
||||
|
||||
If you are new, follow this path:
|
||||
|
||||
1. [Install Wren AI](/oss/get_started/installation) — agent-driven
|
||||
2. [Quickstart with sample data](/oss/get_started/quickstart) — try the CLI on the bundled `jaffle_shop` demo
|
||||
3. [Connect your own database](/oss/guides/connect)
|
||||
4. [Learn the concepts](/oss/concepts/what_is_context) — context, MDL, skills, memory, architecture
|
||||
1. **Context enrichment, end to end** - bring structural, semantic, business, operational, and behavioral context into one agent-driven workflow.
|
||||
2. **An end-to-end correctness system** - rich schema retrieval, dry-plan validation, structured errors, value profiling, retry and repair, and small golden evals that agents can run.
|
||||
3. **Agent-native distribution** - first-class SDKs and workflows for the frameworks where engineers already build agents.
|
||||
|
||||
## When to use Wren AI
|
||||
|
||||
Wren AI is especially useful when you want to:
|
||||
Reach for Wren AI when you want to:
|
||||
|
||||
- build an AI agent workflow on top of business data
|
||||
- create a reusable business layer across analytics tools
|
||||
- improve text-to-SQL reliability with explicit modeling
|
||||
- separate business logic from raw warehouse structure
|
||||
- keep modeling definitions under version control
|
||||
- give humans, agents, dashboards, and apps the same trusted answer
|
||||
|
||||
## Start here
|
||||
|
||||
If you are new to Wren AI, follow this path:
|
||||
|
||||
1. [Install Wren AI](/oss/get_started/installation)
|
||||
2. [Quickstart with sample data](/oss/get_started/quickstart)
|
||||
3. [Connect your own database](/oss/guides/connect)
|
||||
4. [Learn the concepts](/oss/concepts/what_is_context)
|
||||
5. [Model your business](/oss/guides/model)
|
||||
|
||||
## Looking for the GenBI app docs?
|
||||
|
||||
The **Wren AI GenBI** app (the Docker-based chat-first BI product) is now in **sunset** — its code lives on a `legacy` branch and no security fixes will be issued. Existing deployments still work, and reference docs are kept under [Wren AI GenBI · Sunset](/oss/overview/introduction) in the sidebar.
|
||||
The **Wren AI GenBI** app, the Docker-based chat-first BI product, is now in **sunset**. Its code lives on the `legacy/v1` branch and no security fixes will be issued. Existing deployments still work, and reference docs are kept under [Wren AI GenBI - Sunset](/oss/overview/introduction) in the sidebar.
|
||||
|
||||
For an actively maintained version with the same feature set, see [Upgrade to Commercial Plans](/oss/genbi/upgrade-to-commercial) (Wren AI Cloud or Self-hosted Commercial).
|
||||
For an actively maintained version with the same feature set, see [Wren AI Commercial](https://getwren.ai).
|
||||
|
||||
## Learn more
|
||||
|
||||
- Browse the [CLI reference](/oss/reference/cli)
|
||||
- Explore the [modeling guides](/oss/guides/modeling/overview)
|
||||
- Learn how the [memory layer](/oss/guides/memory) enables self-learning
|
||||
- Explore the [MDL schema reference](/oss/reference/mdl)
|
||||
- Learn how to [refine answer quality](/oss/guides/refine) with memory and instructions
|
||||
- Read the original announcement: [Fueling the Next Wave of AI Agents](https://getwren.ai/post/fueling-the-next-wave-of-ai-agents-building-the-foundation-for-future-mcp-clients-and-enterprise-data-access)
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
# Architecture
|
||||
|
||||
Wren AI is built as an open context layer for agents. Architecturally, that means two things:
|
||||
|
||||
1. Business meaning is stored in explicit project artifacts: MDL, instructions, profiles, and memory.
|
||||
2. Correctness is handled as a system of primitives the agent can orchestrate, not as one hidden feature.
|
||||
|
||||
The result is a stack where agents can query through governed business context while Wren AI handles modeling, planning, validation, execution, and recall.
|
||||
|
||||
## Correctness is a system
|
||||
|
||||
Text-to-SQL does not become reliable because one metadata field is present or one prompt is clever. It becomes reliable when several pieces work together.
|
||||
|
||||
| Pillar | What it means | Where it lives in Wren AI |
|
||||
| --- | --- | --- |
|
||||
| **Schema linking** | Knowing which models, columns, and relationships matter for a question. | MDL + memory retrieval (`wren memory fetch`) |
|
||||
| **Value profiling** | Knowing what values actually appear in the data, such as what `status = 4` means. | Connector behavior, profiling workflows, instructions indexed into memory |
|
||||
| **Ambiguity detection** | Knowing when the question is underspecified and needs clarification. | Skill orchestration by the agent |
|
||||
| **Generation trace** | Showing how an answer was constructed: models, joins, CTEs, and expanded SQL. | `wren dry-plan` |
|
||||
| **Retry and repair** | Recovering when generated SQL fails or points at the wrong modeled object. | Structured errors, `wren dry-run`, agent retry workflows |
|
||||
| **Eval** | Detecting regressions when schemas, definitions, or prompts change. | Golden NL-SQL eval workflows in development |
|
||||
|
||||
Wren AI exposes these as primitives. The agent chooses when to fetch, recall, dry-plan, execute, repair, or ask a clarification. The trace stays visible where the agent's reasoning happens.
|
||||
|
||||
## System overview
|
||||
|
||||
At a high level, Wren AI has four layers:
|
||||
|
||||
| Layer | Responsibility |
|
||||
| --- | --- |
|
||||
| **Agent workflow** | Skills guide the agent through onboarding, MDL generation, querying, validation, and memory updates. |
|
||||
| **Project context** | MDL, instructions, profiles, and memory describe what the data means and how it should be used. |
|
||||
| **Planning engine** | Wren AI expands modeled SQL into executable SQL using the semantic engine and SQL planner. |
|
||||
| **Execution layer** | Connectors run the planned SQL against the target data source and return results. |
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
user["User / Agent"] --> skills["Agent skills<br/>onboarding · generate MDL · usage"]
|
||||
skills --> cli["Wren CLI / Python SDK"]
|
||||
|
||||
cli --> project["Project context<br/>MDL · instructions · queries"]
|
||||
cli --> runtime["Runtime context<br/>profile · memory · history"]
|
||||
|
||||
project --> orchestrator["Plan + execute pipeline"]
|
||||
runtime --> orchestrator
|
||||
|
||||
orchestrator --> planner["SQL planner<br/>sqlglot · CTE rewrite · policy"]
|
||||
planner --> core["wren-core<br/>Rust semantic engine"]
|
||||
core --> connectors["Connectors<br/>22+ data sources"]
|
||||
connectors --> data["Data source"]
|
||||
```
|
||||
|
||||
The same architecture can also be read as a query path:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as User / Agent
|
||||
participant S as Skill
|
||||
participant M as Memory
|
||||
participant W as Wren CLI / SDK
|
||||
participant P as SQL planner
|
||||
participant R as wren-core
|
||||
participant D as Data source
|
||||
|
||||
U->>S: Ask a business question
|
||||
S->>M: Recall similar NL-SQL pairs
|
||||
S->>M: Fetch relevant schema
|
||||
S->>W: Submit SQL against MDL
|
||||
W->>P: Load context, plan SQL
|
||||
P->>R: Expand MDL semantics
|
||||
P->>D: Execute via connector
|
||||
D-->>U: Return result
|
||||
S->>M: Store confirmed pair
|
||||
```
|
||||
|
||||
## Core components
|
||||
|
||||
### Agent skills
|
||||
|
||||
[Skills](/oss/reference/skills) are Markdown workflows that tell AI coding agents how to operate Wren AI safely. They encode procedures such as "build MDL before querying," "fetch context before writing SQL," and "store confirmed examples after success."
|
||||
|
||||
Skills sit above the CLI. They do not hide the primitives; they help the agent use them in the right order.
|
||||
|
||||
### Wren CLI
|
||||
|
||||
The CLI is the main interface for agents and developers. It discovers the project, resolves the active profile, and routes commands to the right subsystem.
|
||||
|
||||
| Command | What it does |
|
||||
| --- | --- |
|
||||
| `wren query` / `wren --sql` | Plan and execute SQL, then return results. |
|
||||
| `wren dry-plan` | Plan SQL and show the expanded SQL without executing it. |
|
||||
| `wren dry-run` | Validate SQL against the live database without returning rows. |
|
||||
| `wren context` | Initialize, validate, build, and inspect a Wren project. |
|
||||
| `wren profile` | Manage database connection profiles. |
|
||||
| `wren memory` | Index context, fetch schema items, recall examples, and store confirmed queries. |
|
||||
| `wren utils` | Run helper operations such as type normalization. |
|
||||
|
||||
### Project context
|
||||
|
||||
A Wren project is the portable context package for one business data layer.
|
||||
|
||||
It includes:
|
||||
|
||||
- **MDL source files** - models, relationships, views, cubes, and project metadata.
|
||||
- **`instructions.md`** - business and operational guidance for agents.
|
||||
- **`queries.yml`** - reviewed natural-language-to-SQL examples that can seed memory.
|
||||
- **`target/mdl.json`** - compiled MDL manifest used by the engine.
|
||||
- **`.wren/memory/`** - local LanceDB indexes for schema retrieval and query recall.
|
||||
|
||||
Connection profiles live separately in `~/.wren/profiles.yml` so credentials stay environment-specific.
|
||||
|
||||
See the [MDL schema reference](/oss/reference/mdl) for the full project structure.
|
||||
|
||||
### Wren Python SDK
|
||||
|
||||
The `wren-engine` Python package exposes the same plan-and-execute pipeline that the CLI drives. The CLI is a thin Typer wrapper over the SDK — both share the orchestration code, both can be embedded in agent frameworks, notebooks, and applications.
|
||||
|
||||
When invoked (via CLI or SDK), the orchestrator:
|
||||
|
||||
1. Receives modeled SQL.
|
||||
2. Loads the compiled MDL manifest and active connection profile.
|
||||
3. Calls the SQL planning subsystem (sqlglot + CTE rewrite + wren-core).
|
||||
4. Sends planned SQL to the correct connector.
|
||||
5. Returns results as a PyArrow table.
|
||||
|
||||
For higher-level integrations, see the [LangChain SDK](/oss/sdk/langchain) and [Pydantic AI SDK](/oss/sdk/pydantic) — both wrap this pipeline as agent tools.
|
||||
|
||||
### SQL planning
|
||||
|
||||
The SQL planner transforms SQL written against modeled objects into SQL that the target database can execute.
|
||||
|
||||
Three pieces collaborate:
|
||||
|
||||
- **sqlglot** parses SQL, qualifies table and column references, and transpiles between SQL dialects.
|
||||
- **CTE rewriter** identifies referenced MDL objects and injects expanded model SQL as CTEs.
|
||||
- **wren-core** expands MDL semantics: models, relationships, calculated fields, and views.
|
||||
|
||||
```text
|
||||
User SQL against MDL
|
||||
|
|
||||
|-- parse and qualify SQL
|
||||
|-- identify referenced models/views
|
||||
|-- extract the relevant MDL manifest slice
|
||||
|-- expand models and calculated fields through wren-core
|
||||
|-- inject expanded CTEs
|
||||
|-- run policy checks
|
||||
|-- transpile to the target dialect
|
||||
|
|
||||
v
|
||||
Executable SQL for the connected data source
|
||||
```
|
||||
|
||||
### wren-core
|
||||
|
||||
`wren-core` is the Rust semantic engine. It is exposed to Python through PyO3 bindings and acts as the source of truth for MDL semantics.
|
||||
|
||||
It handles:
|
||||
|
||||
- maintaining MDL state in a session context
|
||||
- extracting only the manifest objects needed for a query
|
||||
- expanding `table_reference` and `ref_sql` models
|
||||
- resolving calculated fields
|
||||
- expanding relationship-aware expressions
|
||||
- enforcing how modeled objects map to SQL
|
||||
|
||||
### Connectors
|
||||
|
||||
Connectors execute planned SQL against the target database. Each connector implements a common interface for query execution, dry-run validation, type handling, and connection lifecycle.
|
||||
|
||||
Supported data sources include PostgreSQL, MySQL, BigQuery, Snowflake, DuckDB, ClickHouse, Trino, SQL Server, Databricks, Redshift, Oracle, Athena, Apache Spark, and more.
|
||||
|
||||
### Memory layer
|
||||
|
||||
The [memory system](/oss/concepts/memory_system) is a LanceDB-backed retrieval layer with two primary collections:
|
||||
|
||||
| Collection | Contents | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `schema_items` | Models, columns, relationships, views, cubes, and instructions | Retrieve the right context for each question. |
|
||||
| `query_history` | Confirmed natural-language-to-SQL pairs | Recall examples that worked before. |
|
||||
|
||||
Memory turns usage into behavioral context. Each confirmed query can become a future example.
|
||||
|
||||
## Data flows
|
||||
|
||||
### Query execution
|
||||
|
||||
```text
|
||||
wren --sql "SELECT customer_id, SUM(total) FROM orders GROUP BY 1"
|
||||
|
|
||||
|-- 1. Discover project: wren_project.yml -> target/mdl.json
|
||||
|-- 2. Resolve profile: ~/.wren/profiles.yml
|
||||
|-- 3. Plan: parse -> extract MDL -> expand CTEs -> transpile
|
||||
|-- 4. Execute: connector -> database -> PyArrow table
|
||||
|-- 5. Output: table, CSV, JSON, or SDK return value
|
||||
```
|
||||
|
||||
### Agent-assisted query
|
||||
|
||||
```text
|
||||
User asks a business question
|
||||
|
|
||||
|-- skill selects the query workflow
|
||||
|-- memory recalls similar accepted NL-SQL pairs
|
||||
|-- memory fetches relevant schema and instructions
|
||||
|-- agent writes SQL against MDL objects
|
||||
|-- Wren AI dry-plans, validates, or executes
|
||||
|-- agent repairs or asks a clarification if needed
|
||||
|-- confirmed answer is stored back into memory
|
||||
```
|
||||
|
||||
### Project build
|
||||
|
||||
```text
|
||||
wren context build
|
||||
|
|
||||
|-- read wren_project.yml
|
||||
|-- read models, views, cubes, and relationships
|
||||
|-- validate structure and references
|
||||
|-- compile source YAML into target/mdl.json
|
||||
```
|
||||
|
||||
### Memory lifecycle
|
||||
|
||||
```text
|
||||
wren memory index -> parse MDL and instructions, build schema_items
|
||||
wren memory fetch -q "..." -> retrieve relevant schema context
|
||||
wren memory recall -q "..." -> retrieve similar confirmed examples
|
||||
wren memory store -> append a new NL-SQL pair to query_history
|
||||
```
|
||||
|
||||
## Key dependencies
|
||||
|
||||
| Dependency | Role |
|
||||
| --- | --- |
|
||||
| `wren-core-py` | Python bindings for the Rust semantic engine. |
|
||||
| `sqlglot` | SQL parsing, qualification, and dialect transpilation. |
|
||||
| Database connectors | Execution layer for supported data sources. |
|
||||
| `pyarrow` | Query result representation. |
|
||||
| `lancedb` | Vector storage for memory. |
|
||||
| `sentence-transformers` | Local embeddings for memory search. |
|
||||
| `typer` | CLI framework. |
|
||||
| `pydantic` | Configuration and connection validation. |
|
||||
|
||||
## In short
|
||||
|
||||
Wren AI architecture separates context from execution:
|
||||
|
||||
- project files define what the data means
|
||||
- memory retrieves relevant context and examples
|
||||
- skills tell agents how to operate safely
|
||||
- the planner and Rust engine turn modeled SQL into executable SQL
|
||||
- connectors run that SQL against the database
|
||||
|
||||
That separation is what makes Wren AI portable, inspectable, and agent-native.
|
||||
@@ -269,5 +269,5 @@ cat query.json | wren cube query --from -
|
||||
**Supported filter operators:** `eq`, `neq`, `in`, `not_in`, `gt`, `gte`, `lt`,
|
||||
`lte`, `contains`, `starts_with`, `is_null`, `is_not_null`.
|
||||
|
||||
See the [Cube guide](../guides/modeling/cube.md) for YAML structure and
|
||||
See the [Cube guide](../guides/cubes.md) for YAML structure and
|
||||
validation rules.
|
||||
|
||||
@@ -0,0 +1,381 @@
|
||||
---
|
||||
sidebar_label: MDL schema
|
||||
---
|
||||
|
||||
# MDL schema reference
|
||||
|
||||
This page documents every YAML artifact in a Wren project — `wren_project.yml`, models, relationships, views, cubes, and `instructions.md` — with the full field surface for each.
|
||||
|
||||
> For the conceptual framing of MDL, see [What does MDL do for the agent?](/oss/concepts/what_is_mdl). For the project lifecycle commands, see [Manage project](/oss/guides/manage_project). For the canonical YAML compilation flow, run `wren context build` after editing.
|
||||
|
||||
## Project structure
|
||||
|
||||
```text
|
||||
my_project/
|
||||
├── wren_project.yml # project metadata
|
||||
├── models/
|
||||
│ ├── orders/
|
||||
│ │ └── metadata.yml # table_reference mode (physical table)
|
||||
│ ├── customers/
|
||||
│ │ └── metadata.yml
|
||||
│ └── revenue_summary/
|
||||
│ ├── metadata.yml # ref_sql mode (SQL-defined model)
|
||||
│ └── ref_sql.sql # SQL in separate file (optional)
|
||||
├── views/
|
||||
│ ├── monthly_revenue/
|
||||
│ │ ├── metadata.yml
|
||||
│ │ └── sql.yml # statement in separate file (optional)
|
||||
│ └── top_customers/
|
||||
│ └── metadata.yml # statement inline
|
||||
├── cubes/
|
||||
│ └── revenue/
|
||||
│ └── metadata.yml
|
||||
├── relationships.yml # all relationships
|
||||
├── instructions.md # business and operational guidance for agents
|
||||
├── queries.yml # curated NL-SQL pairs (optional)
|
||||
├── .wren/ # runtime state (gitignored)
|
||||
│ └── memory/ # LanceDB index files
|
||||
└── target/
|
||||
└── mdl.json # build output (gitignored)
|
||||
```
|
||||
|
||||
YAML files use **snake_case** field names. The compiled `target/mdl.json` uses **camelCase** — the wire format expected by the engine.
|
||||
|
||||
## `wren_project.yml`
|
||||
|
||||
```yaml
|
||||
schema_version: 3
|
||||
name: my_project
|
||||
version: "1.0"
|
||||
catalog: wren
|
||||
schema: public
|
||||
data_source: postgres
|
||||
profile: my-pg
|
||||
```
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `schema_version` | int | yes | Directory layout version. `2` = folder-per-entity, `3` = adds `dialect` field support (current). Owned by the CLI — bump with `wren context upgrade`. |
|
||||
| `name` | string | yes | Project identifier. |
|
||||
| `version` | string | no | User-defined project version (free-form, no parsing effect). |
|
||||
| `catalog` | string | no | **Wren AI namespace** — not your database catalog. Defaults to `wren`. |
|
||||
| `schema` | string | no | **Wren AI namespace** — not your database schema. Defaults to `public`. |
|
||||
| `data_source` | string | no | Data source type (`postgres`, `bigquery`, `snowflake`, ...). Set by `wren context set-profile`. |
|
||||
| `profile` | string | no | The bound connection profile name. Set by `wren context set-profile`. |
|
||||
|
||||
> **Two levels of `catalog` and `schema`.** The same field names appear in two places with completely different meanings. The project-level fields are Wren AI's internal namespace; the model-level `table_reference.catalog` and `table_reference.schema` point at the underlying database location.
|
||||
>
|
||||
> | Location | Refers to | Example |
|
||||
> |---|---|---|
|
||||
> | `wren_project.yml` → `catalog`, `schema` | Wren AI namespace | `wren`, `public` |
|
||||
> | `models/*/metadata.yml` → `table_reference.catalog`, `table_reference.schema` | Database location | `jaffle_shop`, `main` |
|
||||
|
||||
## Models (`models/<name>/metadata.yml`)
|
||||
|
||||
Each model is its own directory under `models/`. A model defines:
|
||||
|
||||
- where its data comes from — `table_reference` or `ref_sql`
|
||||
- which columns are exposed
|
||||
- relationships and calculated fields
|
||||
|
||||
### Model fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|---|---|---|
|
||||
| `name` | yes | Unique model name (used in SQL queries). |
|
||||
| `table_reference` | one of two | Maps to a physical table (`catalog`, `schema`, `table`). |
|
||||
| `ref_sql` | one of two | A SQL SELECT used as the model's data source. |
|
||||
| `columns` | yes | List of columns to expose. |
|
||||
| `primary_key` | no | Column name uniquely identifying a row; required for `TO_MANY` relationship traversals. |
|
||||
| `cached` | no | Whether query results should be cached. Defaults to `false`. |
|
||||
| `dialect` | no | SQL dialect of the model's `ref_sql`. Overrides project-level `data_source` for this model. Requires `schema_version: 3`. |
|
||||
| `properties` | no | Arbitrary key-value metadata. |
|
||||
|
||||
Using both `table_reference` and `ref_sql` in the same model is a validation error.
|
||||
|
||||
### `table_reference`
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `catalog` | string | no | Source-side catalog (DuckDB database stem, BigQuery project, Snowflake database). Omit for sources without a catalog layer. |
|
||||
| `schema` | string | no | Source-side schema or dataset. Omit for flat sources. |
|
||||
| `table` | string | yes | Source-side table or view name. |
|
||||
|
||||
### Example: `table_reference`
|
||||
|
||||
```yaml
|
||||
name: customers
|
||||
table_reference:
|
||||
catalog: jaffle_shop
|
||||
schema: main
|
||||
table: customers
|
||||
primary_key: customer_id
|
||||
columns:
|
||||
- name: customer_id
|
||||
type: INTEGER
|
||||
is_primary_key: true
|
||||
not_null: true
|
||||
- name: first_name
|
||||
type: VARCHAR
|
||||
- name: last_name
|
||||
type: VARCHAR
|
||||
- name: number_of_orders
|
||||
type: BIGINT
|
||||
```
|
||||
|
||||
### Example: `ref_sql`
|
||||
|
||||
```yaml
|
||||
name: revenue_summary
|
||||
ref_sql: |
|
||||
SELECT DATE_TRUNC('month', order_date) AS month,
|
||||
SUM(total) AS total_revenue
|
||||
FROM orders
|
||||
GROUP BY 1
|
||||
columns:
|
||||
- name: month
|
||||
type: DATE
|
||||
- name: total_revenue
|
||||
type: DECIMAL
|
||||
```
|
||||
|
||||
The SQL can live inline (above) or in a sibling `ref_sql.sql` file. The `.sql` file takes precedence.
|
||||
|
||||
### Columns
|
||||
|
||||
| Field | Required | Description |
|
||||
|---|---|---|
|
||||
| `name` | yes | Column name used in SQL. |
|
||||
| `type` | yes | SQL type (`VARCHAR`, `INTEGER`, `DOUBLE`, `DATE`, `TIMESTAMP`, `BOOLEAN`, `DECIMAL`, `JSON`, ...). |
|
||||
| `is_calculated` | no | If `true`, the value is derived from `expression` at query time. |
|
||||
| `expression` | no | SQL expression for calculated columns, or a single-column reference for simple renames. |
|
||||
| `relationship` | no | Name of a relationship — makes this a join handle column. |
|
||||
| `not_null` | no | Constraint hint. Defaults to `false`. |
|
||||
| `is_primary_key` | no | Marks the column as the model's primary key. |
|
||||
| `is_hidden` | no | Engine-internal flag; column is stripped from the symbol table and invisible to all clients. |
|
||||
| `properties` | no | Arbitrary metadata (e.g. `properties.description`). |
|
||||
|
||||
#### Calculated columns
|
||||
|
||||
```yaml
|
||||
- name: total_with_tax
|
||||
type: DOUBLE
|
||||
is_calculated: true
|
||||
expression: "amount * 1.1"
|
||||
```
|
||||
|
||||
#### Relationship columns
|
||||
|
||||
A relationship column declares a join path to another model:
|
||||
|
||||
```yaml
|
||||
- name: customer
|
||||
type: customers # the related model name
|
||||
relationship: orders_customers
|
||||
```
|
||||
|
||||
Then `orders.customer.first_name` is valid SQL — the engine resolves the join automatically.
|
||||
|
||||
#### Column rename via `expression`
|
||||
|
||||
When `is_calculated` is `false` but an `expression` is present, the expression must be a simple column reference. The engine resolves the physical column name from the expression and uses the model column name as the alias:
|
||||
|
||||
```yaml
|
||||
- name: customer_id # exposed name
|
||||
type: INTEGER
|
||||
expression: usr_id # physical column name
|
||||
```
|
||||
|
||||
### Selective exposure for column-level access control
|
||||
|
||||
A model does not have to expose every column in the underlying table. Omitted columns are physically invisible to clients — no SQL can reference them, and they do not appear in schema introspection.
|
||||
|
||||
This matters for AI agents: any column you omit from the model cannot be retrieved through Wren AI, regardless of what the agent asks.
|
||||
|
||||
## Relationships (`relationships.yml`)
|
||||
|
||||
```yaml
|
||||
relationships:
|
||||
- name: orders_customers
|
||||
models:
|
||||
- orders
|
||||
- customers
|
||||
join_type: MANY_TO_ONE
|
||||
condition: orders.customer_id = customers.customer_id
|
||||
```
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `name` | string | yes | Unique relationship identifier. |
|
||||
| `models` | array[string] | yes | Exactly two model names `[from, to]`. |
|
||||
| `join_type` | enum | yes | `ONE_TO_ONE`, `ONE_TO_MANY`, `MANY_TO_ONE`, or `MANY_TO_MANY`. |
|
||||
| `condition` | string | yes | SQL equality condition using `model.column` references on both sides. |
|
||||
|
||||
The first model in `models` should appear on the left side of the condition. Only equality conditions are supported.
|
||||
|
||||
For `TO_MANY` relationships, calculated columns that traverse the relationship must use aggregate functions — the engine wraps the join in an aggregate subquery to prevent row multiplication.
|
||||
|
||||
## Views (`views/<name>/metadata.yml`)
|
||||
|
||||
```yaml
|
||||
name: top_customers
|
||||
statement: |
|
||||
SELECT customer_id, SUM(total) AS lifetime_value
|
||||
FROM wren.public.orders
|
||||
GROUP BY 1
|
||||
ORDER BY 2 DESC
|
||||
LIMIT 100
|
||||
properties:
|
||||
description: "Top customers by lifetime value"
|
||||
```
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `name` | string | yes | Unique view name. |
|
||||
| `statement` | string | yes | Complete SQL SELECT. May reference other models or views. |
|
||||
| `dialect` | string | no | SQL dialect (metadata only — engine parses with its generic parser). Requires `schema_version: 3`. |
|
||||
| `properties` | no | Arbitrary metadata. |
|
||||
|
||||
The statement can live inline or in a sibling `sql.yml` file. The `sql.yml` takes precedence.
|
||||
|
||||
Views inherit no column declarations — schema is inferred from the statement at query time. Views can reference other views; the engine expands them recursively before resolving models.
|
||||
|
||||
## Cubes (`cubes/<name>/metadata.yml`)
|
||||
|
||||
A cube is a pre-aggregated semantic object: a base model or view, plus declared measures, dimensions, time dimensions, and hierarchies.
|
||||
|
||||
```yaml
|
||||
name: revenue
|
||||
base_object: orders
|
||||
measures:
|
||||
- name: total
|
||||
expression: SUM(amount)
|
||||
type: DOUBLE
|
||||
- name: order_count
|
||||
expression: COUNT(*)
|
||||
type: BIGINT
|
||||
dimensions:
|
||||
- name: status
|
||||
expression: status
|
||||
type: VARCHAR
|
||||
time_dimensions:
|
||||
- name: month
|
||||
expression: order_date
|
||||
grain: month
|
||||
type: DATE
|
||||
hierarchies:
|
||||
- name: time
|
||||
levels: [year, quarter, month]
|
||||
```
|
||||
|
||||
| Field | Required | Description |
|
||||
|---|---|---|
|
||||
| `name` | yes | Unique cube name. |
|
||||
| `base_object` | yes | Model or view this cube aggregates over. |
|
||||
| `measures[]` | yes | Aggregated values (`expression` + `type`). |
|
||||
| `dimensions[]` | no | Categorical group-bys. |
|
||||
| `time_dimensions[]` | no | Time-based group-bys with explicit grain. |
|
||||
| `hierarchies[]` | no | Ordered levels for drill-down (year → quarter → month). |
|
||||
| `refresh_time` | no | Cache refresh interval. |
|
||||
| `properties` | no | Arbitrary metadata. |
|
||||
|
||||
Cubes are queried structurally via `wren cube query`, not by writing raw `GROUP BY` SQL. See [Pre-aggregate with cubes](/oss/guides/cubes) for the agent-facing recipe.
|
||||
|
||||
## Instructions (`instructions.md`)
|
||||
|
||||
Free-form markdown with business and operational guidance for AI agents. Organized by topic with `##` headings — each heading and its body becomes a retrievable chunk in memory.
|
||||
|
||||
```markdown
|
||||
## Business rules
|
||||
- Revenue queries must use `net_revenue`, not `gross_revenue`.
|
||||
- All active-customer queries exclude rows where `is_internal = true`.
|
||||
|
||||
## Canonical tables
|
||||
- Use `customers` for analytics, not `customers_v3` or `loyalty_v3`.
|
||||
|
||||
## Formatting
|
||||
- Currency is USD; display with thousand separators and 2 decimals.
|
||||
- Timestamps are stored in UTC.
|
||||
```
|
||||
|
||||
Instructions are consumed by agents, not by the engine. They are intentionally excluded from `target/mdl.json`. Agents access them via:
|
||||
|
||||
- `wren context instructions` — full text, run once at session start
|
||||
- `wren memory fetch -q "..."` — relevant chunks per query
|
||||
|
||||
## `queries.yml` (optional)
|
||||
|
||||
Curated natural-language-to-SQL pairs that seed memory. Same format as `wren memory dump` output:
|
||||
|
||||
```yaml
|
||||
version: 1
|
||||
pairs:
|
||||
- nl: "monthly revenue by product category"
|
||||
sql: |
|
||||
SELECT category, DATE_TRUNC('month', order_date) AS month, SUM(amount)
|
||||
FROM orders
|
||||
GROUP BY 1, 2
|
||||
source: user
|
||||
datasource: postgres-prod
|
||||
```
|
||||
|
||||
`wren memory index` auto-loads `queries.yml` after indexing the schema. Pairs added through `wren memory store` can be exported back to `queries.yml` with `wren memory dump`.
|
||||
|
||||
## Snake_case to camelCase mapping
|
||||
|
||||
`wren context build` converts YAML field names to camelCase in `target/mdl.json`:
|
||||
|
||||
| YAML | JSON |
|
||||
|---|---|
|
||||
| `table_reference` | `tableReference` |
|
||||
| `ref_sql` | `refSql` |
|
||||
| `is_calculated` | `isCalculated` |
|
||||
| `not_null` | `notNull` |
|
||||
| `is_primary_key` | `isPrimaryKey` |
|
||||
| `primary_key` | `primaryKey` |
|
||||
| `join_type` | `joinType` |
|
||||
| `data_source` | `dataSource` |
|
||||
| `layout_version` | `layoutVersion` |
|
||||
| `refresh_time` | `refreshTime` |
|
||||
| `base_object` | `baseObject` |
|
||||
|
||||
Generic rule: split on `_`, capitalize each word after the first, join. All other fields (`name`, `type`, `catalog`, `schema`, `table`, `condition`, `models`, `columns`, `cached`, `dialect`, `properties`) are identical in both formats.
|
||||
|
||||
`layoutVersion` is stamped automatically by `wren context build` based on the project's `schema_version` — you do not set it manually in YAML.
|
||||
|
||||
## Dialect override
|
||||
|
||||
Models and views support an optional `dialect` field declaring which SQL dialect their embedded SQL is written in. Requires `schema_version: 3`.
|
||||
|
||||
| Setting | Behavior |
|
||||
|---|---|
|
||||
| `dialect` omitted | Falls back to project-level `data_source`. Default. |
|
||||
| `dialect` set | Engine uses the named dialect parser for this object's SQL. |
|
||||
|
||||
Valid dialect values: `athena`, `bigquery`, `canner`, `clickhouse`, `databricks`, `datafusion`, `doris`, `duckdb`, `gcs_file`, `local_file`, `minio_file`, `mssql`, `mysql`, `oracle`, `postgres`, `redshift`, `s3_file`, `snowflake`, `spark`, `trino`.
|
||||
|
||||
### Schema version vs layout version
|
||||
|
||||
| `schema_version` | `layoutVersion` | Capabilities |
|
||||
|---|---|---|
|
||||
| 1 | 1 | Legacy flat-file project format. |
|
||||
| 2 | 1 | Folder-per-entity project format. |
|
||||
| 3 | 2 | Adds the `dialect` field on models and views. |
|
||||
|
||||
Use `wren context upgrade` to bump. The upgrade is dry-runnable with `--dry-run`.
|
||||
|
||||
## Recommended `.gitignore`
|
||||
|
||||
```text
|
||||
target/
|
||||
.wren/memory/
|
||||
```
|
||||
|
||||
Source YAML and `instructions.md` are committed. `target/mdl.json` is derived; `.wren/memory/` is binary LanceDB data — share confirmed NL-SQL pairs through `queries.yml` instead.
|
||||
|
||||
## See also
|
||||
|
||||
- [Manage project](/oss/guides/manage_project) — lifecycle commands, profile binding, multi-env workflow
|
||||
- [CLI reference](./cli.md) — every `wren` command
|
||||
- [Operational reference](./operational.md) — all paths, env vars, and discovery rules
|
||||
- [What does MDL do for the agent?](/oss/concepts/what_is_mdl) — the conceptual framing
|
||||
@@ -0,0 +1,133 @@
|
||||
---
|
||||
sidebar_label: Operational reference
|
||||
---
|
||||
|
||||
# Operational reference
|
||||
|
||||
Single-page reference for every path, environment variable, and discovery rule Wren AI uses. Bookmark this page if you operate Wren AI across machines, environments, or CI.
|
||||
|
||||
## File system layout
|
||||
|
||||
### Global (`~/.wren/`)
|
||||
|
||||
| Path | Purpose | Created by |
|
||||
|---|---|---|
|
||||
| `~/.wren/profiles.yml` | All connection profiles plus the `active` pointer. Permissions: `0600`. | `wren profile add` |
|
||||
| `~/.wren/config.yml` | CLI preferences. Contains `default_project` if set. | `wren context set-profile`, manual edits |
|
||||
| `~/.wren/connection_info.json` | Legacy connection fallback (kept for backward compatibility). | Older CLI versions |
|
||||
| `~/.wren/.env` | User-global `.env` fallback for `${VAR}` interpolation. | Manual |
|
||||
|
||||
Override the entire global directory with `WREN_HOME`.
|
||||
|
||||
### Per-project (`<project>/`)
|
||||
|
||||
| Path | Purpose | Commit? |
|
||||
|---|---|---|
|
||||
| `wren_project.yml` | Project root, `schema_version` pin, bound profile and data source. | ✅ yes |
|
||||
| `models/<name>/metadata.yml` | Model definitions. | ✅ yes |
|
||||
| `models/<name>/ref_sql.sql` | Optional separate SQL file for `ref_sql` models. | ✅ yes |
|
||||
| `views/<name>/metadata.yml` | View definitions. | ✅ yes |
|
||||
| `views/<name>/sql.yml` | Optional separate `statement` file for views. | ✅ yes |
|
||||
| `cubes/<name>/metadata.yml` | Cube definitions. | ✅ yes |
|
||||
| `relationships.yml` | All relationships. | ✅ yes |
|
||||
| `instructions.md` | LLM-facing natural-language guidance. | ✅ yes |
|
||||
| `queries.yml` | Curated NL-SQL pairs (seed for memory). | ✅ yes |
|
||||
| `.env` | Per-project `.env` for `${VAR}` interpolation. | ❌ gitignore |
|
||||
| `.wren/memory/` | LanceDB index files (schema + query history). | ❌ gitignore |
|
||||
| `target/mdl.json` | Compiled MDL manifest (rebuildable). | ❌ gitignore |
|
||||
|
||||
## Environment variables
|
||||
|
||||
| Var | Purpose | Default |
|
||||
|---|---|---|
|
||||
| `WREN_HOME` | Override the global Wren directory. | `~/.wren` |
|
||||
| `WREN_PROJECT_HOME` | Skip project walk-up; point directly at a project root. | — (walks up from cwd) |
|
||||
| `OPENAI_API_KEY` | Required for memory embeddings and the `add-llms-md.js` doc prebuild. | — |
|
||||
| `CLAUDE_SKILLS_DIR` | Override the skill install directory used by `install.sh`. | `~/.claude/skills` |
|
||||
| `WREN_SKILLS_BRANCH` | Override the branch when installing skills via the curl script. | `main` |
|
||||
|
||||
Profile values can also reference `${VAR}` from `os.environ` or a `.env` file — see [Resolution order](#env-resolution-order).
|
||||
|
||||
## Project discovery
|
||||
|
||||
When a `wren` command needs a project (`query`, `memory fetch`, `context build`, etc.), the CLI resolves `<project>` in this order:
|
||||
|
||||
1. `--path <path>` flag (explicit)
|
||||
2. `WREN_PROJECT_HOME` environment variable
|
||||
3. Walk up from cwd looking for `wren_project.yml`
|
||||
4. `default_project` field in `~/.wren/config.yml`
|
||||
|
||||
If no project is found, the CLI exits with a clear error and suggests `wren context init` or setting `WREN_PROJECT_HOME`.
|
||||
|
||||
## Profile resolution
|
||||
|
||||
When a command needs a connection, the CLI resolves connection info in this order:
|
||||
|
||||
1. Explicit `--connection-info '<json>'` flag (highest priority)
|
||||
2. Explicit `--connection-file <path>` flag
|
||||
3. **Bound profile** in `wren_project.yml` (`profile: <name>`)
|
||||
4. **Active profile** in `~/.wren/profiles.yml` (the `active` pointer)
|
||||
5. Legacy `~/.wren/connection_info.json`
|
||||
|
||||
If none are found, the command fails with a connection error.
|
||||
|
||||
## `.env` resolution order {#env-resolution-order}
|
||||
|
||||
`${VAR}` placeholders in profile YAML are resolved at connection time. The CLI looks up each variable in this order (first match wins; process env beats any `.env`):
|
||||
|
||||
1. `os.environ` — variables already exported in your shell
|
||||
2. `$CWD/.env` — directory you run `wren` from
|
||||
3. `<project>/.env` — co-located with `wren_project.yml`
|
||||
4. `~/.wren/.env` — user-global fallback
|
||||
|
||||
Rules:
|
||||
|
||||
- Names must be **UPPERCASE** (`[A-Z_][A-Z0-9_]*`)
|
||||
- Lowercase `${foo}` is treated as a literal string
|
||||
- `$$` escapes a literal dollar sign (`a$$b` becomes `a$b`)
|
||||
- Missing variables fail early with a clear error — no cryptic driver auth errors
|
||||
|
||||
## Skill install paths
|
||||
|
||||
The `npx skills add` and `install.sh` paths write skills to one of the following directories, depending on the `--agent` flag:
|
||||
|
||||
| Pattern | Used by | Examples |
|
||||
|---|---|---|
|
||||
| `<project>/.agents/skills/` | Multi-agent shared dir | Amp, Cursor, Cline, OpenCode (project), Codex (project) |
|
||||
| `<project>/.<agent>/skills/` | Agent-specific dir | Claude Code (`.claude/skills/`), Continue (`.continue/skills/`), Windsurf (`.windsurf/skills/`) |
|
||||
| `<project>/skills/` | Repo-root convention | OpenClaw |
|
||||
| `~/.<agent>/skills/` | Global install | `~/.codex/skills/`, `~/.gemini/skills/`, `~/.deepagents/agent/skills/` |
|
||||
|
||||
See [Installation](/oss/get_started/installation) for the per-agent picker.
|
||||
|
||||
## Recommended `.gitignore`
|
||||
|
||||
For a Wren project, add:
|
||||
|
||||
```text
|
||||
target/
|
||||
.wren/memory/
|
||||
.env
|
||||
```
|
||||
|
||||
For an application repo that uses Wren AI through SDK or CLI, also consider:
|
||||
|
||||
```text
|
||||
.wren/ # if the runtime state directory is created in the repo root
|
||||
```
|
||||
|
||||
## Permissions
|
||||
|
||||
| File | Permission |
|
||||
|---|---|
|
||||
| `~/.wren/profiles.yml` | `0600` — owner read/write only. Written atomically (temp file + rename). |
|
||||
| `<project>/.env` | Owner read/write recommended. |
|
||||
| `~/.wren/.env` | Owner read/write recommended. |
|
||||
|
||||
Secrets in `profiles.yml` are kept as `${VAR}` placeholders — the file never contains plaintext credentials. `wren profile debug` masks any fields named `password`, `credentials`, `secret`, or `token`.
|
||||
|
||||
## See also
|
||||
|
||||
- [CLI reference](./cli.md) — every command and flag
|
||||
- [MDL schema reference](./mdl.md) — every YAML field in a project
|
||||
- [Manage project](/oss/guides/manage_project) — lifecycle commands and profile workflow
|
||||
@@ -129,7 +129,7 @@ await engine.loadMDL(mdl, { source: '' }); // auto-detect; uses the registered
|
||||
|
||||
### 3. Cube queries (structured aggregation)
|
||||
|
||||
When the MDL defines a [cube](../guides/modeling/cube.md), prefer `cubeQuery`
|
||||
When the MDL defines a [cube](../guides/cubes.md), prefer `cubeQuery`
|
||||
over hand-written `GROUP BY` SQL. The engine assembles `DATE_TRUNC` / filters
|
||||
/ projections from a JSON request — useful for an agent that doesn't need to
|
||||
think about SQL syntax.
|
||||
@@ -269,7 +269,7 @@ interface CubeQueryInput {
|
||||
}
|
||||
```
|
||||
|
||||
See [`docs/core/guides/modeling/cube.md`](../guides/modeling/cube.md) for the
|
||||
See [`docs/co../guides/cubes.md`](../guides/cubes.md) for the
|
||||
full input shape and filter operator list.
|
||||
|
||||
### `engine.listCubes()`
|
||||
|
||||
Reference in New Issue
Block a user