Groq provider
Standalone — usable in any Node project, no
@warlock.js/corerequired.
@warlock.js/ai-groq is the Groq provider adapter for
@warlock.js/ai — open models (Llama, GPT-OSS,
DeepSeek-R1 distill) served fast on Groq’s LPU hardware. Groq speaks the
OpenAI Chat Completions protocol, so this package is a thin wrapper over
@warlock.js/ai-openai: it owns an internal
OpenAISDK pointed at Groq’s endpoint (https://api.groq.com/openai/v1) and
delegates the wire work, while injecting Groq’s own capability inference and
default pricing.
Install
Section titled “Install”npm install @warlock.js/ai @warlock.js/ai-groqyarn add @warlock.js/ai @warlock.js/ai-groqpnpm add @warlock.js/ai @warlock.js/ai-groqConstruct
Section titled “Construct”import { GroqSDK } from "@warlock.js/ai-groq";
const groq = new GroqSDK({ apiKey: process.env.GROQ_API_KEY!,});baseURL defaults to https://api.groq.com/openai/v1 (Groq’s
OpenAI-compatible endpoint) — override only to route through a proxy or
gateway. provider defaults to "groq" and flows through to
ModelContract.provider, AgentReport.model.provider, and logs. Every
upstream OpenAI ClientOptions field (timeout, maxRetries,
defaultHeaders, fetch, …) is forwarded verbatim to the inner client.
Use as a model
Section titled “Use as a model”const model = groq.model({ name: "llama-3.3-70b-versatile" });// Pass to any @warlock.js/ai agent / workflow / supervisor.name is the Groq-hosted open-weight id (the upstream name), NOT an
OpenAI id. Any current Groq model id works — the list below is curated, not
an allow-list:
groq.model({ name: "llama-3.3-70b-versatile" }); // flagship general-purpose textgroq.model({ name: "llama-3.1-8b-instant" }); // fastest / cheapest small textgroq.model({ name: "openai/gpt-oss-120b" }); // vision + reasoning auto-truegroq.model({ name: "deepseek-r1-distill-llama-70b" }); // reasoning auto-trueCapabilities
Section titled “Capabilities”The whole reason this wrapper exists: Groq’s ids aren’t OpenAI’s, so the
OpenAI adapter’s prefix inference would never fire. GroqSDK carries its
own name lists:
- Vision — auto-inferred
trueforgpt-oss,llama-4, andllama-3.2-*-vision;falseotherwise (e.g.llama-3.3-70b-versatile,llama-3.1-8b-instant). - Reasoning — auto-inferred
trueforgpt-oss,deepseek-r1/deepseek-r1-distill,qwq, andqwen3;falseotherwise. Drives whetherreasoning_effortis forwarded. - Structured output —
true; Groq accepts OpenAI-styleresponse_format. - Prompt caching — inherited from the inner OpenAI adapter (
true; read-sidecachedTokensaccounting).
An explicit flag always wins over inference:
groq.model({ name: "some-custom-llama", vision: true }); // force on for an unlisted multimodal idgroq.model({ name: "openai/gpt-oss-120b", reasoning: false }); // pin offReasoning (gpt-oss / deepseek-r1 distill)
Section titled “Reasoning (gpt-oss / deepseek-r1 distill)”Reasoning models accept a discrete effort knob, forwarded by the inner
adapter as OpenAI’s reasoning_effort:
const model = groq.model({ name: "deepseek-r1-distill-llama-70b" }); // reasoning auto-trueawait model.complete(messages, { reasoning: { effort: "high" } }); // → reasoning_effort: "high"reasoning.effort("low" | "medium" | "high" | "none") maps verbatim.reasoning.maxTokenshas no Chat Completions equivalent and is ignored (same as the OpenAI adapter).- When
capabilities.reasoningisfalse(e.g.llama-3.3-70b-versatile), the option is dropped — never sent as an unsupported param.
Pricing and usage
Section titled “Pricing and usage”pricing is a registry keyed by model name, rates in USD per 1,000,000
tokens (input, output, optional cachedInput). The adapter ships
built-in default rates (GROQ_DEFAULT_PRICING) as the final fallback,
taken from Groq’s model list,
fetched 2026-10-17: openai/gpt-oss-120b, openai/gpt-oss-20b,
openai/gpt-oss-safeguard-20b and qwen/qwen3.8-27b. Cached input is
50% of the input rate on the gpt-oss models — the only ones Groq caches,
automatically and with no write charge. The Llama models have no public
price (“Enterprise – Contact Sales”), so they are unpriced unless you
pass a rate:
import { GroqSDK } from "@warlock.js/ai-groq";
const groq = new GroqSDK({ apiKey: process.env.GROQ_API_KEY ?? "", pricing: { "llama-3.3-70b-versatile": { input: 0.59, output: 0.79 }, // your contract rate },});
// Or per model, overriding the SDK entry:const model = groq.model({ name: "llama-3.1-8b-instant", pricing: { input: 0.05, output: 0.08 },});Resolution at model() time: per-model pricing > SDK pricing[name] >
GROQ_DEFAULT_PRICING > undefined (no cost computed).
Every response reports token usage (with cachedTokens inside input,
inputIncludesCache: true) — on model.complete() and the streaming
done chunk too, with usage.cost when priced. Groq takes no cache
hint, so promptCacheKey is never sent. Need an offline estimate before
a call? groq.count(text) returns a fast character-heuristic
approximation — good for budgeting and quota guards, not for billing.
An overloaded endpoint (HTTP 503) surfaces as ProviderOverloadedError
(code: "PROVIDER_OVERLOADED", retryable: true); every provider error
carries status, retryable and billed (false for 401 / 402 / 403,
otherwise "unknown").
OpenAI-compatible wire behavior
Section titled “OpenAI-compatible wire behavior”Structured output and streaming are inherited unchanged from
@warlock.js/ai-openai: a responseSchema maps to response_format: json_schema (strict) when the schema is a proper root object, else loose
json_object; model.stream() drains the streaming Chat Completions
response and yields delta / tool-call / done chunks with include_usage
on. Raw errors are wrapped into the typed @warlock.js/ai AIError hierarchy
by the inner adapter (dispatch keys on status + code).
For the full wire-level surface — it is identical here — see the
OpenAI provider page and the warlock-js-ai-groq
skill.
See also
Section titled “See also”- OpenAI provider — the wrapped adapter; full wire / streaming / structured-output detail.
- Mistral provider — another OpenAI-compatible wrapper, for the Mistral model families.
@warlock.js/ai— passing the model intoai.agent({ ... }).
Provider body options and token estimates
Section titled “Provider body options and token estimates”This adapter delegates Chat Completions to the OpenAI adapter, so
providerOptions.openai.body adds native Chat request fields. Other provider
keys are ignored. Plain-object fields merge one level deep with neutral options;
caller-provided keys win, while arrays, scalars and null replace the field.
The OpenAI adapter’s protected conversation, tool and transport fields remain
protected here too. Send only fields supported by this provider; do not reuse
OpenAI-only bodies across a mixed-provider fallback chain.
Models from this adapter have no native countTokens method. Check
model.countTokens before using an optional native counting capability;
sdk.count(text) is a separate offline estimate.