Events report what AVA is doing while an operation runs. You can use them to show progress, inspect generated queries, or diagnose failures. The operation’s return value contains its final result.
Subscribe to events
Register a listener before starting the operation. Subscribe to a specific event by name, or use '*' to listen to all events:
import { AVA } from '@antv/ava';
const ava = new AVA({ llm: { model: 'your-model' } });
const listener = (event) => console.log(event.type, event.data);
ava.on('*', listener);
try {
await ava.source({ type: 'json', options: { data: [{ sales: 120 }] } });
} finally {
ava.off('*', listener);
await ava.dispose();
}Use the same listener reference to unsubscribe. Event classes and constants are not exported by the public package, so use the event names listed on this page as strings.
Read an event
Every AVA event has a lowercase type and a data object. For example, the sourcestart event above contains { type: 'json' } in data. Analysis events emitted within analyze() also carry context, which identifies their step and pairs related start and end events.
An operation usually emits a start event and then an end event. A failed end event carries data.error with a message and, for an Error, a name. Some failures are recoverable: a query can fail and be retried, so queryend may report an error even if analyze() eventually succeeds. An unrecovered failure rejects the operation. A precondition failure, such as calling analyze() before loading a source, can occur before its start event.
Event reference
Lifecycle events
These events describe AVA operations. On success, end-event data is {}; the method returns the result separately.
| Operation | Start event and data | End event |
|---|---|---|
| Create an engine | createstart: {} | createend |
| Dispose an engine | disposestart: {} | disposeend |
| Load a source | sourcestart: { type } | sourceend |
| Discover or set schema | schemastart: {} | schemaend |
| Compute or set profile | profilestart: {} | profileend |
| Set semantic definitions | semanticstart: {} | semanticend |
| Analyze a question | analyzestart: { query } | analyzeend |
| Visualize a result | visualizestart: { query } | visualizeend |
| Suggest questions | suggeststart: {} | suggestend |
Loading a source can also emit engine disposal and creation events. Cached schema reads and semantic reads emit no events; schema discovery performed internally by other methods does not emit schema events. recommend() and viz() do not have their own events.
Analysis events
These events describe analysis steps and the statements they produce or execute. The table shows successful end-event data; on failure, the end event carries error instead. A failed step also carries step and, when applicable, finalAttempt. A question is natural language; dsl is an executable statement, such as SQL or Python code.
| Operation | Start event and data | Successful end event and data |
|---|---|---|
| Analysis step | stepstart: { step, finalAttempt? } | stepend: { step, action, text, usage?, finalAttempt? } |
| Translate a question | translatestart: { query, attempt? } | translateend: { dsl, usage? } |
| Execute a statement | querystart: { dsl } | queryend: { data, schema, rowCount?, truncated?, truncatedBy? } |
| Summarize a result | summarizestart: { queryId } | summarizeend: { queryExplanation, conclusion, limitations?, nextStep?, usage? } |
? marks an optional field. In queryend, data contains the returned rows and schema describes their columns; truncation fields indicate when a result limit was reached. See query results for the full result structure.
step and attempt are zero-based. attempt is present on translation starts within analysis. finalAttempt marks an additional step after the normal step limit. Step actions are EXPLORE (inspect data), REFINE (revise the plan), SQL (execute an answer statement), and CONFIRM (verify the answer). The text field does not include the leading action tag.
Where present, usage describes token usage for the model call. A step can retain usage when parsing or execution fails after the model has returned. Token fields depend on the provider, and a failed call that returns no usage cannot be counted from the events. AVA does not emit an aggregate usage event. queryend describes execution and carries no model usage.
Event context
Analysis events emitted within analyze() include a context object:
| Field | Meaning |
|---|---|
eventId | Unique event ID. A start/end pair shares an ID prefix and uses :start and :end suffixes. |
stepId | ID of the step containing the event. |
parentStepIds | IDs of steps that this step depends on. |
Step event IDs use stepId as their prefix; operations within a step have separate pair IDs. Each retry gets a new pair. summarizestart.data.queryId references the successful queryend.context.eventId, including :end. Standalone translate() and query() emit their respective events without analysis context or step events.
Listener parameters
| Method | Behavior |
|---|---|
on(name, listener, once?) | Subscribe; the optional once flag defaults to false. |
once(name, listener) | Subscribe for one invocation. |
off(name?, listener?) | Remove a listener, all listeners for a name, or all listeners if omitted. Pass the same listener reference used to subscribe. |
emit(name, ...args) | Emit an event manually. |
getEvents() | Return the listener registry. |
Event dispatch is synchronous: on, once, and off return the emitter, synchronous listener errors propagate, and async listeners are not awaited. Event data is not copied; use structuredClone(event) if you need a snapshot.