@nightowlsdev/provider-openai
Adapter/ModelOpenAI model provider for Night Owls swarms, backed by the native AI SDK.
What it does
Exposes `openaiModels(opts?)`, a model factory for `defineSwarm({ modelFactory })`. It wraps `@ai-sdk/openai`'s `createOpenAI`, mapping a model id (e.g. `gpt-4o`) to an AI SDK `LanguageModelV3`. Reads `OPENAI_API_KEY` from the environment by default; pass `{ apiKey }` to override. Also exports a declarative `nightOwlsPlugin` manifest for CLI scaffolding of env/config; model providers compose, so this adapter can sit alongside the other `provider-*` packages and be routed per agent by `createModelFactory`.
Install
pnpm add @nightowlsdev/provider-openaiKey exports
- openaiModels
- nightOwlsPlugin
Usage
import { defineSwarm } from "@nightowlsdev/core";
import { openaiModels } from "@nightowlsdev/provider-openai";
// Reads OPENAI_API_KEY from the env by default.
const swarm = defineSwarm({ agents, modelFactory: openaiModels() });What it provides
A one-line model provider for Night Owls: openaiModels() returns a modelFactory you hand to defineSwarm, mapping an OpenAI model id (gpt-5, gpt-4.1, gpt-4o-mini, …) to an AI SDK LanguageModelV3 via the native @ai-sdk/openai. It reads OPENAI_API_KEY (pass { apiKey } to override). Uniquely among the native adapters it also ships openaiEmbeddings() — an embedding-model factory from the SAME provider, with authoritative output-dimension pinning so your vectors always match the pgvector column — plus openaiProvider() (the adapter-object form with a priced catalog). One of six interchangeable provider-* packages that compose via createModelFactory.
When to use it
- You want GPT models directly — native SDK, cached-input pricing, big context (gpt-4.1 ~1M tokens) or a cheap tool-calling workhorse (gpt-4o-mini).
- You need an EMBEDDING model for RAG or swarm memory from the same adapter you already installed — openaiEmbeddings pins the dimension to your vector column, even through Mastra memory recall.
- You have a direct OpenAI billing relationship and want provider-qualified allow-list entries (openai:*) priced from the shipped snapshot.
When not to
- You want one key to reach many vendors — use provider-vercel-gateway (live pricing) or provider-openrouter.
- You want the cheapest / fastest inference, or local-and-free — route those agents to provider-groq or provider-ollama.
- You need a runtime model listing in the picker — @ai-sdk/openai exposes none, so this adapter is catalog-only (canList is honestly false).
Alternatives
- provider-vercel-gatewayYou want GPT plus every other vendor behind one key, with a live listing and per-model pricing.
- provider-openrouterYou want GPT alongside hundreds of other models via provider/model ids and one key.
- provider-anthropicYou want Claude directly instead of (or alongside, via createModelFactory) GPT.
- provider-groq / provider-ollamaThe step is high-volume and cost/latency-bound; use fast hosted or free local open models for those agents.
Strengths
- Native @ai-sdk/openai — full features (vision, tool calling, cached-input pricing) with no routing hop.
- Ships an embedding factory (openaiEmbeddings / pinEmbeddingDimensions) with AUTHORITATIVE dimension pinning: a stray caller can't override the size and mismatch your pgvector column.
- A priced catalog (gpt-5 / -mini, gpt-4.1, gpt-4o / -mini) feeds openai:* expansion, the picker, and cost.maxCostUsd.
- Engine-wall clean: one dependency, zero @mastra and zero @nightowlsdev/core.
Limits & trade-offs
- No runtime model listing (catalog-only, canList false) — the small hand-curated catalog is the whole picker input.
- Prices are a snapshot (2026-07-27); a new or untranscribed model is unpriced and dropped by openai:* unless you supply cost.prices or pass allowUnpriced.
- A single vendor: compose other provider-* packages with createModelFactory to spread cost and latency across tasks.
How it works
openaiModels(opts) calls createOpenAI and returns a (modelId) => provider(modelId) factory — the AI SDK LanguageModelV3 the engine drives, reading OPENAI_API_KEY when no apiKey is passed. openaiEmbeddings(opts) builds provider.embedding(model); when you set dimensions it wraps the model with pinEmbeddingDimensions, a Proxy that injects providerOptions.openai.dimensions on every doEmbed call — so the output vector size is fixed even where the call site (a host caller, or Mastra memory recall) wouldn't pass it. openaiProvider() is the adapter-object form for createModelProviderRegistry: the same .model factory plus a static priced catalog and no models() (the SDK has no listing).
Examples
Wire OpenAI into a swarm
One factory for every agent; the key comes from OPENAI_API_KEY.
import { defineSwarm } from "@nightowlsdev/core";
import { openaiModels } from "@nightowlsdev/provider-openai";
export default defineSwarm({
modelFactory: openaiModels(), // reads OPENAI_API_KEY
models: { allow: ["gpt-4o"] },
agents,
});An embedder for swarm semantic-recall memory
Same adapter as your chat model; dimensions pins the vector to your pgvector column. store + vector are the required memory infra.
import { openaiEmbeddings } from "@nightowlsdev/provider-openai";
import { createMastraPgStore, createMastraVectorStore } from "@nightowlsdev/storage-supabase";
const memory = {
store: createMastraPgStore({ dbUrl }),
vector: createMastraVectorStore({ dbUrl }),
embedder: openaiEmbeddings({ model: "text-embedding-3-small", dimensions: 1536 }),
semanticRecall: true,
};
// pass as defineSwarm({ modelFactory, memory, agents })Register the adapter for a model picker
openaiProvider() contributes its priced catalog; providers compose in the registry.
import { createModelProviderRegistry } from "@nightowlsdev/core";
import { openaiProvider } from "@nightowlsdev/provider-openai";
import { anthropicProvider } from "@nightowlsdev/provider-anthropic";
const registry = createModelProviderRegistry({
providers: [openaiProvider(), anthropicProvider()],
});Doing the parts it doesn't support
- Listing available OpenAI models at runtime@ai-sdk/openai has no listing endpoint, so this adapter is catalog-only. Treat the shipped catalog as the source, or front OpenAI through provider-vercel-gateway, whose adapter has a live models().
- Per-task embedding-model routingUse createEmbeddingFactory (core) over openaiEmbeddings (and openrouterEmbeddings) to pick a different embedder per key, each dimension-pinned to its column.
- Mixing GPT with other vendors per agentWrap openaiModels() and the other provider factories in createModelFactory with a resolve() mapping each agent slug to a { provider, modelId } route, and list the routed ids in allow.
Related
- core — defineSwarm / modelFactory consume the factory; createModelFactory and createEmbeddingFactory compose it.
- provider-openrouter — The other adapter that ships an embedder, plus one key to hundreds of models.
- provider-vercel-gateway — Reach GPT plus every vendor through one key, with a live listing and per-model pricing.
- knowledge-and-tools — The RAG / knowledge surface an OpenAI embedder feeds.
- model-providers — The guide to registering providers, provider-qualified allow-lists, and pricing.