Bring your own model
Model providers
AskDB doesn’t host inference. You wire a model in, AskDB calls it, and the model’s response goes back through your provider — billed to your account.
Two ways to wire a model
Section titled “Two ways to wire a model”| What you do | Best for | |
|---|---|---|
| In your config | Set ai.provider in askdb.config.ts. The CLI, Studio, and the HTTP API resolve the model for you. No model code. | CLI workflows, Studio, the bundled HTTP service |
| In your code | Pass any Vercel AI SDK LanguageModel to ask(). Full control. | Embedding @askdb/core in your own service |
With @askdb/client | Call createAskDb({ config, providers }) then askdb.ask("question"). Schema, model, and dialect come from config. | The shortest config-driven embed — one schema, one model |
Same providers, same keys — pick per surface. You can use both in one project (for example: Studio uses your config, your embedding service constructs the model directly).
Which should I use?
Section titled “Which should I use?”ask()’s actual contract is model: LanguageModel — a plain Vercel AI SDK model object. Every path below ends up building one of those; @askdb/ai-* and @askdb/client are a convenience layer on top, not a separate mechanism. Neither path is more “correct.” Pick based on who owns provider configuration:
- Use
@askdb/ai-*+@askdb/clientwhen you wantaskdb.config.tsto drive provider/model selection — one config file, no provider code, and the CLI/Studio/your app all resolve the same way. This is the right default when you’re embedding AskDB as a standalone service and don’t already have a provider-config system. - Construct a
LanguageModeldirectly with the AI SDK when your app already owns provider/config resolution (env vars, a secrets manager, feature flags), or when you need to reuse the same model instance for calls AskDB doesn’t make — for example, a separategenerateObject()call for chart planning that sits next toask()in your service.@askdb/ai’s registry only resolves models for AskDB’s own config shape, so if you need the model object for other LLM calls too, building it with the AI SDK directly is usually less code, not more.
If you’re an agent implementing this integration: check whether the host app already constructs AI SDK models elsewhere before reaching for @askdb/ai-* — duplicating provider config across two systems is the failure mode to avoid.
In your config (CLI, Studio, HTTP API)
Section titled “In your config (CLI, Studio, HTTP API)”Set ai.provider in askdb.config.ts and supply the matching env var. The CLI, Studio, and the HTTP service call createLanguageModelFromEnv internally.
export default { ai: { provider: "openai", providerConfig: { openai: { apiKey: env("OPENAI_API_KEY"), }, }, }, // ...};Default model: gpt-4o-mini. To use a different one, set model in providerConfig.openai (the scaffolded config reads it from OPENAI_MODEL).
export default { ai: { provider: "anthropic", providerConfig: { anthropic: { apiKey: env("ANTHROPIC_API_KEY"), }, }, }, // ...};Default model: claude-sonnet-4-6. To use a different one, set model in providerConfig.anthropic (bind it to ANTHROPIC_MODEL in your config).
export default { ai: { provider: "google", providerConfig: { google: { apiKey: env("GOOGLE_GENERATIVE_AI_API_KEY"), }, }, }, // ...};export default { ai: { provider: "azure", providerConfig: { azure: { apiKey: env("AZURE_API_KEY"), resourceName: env("AZURE_RESOURCE_NAME"), }, }, }, // ...};Set model in providerConfig.azure to your deployment name (the scaffolded config reads it from AZURE_OPENAI_DEPLOYMENT).
See the Configuration reference for the full env-var table and the custom-provider escape hatch.
In your code (embedding)
Section titled “In your code (embedding)”When you embed @askdb/core directly, pass any Vercel AI SDK LanguageModel to ask(). AskDB calls the model with the assembled prompt and parses the SQL it returns. No proxy. No middleman.
import { ask } from "@askdb/core";
const { sql } = await ask({ question, schema, dialect: "postgres", model, // any LanguageModel from the Vercel AI SDK});Install the provider package and construct the model:
npm install ai @ai-sdk/openaipnpm add ai @ai-sdk/openaiyarn add ai @ai-sdk/openaiimport { openai } from "@ai-sdk/openai";
// Reads OPENAI_API_KEY from the environmentconst model = openai("gpt-4o-mini");npm install ai @ai-sdk/anthropicpnpm add ai @ai-sdk/anthropicyarn add ai @ai-sdk/anthropicimport { anthropic } from "@ai-sdk/anthropic";
const model = anthropic("claude-sonnet-4-6");npm install ai @ai-sdk/googlepnpm add ai @ai-sdk/googleyarn add ai @ai-sdk/googleimport { google } from "@ai-sdk/google";
// Reads GOOGLE_GENERATIVE_AI_API_KEY from the environmentconst model = google("gemini-2.0-flash");npm install ai @ai-sdk/azurepnpm add ai @ai-sdk/azureyarn add ai @ai-sdk/azureimport { createAzure } from "@ai-sdk/azure";
const azure = createAzure({ resourceName: process.env.AZURE_RESOURCE_NAME, apiKey: process.env.AZURE_API_KEY,});
const model = azure("your-deployment-name");For self-hosted or alternative providers that expose the OpenAI chat-completions shape (vLLM, llama.cpp server, OpenRouter, Together, LM Studio, Ollama, …):
npm install ai @ai-sdk/openai-compatiblepnpm add ai @ai-sdk/openai-compatibleyarn add ai @ai-sdk/openai-compatibleimport { createOpenAICompatible } from "@ai-sdk/openai-compatible";
const local = createOpenAICompatible({ name: "local", baseURL: "http://localhost:11434/v1", apiKey: "ignored-by-local-server",});
const model = local("llama3.1");One config driving both
Section titled “One config driving both”If you embed AskDB but want to reuse the same askdb.config.ts instead of hardcoding a provider, use @askdb/client. createAskDb resolves the schema, model, and dialect from your config and the adapters you pass — the same resolution the CLI and the bundled HTTP API use.
npm install @askdb/client @askdb/config @askdb/ai-openai @askdb/ai-anthropicpnpm add @askdb/client @askdb/config @askdb/ai-openai @askdb/ai-anthropicyarn add @askdb/client @askdb/config @askdb/ai-openai @askdb/ai-anthropicimport { createAskDb } from "@askdb/client";import { bootstrapAskDbEnv, getAskDbRuntimeConfig } from "@askdb/config";import { openaiProvider } from "@askdb/ai-openai";import { anthropicProvider } from "@askdb/ai-anthropic";
bootstrapAskDbEnv({ cwd: process.cwd() });
const askdb = createAskDb({ config: getAskDbRuntimeConfig(), providers: [openaiProvider, anthropicProvider], // whichever ai.provider the config selects schema: { path: "./my-app.schema" }, // or set host.schemaPath in config and omit this});
// Only the question — schema, model, and dialect come from config.const { sql } = await askdb.ask("Which customers signed up last week?");Need the model object yourself (to pass to ask() directly, or to share with other code)? Build it from the same config with @askdb/ai’s registry — the one advanced case where you import @askdb/ai directly:
import { bootstrapAskDbEnv, getAskDbRuntimeConfig } from "@askdb/config";import { createAiRegistry } from "@askdb/ai";import { openaiProvider } from "@askdb/ai-openai";
bootstrapAskDbEnv({ cwd: process.cwd() });const rt = getAskDbRuntimeConfig();const ai = createAiRegistry([openaiProvider]);const model = await ai.createLanguageModelFromEnv(rt.ai.aiEnv);Adapters declare ai and @askdb/ai as peer dependencies — add ai to your own package.json when you want to pin its version.
Reasoning/latency effort
Section titled “Reasoning/latency effort”Set ai.reasoning in askdb.config.ts (see the config reference) for the config-driven path. Skip it and current behavior is unchanged — no providerOptions are sent, and the provider/model uses its own default.
With @askdb/client, createAskDb resolves ai.reasoning.nlToSql/effort automatically — nothing else to wire. Override per call, or set a client-level default:
const askdb = createAskDb({ config: getAskDbRuntimeConfig(), providers: [openaiProvider], reasoningEffort: "medium", // client-level default, overrides ai.reasoning from config});
const { sql } = await askdb.ask("Which customers signed up last week?", { reasoningEffort: "low", // per-call override, overrides the client default});Programmatically, resolve the portable effort to provider providerOptions with @askdb/ai’s registry, then forward it to ask()’s deps.providerOptions — @askdb/core forwards it verbatim to generateText and never interprets it:
import { createAiRegistry } from "@askdb/ai";import { openaiProvider } from "@askdb/ai-openai";import { ask } from "@askdb/core";
const ai = createAiRegistry([openaiProvider]);const config = ai.resolveAiConfig(rt.ai.aiEnv)!; // e.g. { provider: "openai", model: "o4-mini", ... }const model = await ai.createLanguageModel(config);
// Provider-portable: "minimal" | "low" | "medium" | "high".// Returns undefined (nothing sent) when the model doesn't support reasoning tuning.const providerOptions = ai.resolveProviderOptions(config, { reasoningEffort: "low" });
const { sql } = await ask({ question, schema, dialect: "postgres", model, deps: { providerOptions },});Key management
Section titled “Key management”Your model API key lives in your environment, not in the schema artifact and not in AskDB. The CLI loads .env for local work; in production, supply the key the same way you supply your database URL.
AskDB has no API of its own to authenticate — it’s a library. The only credentials it touches are the ones you pass to your model provider through the AI SDK.
Switching models
Section titled “Switching models”Models can be swapped without changing any other AskDB code. A common pattern: cheaper model for low-stakes analytics, stronger model for complex multi-join queries.
import { openai } from "@ai-sdk/openai";
const cheapModel = openai("gpt-4o-mini");const strongModel = openai("gpt-4o");
const model = question.length > 200 ? strongModel : cheapModel;
const { sql } = await ask({ question, schema, dialect: "postgres", model });You’re billed by your model provider for every ask() call. Cost scales with:
- Schema size (larger artifacts mean more tokens in the prompt) — use RAG for large schemas to send only the relevant slice. AskDB handles the chunking, embedding, and retrieval; you configure the store and it takes care of the rest.
- Question length.
- Model tier.
AskDB itself is Apache 2.0-licensed and free.
Read next
Section titled “Read next”© 2026 Yahya Gilany

