Skip to content
Night Owls.dev
Jump to a page

@nightowlsdev/provider-openai

Adapter/Model

OpenAI 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-openai

Key exports

  • openaiModels
  • nightOwlsPlugin

Usage

provider-openai.ts
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.

provider-openai-example-1.ts
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.

provider-openai-example-2.ts
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.

provider-openai-example-3.ts
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

  • coredefineSwarm / modelFactory consume the factory; createModelFactory and createEmbeddingFactory compose it.
  • provider-openrouterThe other adapter that ships an embedder, plus one key to hundreds of models.
  • provider-vercel-gatewayReach GPT plus every vendor through one key, with a live listing and per-model pricing.
  • knowledge-and-toolsThe RAG / knowledge surface an OpenAI embedder feeds.
  • model-providersThe guide to registering providers, provider-qualified allow-lists, and pricing.