@nightowlsdev/provider-anthropic
Adapter/ModelAnthropic Claude model provider for Night Owls swarms, backed by the native AI SDK.
What it does
Exposes `anthropicModels(opts?)`, a model factory you pass to `defineSwarm({ modelFactory })` in `@nightowlsdev/core`. It wraps `@ai-sdk/anthropic`'s `createAnthropic`, mapping a model id (e.g. `claude-sonnet-4-6`) to an AI SDK `LanguageModelV3`. By default it reads `ANTHROPIC_API_KEY` from the environment; pass `{ apiKey }` to override. Also ships a declarative `nightOwlsPlugin` manifest the CLI uses to scaffold env/config. Model providers compose: install one `provider-*` package per provider you use, then route per agent with `createModelFactory` from `@nightowlsdev/core`.
Install
pnpm add @nightowlsdev/provider-anthropicKey exports
- anthropicModels
- nightOwlsPlugin
Usage
import { defineSwarm } from "@nightowlsdev/core";
import { anthropicModels } from "@nightowlsdev/provider-anthropic";
// Reads ANTHROPIC_API_KEY from the env by default.
const swarm = defineSwarm({ agents, modelFactory: anthropicModels() });What it provides
A one-line model provider for Night Owls: anthropicModels() returns a modelFactory you hand to defineSwarm, mapping a Claude model id (claude-sonnet-4-6, claude-haiku-4-5, …) to an AI SDK LanguageModelV3 backed by the native @ai-sdk/anthropic. It reads ANTHROPIC_API_KEY from the environment (pass { apiKey } to override), and also ships anthropicProvider() — the adapter-object form for the model registry, carrying a small hand-curated, priced catalog (Sonnet / Opus / Haiku 4.x with prompt-cache multipliers). It is one of six interchangeable provider-* packages: they compose, so you install one per vendor you use and route per agent with createModelFactory from core.
When to use it
- You want Claude directly — native SDK, no gateway hop — for the orchestrator or any step that needs strong tool-calling and long-context reasoning.
- You want prompt-caching accounted in your cost caps: the catalog carries the cache-read and cache-write multipliers, not just the base rates.
- You have a direct billing relationship with Anthropic and want provider-qualified allow-list entries (anthropic:*) priced from the shipped snapshot.
When not to
- You want one key to reach many vendors — use provider-vercel-gateway (one key, live pricing) or provider-openrouter (one key, hundreds of models).
- You want the cheapest or fastest inference for high-volume simple tasks — pair provider-groq (hosted, fast) or provider-ollama (local, free) for those agents.
- You need a runtime model listing in the picker — the Anthropic SDK exposes none, so this adapter is catalog-only (canList is honestly false).
Alternatives
- provider-vercel-gatewayYou want Claude AND every other vendor behind a single key, with a live model listing and per-model pricing feeding the picker and cost caps.
- provider-openrouterYou want Claude alongside hundreds of other models via provider/model ids and one key, and can live with an unpriced catalog.
- provider-groq / provider-ollamaThe step is high-volume and cost- or latency-bound; route those agents to fast hosted (Groq) or free local (Ollama) open models and keep Claude for the hard step.
Strengths
- Native @ai-sdk/anthropic — no extra routing hop, and full Claude features (vision, tool calling, prompt caching) come through.
- An honest priced catalog including the cache read/write multipliers, so anthropic:* expansion, the picker, and cost.maxCostUsd all see real numbers.
- Engine-wall clean: exactly one dependency, zero @mastra and zero @nightowlsdev/core — safe to tree-shake and compose.
Limits & trade-offs
- No runtime model listing: the SDK has none, so the small hand-curated catalog is the entire picker input for this provider.
- claude-sonnet-4-6 ships UNPRICED in the catalog (its rate post-dates the snapshot and the catalog refuses to guess), so anthropic:* drops it unless you supply a price or pass allowUnpriced.
- Prices are a snapshot (transcribed 2026-07-27), not a live feed — override via cost.prices / cost.priceFeed if you bill on them.
- A single vendor: for a real cost/latency spread across tasks you must compose other provider-* packages with createModelFactory.
How it works
anthropicModels(opts) calls createAnthropic and returns a (modelId) => provider(modelId) factory — the AI SDK LanguageModelV3 the engine drives. defineSwarm({ modelFactory }) uses that one factory for every agent; to send different agents to different vendors, wrap several factories in createModelFactory with a resolve() that maps an agent slug to a { provider, modelId } route. anthropicProvider() is the adapter-object form consumed by createModelProviderRegistry: the same .model factory plus a static catalog and, deliberately, no models() (the Anthropic SDK exposes no listing). The catalog's USD-per-million-token prices — including cache multipliers — feed the cost governor and the model picker.
Examples
Wire Claude into a swarm
One factory for every agent; the key comes from ANTHROPIC_API_KEY.
import { defineSwarm } from "@nightowlsdev/core";
import { anthropicModels } from "@nightowlsdev/provider-anthropic";
export default defineSwarm({
modelFactory: anthropicModels(), // reads ANTHROPIC_API_KEY
models: { allow: ["claude-sonnet-4-6"] },
agents,
});Claude for the orchestrator, a cheaper model for the rest
createModelFactory composes several provider factories and routes per agent slug; allow gates the routed models.
import { createModelFactory } from "@nightowlsdev/core";
import { anthropicModels } from "@nightowlsdev/provider-anthropic";
import { groqModels } from "@nightowlsdev/provider-groq";
const modelFactory = createModelFactory({
factories: { anthropic: anthropicModels(), groq: groqModels() },
resolve: (agentSlug) =>
agentSlug === "orchestrator"
? { provider: "anthropic", modelId: "claude-sonnet-4-6" }
: { provider: "groq", modelId: "llama-3.3-70b-versatile" },
allow: ["anthropic/claude-sonnet-4-6", "groq/llama-3.3-70b-versatile"],
});Register the adapter for a model picker
anthropicProvider() contributes its priced catalog; providers compose in the registry.
import { createModelProviderRegistry } from "@nightowlsdev/core";
import { anthropicProvider } from "@nightowlsdev/provider-anthropic";
import { openaiProvider } from "@nightowlsdev/provider-openai";
const registry = createModelProviderRegistry({
providers: [anthropicProvider(), openaiProvider()],
});Doing the parts it doesn't support
- Listing available Claude models at runtimeThe Anthropic SDK has no listing endpoint, so this adapter is catalog-only. Either treat the shipped catalog as the source, or front Claude through provider-vercel-gateway, whose adapter has a genuine live models().
- Pricing a new / unpriced Claude modelSupply the rate via cost.prices or resolveModelAllowList({ prices }); an unpriced model prices at $0 and silently disables cost.maxCostUsd, which is why anthropic:* drops unpriced rows unless allowUnpriced is set.
- Mixing Claude with other vendors per agentWrap anthropicModels() and the other provider factories in createModelFactory with a resolve() that maps each agent slug to a { provider, modelId } route, and list the routed ids in allow.
Related
- core — defineSwarm / modelFactory consume the factory, and createModelFactory composes it with other providers.
- provider-vercel-gateway — Reach Claude plus every other vendor through one key, with a live listing and per-model pricing.
- provider-openrouter — Reach Claude among hundreds of models via provider/model ids and a single key.
- model-providers — The guide to registering providers, provider-qualified allow-lists, and per-provider pricing.
- cli — owl install provider-anthropic scaffolds the env vars and the modelFactory config marker for you.