LLM bootstrap — orientation and self-learning

This page is the entry point for an LLM that needs to write or reason about FeatureQL. Read this page first, then load additional pages on demand based on the task.

What FeatureQL is

FeatureQL is a functional, entity-centric DSL that transpiles to SQL dialects (DuckDB, Trino, BigQuery, DataFusion). You write flat lists of named expressions called features. Features are pure functions — they compose through automatic dependency tracking, with no CTEs, no subqueries, and no imperative control flow.

A minimal working query:

WITH
    ID := INPUT(BIGINT),
SELECT
    ID,
    DOUBLED := ID * 2
FOR
    ID := BIND_VALUES(ARRAY[1, 2, 3]);
-- Result: (1, 2), (2, 4), (3, 6)
sql

Every query must have a BIND_XXX() in the FOR clause or it will not execute. This is the single most common mistake.

Page index — load what you need

PageLoad when...
Syntax reference You need to write or debug FeatureQL syntax: types, casting, operators, query structure
Data sources You need to connect features to tables, inline data, or bind input values
Modeling You need to model entities, traverse relationships with EXTEND/TRANSFORM/RELATED
Recipes You need patterns for common tasks: aggregation, filtering, analytics, feature engineering

Self-learning: query the system dynamically

You do not need all knowledge in your context window. FeatureQL has built-in discovery commands you can execute at any time:

-- Browse all documentation pages (titles only, fast)
SHOW DOCS (EXCLUDE (CONTENT)) WHERE CATEGORY='DOC_PAGE' ORDER BY NAME;

-- Search documentation content for a topic
SHOW DOCS WHERE CONTENT LIKE '%EXTEND%' AND CATEGORY = 'CODE_SAMPLE';

-- Get function signatures (exact syntax, parameters, return types)
SHOW FUNCTION SIGNATURES WHERE NAME IN ('EXTEND', 'TRANSFORM', 'EXTERNAL_COLUMNS');

-- Get executable test cases for a function (learn by example)
SHOW FUNCTION TESTS WHERE FUNCTION_NAME = 'EXTEND';

-- Explore persisted features in a namespace
SHOW FEATURES WHERE FUNCTION IN ('ENTITY', 'INPUT', 'EXTERNAL_COLUMNS');
SHOW FEATURES WHERE NAME LIKE 'finance.%';
SHOW FEATURES WHERE IS_DOWNSTREAM_OF(CUSTOMER_ID);
sql

Use these aggressively. When you encounter an unfamiliar function, run SHOW FUNCTION SIGNATURES before guessing. When you need a pattern, search SHOW DOCS or SHOW FUNCTION TESTS before inventing one.

Efficient exploration workflow

When starting a new task on an existing codebase:

  1. Discover what existsSHOW FEATURES WHERE FUNCTION IN ('ENTITY', 'INPUT', 'EXTERNAL_COLUMNS');
  2. Find relevant featuresSHOW FEATURES WHERE NAME LIKE 'finance.%'; or SHOW FEATURES WHERE IS_DOWNSTREAM_OF(CUSTOMER_ID);
  3. Verify function syntaxSHOW FUNCTION SIGNATURES WHERE NAME = 'function_name';
  4. Find examplesSHOW FUNCTION TESTS WHERE FUNCTION_NAME = 'function_name';

Error recovery

When a query fails, read the error message carefully — it includes the location in the query. Then check this list:

SymptomLikely causeFix
"Missing binding" or query won't executeNo BIND_XXX() in FOR clauseAdd FOR INPUT_NAME := BIND_VALUES(ARRAY[...])
Type mismatchNo automatic coercion in FeatureQLCast explicitly: value::TYPE or CAST(value AS TYPE)
Unknown functionTypo or wrong nameVerify: SHOW FUNCTION SIGNATURES WHERE NAME = 'name'
Entity mismatchAnnotations don't match (BIGINT#CUSTOMERS vs BIGINT#ORDERS)Check entity annotations on INPUT and foreign keys
"Cannot resolve feature"Feature not in scopeCheck namespace: FROM fm.namespace or use fully qualified name

General debugging strategy: remove features one by one until the query works, then add them back to isolate the problem.

Critical differences from SQL

These will trip you up if you think in SQL:

  1. No CTEs, no subqueries. A query is a flat list of feature := expression definitions. Features can reference each other in any order — dependency resolution is automatic.
  2. Mandatory binding. Every query needs BIND_VALUE(), BIND_VALUES(), BIND_SQL(), or BIND_COLUMNS() in the FOR clause if one dependency of the returned feature is an INPUT() feature.
  3. Limited type coercion. 1 + 1.0 is an error (integer + decimal). DECIMAL scalar arithmetic auto-coerces between precisions (1.1 + 1.25 works), but array and ROW constructors do not (ARRAY[ROW(1.1 AS v), ROW(1.25 AS v)] fails). Use DOUBLE with e0 suffix to avoid surprises: 1.25e0.
  4. Entity-centric. Features are organized around entities (CUSTOMER, ORDER, PRODUCT), not tables. The mapping to tables is done via EXTERNAL_COLUMNS().
  5. GROUP BY is per-feature. Write SUM(amount) GROUP BY category, not a separate GROUP BY clause at the end.
  6. Only two scopes: features and fields. Top-level features reference other features. Inside TRANSFORM(), you work with fields from the array. There is never a third nesting level. This keeps reasoning simple: EXTEND() brings cross-entity data into the array, TRANSFORM() processes it. Think of it as a pipeline, not nested subqueries.
  7. Always write explicit VIA ... BIND TO in EXTEND. Auto-inference exists but explicit binding is clearer and avoids ambiguity errors.
Last update at: 2026/03/03 16:47:38
Last updated: 2026-03-03 16:48:19