Embed AskDB in a Node app
Integrator guide
Drop @askdb/core into a TypeScript service. AskDB loads your schema artifact, generates validated SQL from a question, and hands it back. Your service runs it through its own connection pool against a read-only role.
Install
Section titled “Install”npm install @askdb/core @ai-sdk/openai pgpnpm add @askdb/core @ai-sdk/openai pgyarn add @askdb/core @ai-sdk/openai pg| Package | Why |
|---|---|
@askdb/core | The pipeline — loadSchema, ask, validation. |
| — | Dialects for all four engines are built into @askdb/core; install @askdb/postgres only if this service also runs askdb introspect programmatically. |
@ai-sdk/openai | OpenAI’s AI SDK provider — bring your own model provider. |
pg | The Postgres driver. AskDB doesn’t open the connection; your app does. |
Load the schema once
Section titled “Load the schema once”The schema artifact is read from disk. Load it at startup and keep it in memory — it doesn’t need to be reloaded per request.
import { loadSchema } from "@askdb/core";
// Point at the artifact directory that `askdb introspect` wrote —// your `introspection.outputDir` (e.g. ./my-app.schema or the default ./askdb).// loadSchema also accepts a bundled .bundle.json file.export const schema = await loadSchema("./my-app.schema");./my-app.schema is a directory, not a file — <name>.schema/ is AskDB’s convention for the introspected-and-enriched artifact. loadSchema autodetects a directory, a bundled JSON, or a bare schema.json.
Wire ask() into a handler
Section titled “Wire ask() into a handler”import { ask } from "@askdb/core";import { openai } from "@ai-sdk/openai";import { Pool } from "pg";import { schema } from "./schema.js";
const model = openai("gpt-4o-mini");
const pool = new Pool({ connectionString: process.env.DATABASE_URL, // Run under a read-only role for defense in depth. statement_timeout: 5000, max: 10,});
export async function askQuestion(question: string) { const { sql } = await ask({ question, schema, dialect: "postgres", model, });
// Audit hook — log every question and generated SQL. console.log({ question, sql });
const { rows } = await pool.query(sql); return { sql, rows };}That’s the whole pipeline. AskDB returns validated SQL — your handler logs it, runs it, and returns the result.
Shorter: let config resolve schema + model
Section titled “Shorter: let config resolve schema + model”If you already use askdb.config.ts, @askdb/client removes the manual schema load and model construction. createAskDb resolves both from config; you pass only the question.
npm install @askdb/client @askdb/ai @askdb/ai-openai @askdb/config pgimport { createAskDb } from "@askdb/client";import { getAskDbRuntimeConfig } from "@askdb/config";import { createAiRegistry } from "@askdb/ai";import { openaiProvider } from "@askdb/ai-openai";import { Pool } from "pg";
const askdb = createAskDb({ config: getAskDbRuntimeConfig(), // after bootstrapAskDbEnv() at startup registry: createAiRegistry([openaiProvider]), schema: { path: "./my-app.schema" }, // or set host.schemaPath in config and omit});
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
export async function askQuestion(question: string) { const { sql } = await askdb.ask(question); const { rows } = await pool.query(sql); return { sql, rows };}Switching engines
Section titled “Switching engines”Same ask() call, different dialect string. Change dialect: "postgres" to "mysql", "sqlite", or "sqlserver". See Switch engines for the full migration matrix.
Read next
Section titled “Read next”© 2026 Yahya Gilany