Skip to content
Browse documentation
API Reference

AVA API

Method signatures, complete input tables, defaults, and returned values.

Use this reference to look up signatures, inputs, and return values after following the quickstart. The AVA data and visualization methods are asynchronous. See Events for lifecycle subscriptions and Custom engines for engine extension points.

API at a glance

SectionAPIWhat it does
Initializationnew AVA(config)Configure the model and execution engine.
Datasource(config)Load or replace a data source.
schema(options?, setter?)Inspect or set data structure.
profile(options?, setter?)Compute or set statistics.
semantic(options?, setter?)Read or set business definitions.
Analysis and queriesanalyze(query, config?)Answer a question.
More control translate(query)Generate a query.
More control query(dsl, options?)Execute a query.
suggest(count?)Suggest questions.
Visualizationvisualize(analysisResult)Recommend and render a chart.
More control recommend(analysisResult)Recommend a chart specification.
More control viz(spec)Render a chart specification.
Cleanupdispose()Release resources.

More control These APIs expose individual operations that can be called independently.

Initialization

Constructor

new AVA(config: AVAConfig)

ParameterTypeRequiredDefault / behavior
configAVAConfigYesConfiguration object.
config.llmLLMConfigYesModel fields below.
config.engineEngineConfigNo{ type: 'duckdb' }; engine fields below.

The constructor does not load data. Engine creation happens on source().

Model options

Fields below belong to config.llm.

FieldTypeRequiredMeaning / default
provider'openai' | 'gateway'NoDefaults to OpenAI-compatible Chat Completions. Gateway reads AI_GATEWAY_API_KEY.
modelstring | LanguageModelYesModel name or a preconfigured AI SDK model instance.
apiKeystringNoAPI key for the LLM provider
baseURLstringNoOptional API base URL
maxRetriesnumberNoMaximum retries for retryable model API failures. Default 3.

String model names use OpenAI-compatible Chat Completions by default. A supplied model object is used directly. Usage callbacks are not a complete accounting stream for every LLM request.

Engine options

config.engine.type is required when engine is supplied. Supported values are duckdb, python, javascript, supabase, and clickhouse, plus names registered through registerEngine(). Omitting engine selects DuckDB. JavaScript, Supabase, and ClickHouse accept no additional engine fields; connection credentials belong to source().

DuckDB

Set engine.type to duckdb. These are all additional fields accepted on engine.

FieldTypeRequiredMeaning / default
memoryLimitstringNoMemory limit, e.g. '512MB'. Default '512MB'.
threadsnumberNoNumber of worker threads. Default 1.
maxTempDirectorySizestringNoMax size of the spill (temp) directory, e.g. '1GB'. Unset = unlimited.
queryTimeoutMsnumberNoPer-query timeout in milliseconds. Default 30000.
allowCommunityExtensionsbooleanNoAllow DuckDB community extensions during source loading when explicitly needed.
Python

Set engine.type to python. These are all additional fields accepted on engine.

FieldTypeRequiredMeaning / default
execute(code: string) => Promise<ExecutionResult>NoOverride local python3 execution with a custom environment. Local execution is not sandboxed. Run the complete Python script and return its JSON output as ExecutionResult. Source loading and result limits are included in the script; configure remote execution deadlines separately.
queryTimeoutMsnumberNoClient wait limit and local process execution deadline. Default 30000 ms.
Registered engines

Set engine.type to the name passed to registerEngine(). Additional fields are forwarded to the engine constructor as options. This is an SDK-only capability; the CLI supports built-in engine names.

FieldTypeRequiredMeaning / default
typestringYesRegistered engine name, such as 'sales'.
Other fieldsEngine-specificDepends on engineValidated by the registered engine.

Data

source

typescript
source(config: DataSourceConfig): Promise<void>

Loads a data source through the engine. It returns no value and does not discover the schema.

typescript
await ava.source({ type: 'json', options: { data: [{ revenue: 120 }] } });
ParameterTypeRequiredMeaning
configDataSourceConfigYesData source to load.
config.typeSourceTypeYesSource type, such as json or csv-file.
config.optionsSource-specific objectYesReader or connection settings for that type.

Loading a source disposes the previous engine and clears the saved schema, profile, and semantic definitions. A failed load leaves no active source. Await pending operations before replacing a source.

schema

typescript
schema(options?: SchemaOptions, setter?: (options: SchemaOptions) => Schema): Promise<Schema>

Returns the structure of the loaded source. Without a setter, AVA returns the saved schema or discovers it through the engine and saves it.

typescript
const schema = await ava.schema();

To supply an existing schema, pass a function that returns it:

typescript
await ava.schema(undefined, () => savedSchema);
ParameterTypeRequiredMeaning / default
optionsSchemaOptionsNo{}; currently has no configurable fields.
setter(options: SchemaOptions) => SchemaNoReturns the schema to save instead of discovering it through the engine.

A setter receives the options object (default {}) and returns a Schema synchronously. Its result replaces the saved schema and clears the saved profile. AVA validates and copies the result; invalid results or thrown errors reject the call without changing previous metadata.

Requires a loaded source. Analysis and profiling obtain the schema when needed; direct query() does not. For the walkthrough, see Inspect your data.

Schema structure

FieldMeaning
modelsTables or views available for queries; required.
models[].nameModel name.
models[].tableReferencePhysical source identity: table, with optional catalog and schema.
models[].columnsColumns, each with name, type, and optional notNull.
models[].primaryKeyOne column name, or a nonempty ordered array for a composite key.
models[].uniqueKeysArray of alternative keys; each entry is a column name or a composite-key array.
relationshipsDiscovered foreign-key relationships, when available.
viewsNamed view queries with name and statement, when available.

The details depend on the source and engine. A query result's schema describes its output columns and is not a source Schema.

profile

typescript
profile(options?: ProfileOptions, setter?: (options: ProfileOptions) => Profile): Promise<Profile>

Calculates and saves statistics for the loaded source through the engine. Each call without a setter computes a fresh profile and requires engine profiling support.

typescript
const profile = await ava.profile({ metrics: ['row_count', 'mean'] });

To supply an existing profile, pass a function that returns it:

typescript
await ava.profile(undefined, () => savedProfile);
ParameterTypeRequiredMeaning / default
optionsProfileOptionsNo{}; uses the default metrics below.
options.metricsMetricConfig[]NoMetrics for engine computation. A supplied list replaces the defaults.
setter(options: ProfileOptions) => ProfileNoReturns the profile to save instead of computing it through the engine.

A setter receives the options object (default {}) and returns a Profile synchronously. It does not require engine profiling support. AVA validates and copies its result; invalid results or thrown errors reject the call without changing previous metadata. The options are passed to the setter; AVA does not calculate or filter metrics on its behalf.

Requires a loaded source. Both paths replace the saved profile, which analysis, translation, and suggestions can reuse. Setting a profile does not replace the saved schema.

Profile format

A profile attaches observations to existing schema models and columns by name:

FieldMeaning
models[].nameModel to enrich.
models[].metricsTable statistics such as row_count.
models[].columns[].nameColumn to enrich within that model.
models[].columns[].metricsColumn statistics such as mean.
models[].columns[].properties.logicalTypeNormalized category: numeric, string, boolean, date, or unknown.

A missing metric means it was not computed, not zero. Setting a schema clears the saved profile, so supply the schema first when providing both manually. Loading another source or calling dispose() clears schema, profile, and semantic definitions. Updating schema or profile retains semantic definitions.

Metrics

The default metrics are row_count, null_count, distinct_count, top_values, min, max, and mean. Additional built-in metrics are duplicate_count, min_length, max_length, sum, stddev, and median.

Each entry is a metric name or an object with an id and metric-specific options:

typescript
await ava.profile({
  metrics: ['row_count', { id: 'top_values', limit: 5 }],
});
FieldTypeDefault / behavior
idstringRequired for object entries; the metric name.
limitnumbertop_values only. Default 3; a non-negative safe integer.
maxDistinctRationumbertop_values only. Default 0.5; a finite number from 0 to 1.

Other built-in metrics accept no additional options. Unknown metrics and unknown option names are rejected when the engine computes the profile. Availability depends on the engine and field type.

metrics: [] produces empty metric objects. A new profile replaces previous statistics; metrics are not accumulated.

semantic

typescript
semantic(options?: SemanticOptions, setter?: (options: SemanticOptions) => Semantic): Promise<Semantic>

Reads or replaces the semantic definitions for the loaded source. Without a setter, returns the saved definitions, initially {}. This call does not discover the schema, compute a profile, or call an LLM.

typescript
await ava.semantic(undefined, () => ({
  description: 'Sales reporting; amounts are in USD.',
  cubes: [{
    name: 'revenue',
    baseObject: 'data',
    measures: [{ name: 'total', expression: 'SUM(revenue)', type: 'DOUBLE' }],
  }],
}));
 
const definitions = await ava.semantic();
await ava.semantic(undefined, () => ({})); // Clear the saved definitions.
ParameterTypeRequiredMeaning / default
optionsSemanticOptionsNo{}; currently has no configurable fields.
setter(options: SemanticOptions) => SemanticNoReturns the semantic definitions to save, replacing the previous definitions.

The setter receives the options object and returns a Semantic synchronously. AVA validates and copies the result; invalid results or thrown errors leave the previous definitions unchanged. Requires a loaded source. Source replacement and disposal clear these definitions; schema and profile updates retain them.

Semantic contains business definitions and excludes model and column metrics; supply statistical observations through profile(). The combined context passed to engines remains a DataModel.

Start with Define data semantics for the authoring walkthrough and sales example. See semantic fields for the detailed reference.

For analyze(), translate(), and suggest(), AVA merges models and columns by name with the schema and profile. Unspecified models, columns, and observations remain available; model and column properties merge by key, with semantic values taking precedence. A supplied relationship or view list replaces its discovered counterpart, including when the list is empty. Each semantic model must declare exactly one source: tableReference, refSql, or baseObject.

These definitions provide context for query generation. Declaring a cube, view, or calculated column does not create database objects; generated queries must work with the configured engine.

Analysis and queries

analyze

analyze(query: string, config?: AnalysisConfig): Promise<AnalysisResponse>

ParameterTypeRequiredDefault / behavior
querystringYesNatural-language question.
configAnalysisConfigNo{}.
config.includeSummarybooleanNotrue; false returns empty text.
config.maxRowsnumberNo200; see execution limits.
config.maxResultBytesnumberNo1048576; see execution limits.
config.strategyAnalysisStrategyConfigNoDirect analysis.
config.strategy.type'direct' / 'loop'When strategy is providedSelects the strategy.
config.strategy.maxRetriesnumberNo; direct only2 with explicit type: 'direct'; currently 10 when the strategy is omitted. Correction attempts after the first execution.
config.strategy.maxStepsnumberNo; loop only12; maximum reasoning steps.

These retry controls differ from llm.maxRetries. See strategy behavior and requirements.

Requires a loaded source. Returns an ExecutionResult plus:

Result fieldTypePresenceMeaning
querystringAlwaysOriginal question.
textstringAlwaysSummary, or empty when disabled.
markdownstringOptionalMarkdown content.
sqlstringOptionalExecuted query or DSL; the property name is retained for non-SQL engines.

translate

translate(query: string): Promise<string>

ParameterTypeRequiredMeaning
querystringYesNatural-language question.

Requires a loaded source. Returns generated DSL without executing it; use query() to execute that string.

query

query(dsl: string, options?: ExecutionOptions): Promise<ExecutionResult>

ParameterTypeRequiredDefault / behavior
dslstringYesExecutable statement in the selected engine's language.
optionsExecutionOptionsNoDefault execution limits below.
options.maxRowsnumberNo200.
options.maxResultBytesnumberNo1048576 bytes.

Requires a loaded source. Does not generate or summarize a query with the model.

ExecutionOptions

FieldTypeDefaultAccepted values / behavior
maxRowsnumber200Rounded down and bounded to 1–1000000; values outside the safe integer range after rounding use the default.
maxResultBytesnumber1048576 (1 MiB)Finite values are rounded down and clamped to at least 1; non-finite values use the default.

These limits bound returned data; they are separate from engine execution timeouts.

ExecutionResult

FieldTypePresenceMeaning
schemaQueryColumn[]AlwaysReturned column metadata.
schema[].namestringAlwaysColumn name.
schema[].typestringOptionalNative type name, if available.
dataT[]AlwaysReturned rows.
truncatedtrueWhen truncatedResult was bounded.
truncatedBy'maxRows' / 'maxResultBytes'When truncatedLimit that stopped the result.
rowCountnumberWhen knownRow count when execution reaches the end of the result.

suggest

suggest(count?: number): Promise<SuggestResult[]>

ParameterTypeRequiredDefault / behavior
countnumberNo3; requested number of questions.

Requires a loaded source. Returns suggestions sorted by descending score, each with query: string, score: number (0–1), and reason: string.

Visualization

visualize and recommend

visualize(analysisResult): Promise<VisualizeResponse | null>

recommend(analysisResult): Promise<ChartSpec | null>

Both methods accept the same input:

ParameterTypeRequiredMeaning
analysisResultPick<AnalysisResponse, 'query' | 'data'>YesAn analysis result or an object containing the two fields below.
analysisResult.querystringYesQuestion or visualization intent.
analysisResult.dataRecord<string, unknown>[]YesRows to visualize.

Neither requires a loaded source. Both use the model and return null for empty data or when no chart is recommended. Generation errors propagate. recommend() returns a ChartSpec; visualize() additionally returns html: string containing a standalone chart page.

viz

viz(spec: ChartSpec): Promise<string>

ParameterTypeRequiredMeaning
specChartSpecYesChart specification.
spec.chartTypeChartTypeYesOne of the chart types below. Part of the shared spec; the current renderer uses config directly.
spec.configChartConfigYesGPT-Vis JSON config to embed in HTML; config.type matches chartType.

ChartType values: line, column, bar, pie, area, scatter, dual-axes, histogram, boxplot, radar, funnel, waterfall, liquid, word-cloud, violin, venn, treemap, sankey, table, summary.

Returns a standalone HTML string. Does not require a loaded source or call a model. See chart specifications.

Cleanup

dispose

dispose(): Promise<void> takes no parameters. Releases the current engine and clears the schema, profile, and semantic definitions. Await it in a finally block.

Semantic model reference

Semantic fields

All six top-level fields are optional. Supply only the sections your application needs. Names and required expressions must be nonempty strings. properties contains JSON values with finite numbers; keys such as description, unit, synonyms, and owner are application conventions, not built-in SDK behaviors.

FieldShapePurpose
descriptionstringShared business context, terminology, eligibility, and time conventions.
propertiesRecord<string, JsonValue>Shared annotations.
modelsModel definitions belowPhysical and logical datasets, column meanings, and source mappings.
relationshipsRelationship definitions belowJoins between named models.
viewsView definitions belowReusable named SQL queries.
cubesCube definitions belowMeasures, grouping expressions, and drill-down paths.

Semantic models

FieldRequiredMeaning
nameYesLogical model name; matches a schema model by name or adds a new one.
tableReferenceOne source selector{ table, schema?, catalog? }; physical identifiers, independent of the logical name. Extra source attributes must be JSON values.
refSqlOne source selectorSQL defining the source rows before column mappings and calculations.
baseObjectOne source selectorName of another model or view supplying the rows.
columnsNoColumn definitions below; unlisted existing columns are retained.
primaryKeyNoOne column name or a nonempty ordered array for a composite key.
uniqueKeysNoArray of keys, each a column name or a nonempty composite-key array.
dialectNoSQL dialect for refSql; otherwise use the execution context.
propertiesNoModel annotations, especially row grain and business purpose.

A primary or unique key is a declaration, not an observed statistic. Verify it against the source. primaryKey: ['tenant_id', 'order_id'] is one composite key. uniqueKeys: ['email', ['tenant_id', 'external_id']] declares two alternative unique keys.

Semantic columns

FieldRequiredMeaning
nameYesName within the owning model; used to match existing columns.
typeYesDeclared type, or target model name for a relationship column.
propertiesNoColumn context such as description, units, enum meanings, or null conventions.
expressionNoSQL mapping or calculation over the source; null or omission supplies none.
isCalculatedNoBoolean marking a derived column; does not compute it.
isPrimaryKeyNoBoolean marking membership in the declared primary key.
notNullNoDeclared non-null constraint; omission is unspecified.
relationshipNoRelationship identifier for navigation, not a foreign-key column name.

Semantic relationships and views

FieldRequiredMeaning
relationships[].nameYesIdentifier, also used by column navigation.
relationships[].modelsYesExactly two model names, ordered first to second.
relationships[].joinTypeYesONE_TO_ONE, ONE_TO_MANY, MANY_TO_ONE, or MANY_TO_MANY.
relationships[].conditionYesSQL join predicate with qualified columns.
relationships[].propertiesNoBusiness context for the relationship.
views[].nameYesLogical name for the query.
views[].statementYesSQL defining the result; saving it does not execute it.
views[].dialectNoSQL dialect; otherwise use the execution context.
views[].propertiesNoPurpose and business conventions.

Relationships and views accept additional JSON-valued attributes whose meaning is agreed on by your application and consumers.

Semantic cubes and expressions

FieldRequiredMeaning
nameYesCube identifier.
baseObjectYesModel or view supplying rows to aggregate.
measuresYesNonempty array of aggregation definitions.
dimensionsNoGrouping definitions.
timeDimensionsNoDate/time grouping definitions; granularity is chosen at query time.
hierarchiesNoMap of names to nonempty dimension-name arrays, ordered coarsest to finest.
propertiesNoCube annotations.

Each entry in measures, dimensions, and timeDimensions uses the same fields:

FieldRequiredMeaning
nameYesExpression identifier within the cube.
expressionYesSQL aggregation for a measure, grouping expression for a dimension.
typeYesDeclared result type.
descriptionNoBusiness meaning of the expression.
propertiesNoAnnotations such as units or synonyms.

For a calendar drill-down, define dimension expressions for year, month, and order_date, then declare hierarchies: { calendar: ['year', 'month', 'order_date'] }. A hierarchy describes a path; it does not generate those fields.

Model, column, cube, and expression objects reject unknown fields; put application annotations in properties where supported.

Semantic model sources

Call schema() and inspect model names, source references, and column types before writing mappings. Names match exactly within their owning model. The inline JSON source in the sales example is exposed as data; other sources can have different names and catalog or schema qualifiers.

Every entry in models needs a name and exactly one source selector, even when you only want to add a description to an existing model:

SelectorUse it whenExample
tableReferenceThe model maps to a physical table or database view. Retain the discovered qualifiers.{ tableReference: { schema: 'public', table: 'orders' } }
refSqlSQL defines the source rows of a logical model.{ refSql: "SELECT * FROM orders WHERE status = 'paid'" }
baseObjectAnother model or declared view supplies the source rows.{ baseObject: 'paid_orders' }

Use the existing schema model's name to enrich it. A different name adds a logical model; it does not rename the underlying table. A column needs both name and type, including when adding only a description. Copy the discovered type for physical columns; specify the result type for calculations.

baseObject, refSql, and column expression describe mappings for the query generator. A logical name is not automatically executable in query(). For example, a query using a calculated net_amount must inline its expression or define it in a subquery or CTE.

Semantic join and view examples

Add relationships when analysis spans more than one model. Add views when a reusable SQL definition makes business logic clearer. These snippets assume an existing source exposing orders and customers; they are separate from the single-table sales example.

Relationship example

typescript
import type { Semantic } from '@antv/ava';
 
const semantic = {
  relationships: [{
    name: 'order_customer',
    models: ['orders', 'customers'],
    joinType: 'MANY_TO_ONE',
    condition: 'orders.customer_id = customers.id',
    properties: { description: 'Each order belongs to one customer.' },
  }],
} satisfies Semantic;

models is an ordered pair. MANY_TO_ONE means many rows in the first model can match one row in the second. joinType describes cardinality; it does not choose LEFT JOIN or INNER JOIN. The join condition must include all parts of a composite key.

If you expose a relationship navigation column, set its relationship to the relationship's name , and its type to the target model name, for example { name: 'customer', type: 'customers', relationship: 'order_customer' }. The physical foreign-key column remains customer_id.

Check grain before aggregating across a join. Joining one order to many line items can repeat the order amount. A cardinality declaration supplies context; AVA does not verify uniqueness or automatically prevent double counting.

View and derived model example

typescript
import type { Semantic } from '@antv/ava';
 
const semantic = {
  views: [{
    name: 'paid_orders',
    statement: "SELECT * FROM orders WHERE status = 'paid'",
    dialect: 'duckdb',
    properties: { description: 'Paid orders only; this excludes fully refunded orders.' },
  }],
  models: [{
    name: 'paid_sales',
    baseObject: 'paid_orders',
    properties: { description: 'One row per paid order.' },
  }],
} satisfies Semantic;

Here a logical model references a named query. A generator can expand that query as a CTE or subquery. await ava.query('SELECT * FROM paid_orders') only works if that name already exists in the execution engine; saving this definition does not create it. A model's refSql can describe its source query directly when a separate named view is unnecessary.

Save and combine semantic definitions

Keep one complete definition in your application, version it alongside the source it describes, and pass it to AVA after source(). Calling the setter replaces the saved semantic object. It does not append definitions or patch the previous object.

typescript
await ava.semantic(undefined, () => completeDefinitions);
const saved = await ava.semantic();
await ava.semantic(undefined, () => ({})); // Clear all saved semantics.

Definitions can live in code or in an application-owned JSON file. For example, after loading a source in Node.js:

javascript
const { readFile } = require('node:fs/promises');
const definitions = JSON.parse(await readFile('./sales-semantic.json', 'utf8'));
await ava.semantic(undefined, () => definitions);

The JSON file contains the definition object, without the JavaScript variable declaration or setter. AVA accepts an object, not a file path; if you store YAML, parse it in your application before calling the setter. Reading and parsing the file can happen asynchronously before the setter returns the object.

When an operation needs its data model, AVA combines the inputs in this order:

CombinationBehavior
Schema, then profileObservations attach to existing models and columns by name.
Semantic modelsMatching names enrich the model; new names add logical models. A supplied source selector takes precedence.
Semantic columnsMatching names enrich columns; new names add columns. Unlisted models, columns, and profile metrics remain available. An empty column list does not remove discovered columns.
Model and column propertiesMerge by key; semantic values win for matching keys. Nested JSON values are replaced as values, not recursively merged.
Other supplied model and column fieldsSemantic values replace corresponding fields, including types and key declarations.
Top-level fieldsSupplied values replace their counterparts. In particular, relationship and view arrays are replaced as complete lists; [] clears that list in the combined context.

Omitting a section retains the corresponding schema context. If adding a relationship alongside discovered foreign keys, include the discovered relationships you want to keep in the supplied list. Reading schema(), profile(), or semantic() still returns that input, not the combined model; there is no public method to read the merged DataModel.

Changing the schema clears the saved profile and retains semantic definitions. Profiling replaces observations and retains semantic definitions. Loading another source or calling dispose() clears all three. Reapply your saved definition after loading a new source, and review mappings if its structure changed. Calls require a loaded source; a failed source replacement leaves no active source.

The setter validates and copies its returned object. A validation failure or thrown error leaves the previous semantic definition in place.

Semantic validation

Structural validation checks field shapes, required fields, source-selector exclusivity, and nonempty measure lists. It does not prove that SQL is valid, referenced objects exist, key declarations hold, units are consistent, or business rules are correct. Duplicate semantic model names and duplicate column names within a model are rejected when building the combined model for analysis, translation, or suggestions, rather than by the setter alone.

Use the sales example’s pattern for your own definition:

  1. Inspect schema() and map exact names and physical types. For remote sources, preserve catalog and schema qualifiers.
  2. Have the business owner review grain, eligible statuses, null handling, units, and time meaning.
  3. Run each declared expression against a small fixture with known answers. Include excluded rows, nulls, refunds, and join duplication where relevant.
  4. Inspect translate() output for those same questions, then compare executed results with the known answers. A successful setter is not a successful end-to-end check.
  5. Repeat the checks when the source schema or business definitions change.
SymptomWhat to check
Setter rejects a modelInclude exactly one of tableReference, refSql, or baseObject; columns need name and type.
Setter rejects a cubeInclude baseObject and at least one measure with name, expression, and type.
Setter rejects statisticsPut model and column metrics in profile(), not semantic().
Query says a logical name does not existCheck whether the SQL expands its declared expression, view, or model into executable SQL.
A discovered join disappearsYour relationship list replaced the discovered list. Include all joins you still need.
Numbers are inflatedCheck row grain, join cardinality, duplicate keys, eligibility filters, and refund treatment.
A rule is ignoredInspect the generated query. Enforce mandatory access rules in the data or execution layer.