Skip to content

Chat Completions (legacy)

@effect-uai/chat-completions implements the generic LanguageModel contract against POST /chat/completions. It is one reusable base you point at any compatible endpoint with baseUrl: OpenRouter, Requesty, Groq, Together, or a self-hosted gateway.

Install

Terminal window
pnpm add @effect-uai/core @effect-uai/chat-completions effect

Wire it up

import { Config, Effect, Layer } from "effect"
import { FetchHttpClient } from "effect/unstable/http"
import { layer as chatLayer } from "@effect-uai/chat-completions/ChatCompletions"
const provider = Layer.unwrap(
Effect.gen(function* () {
const apiKey = yield* Config.redacted("LLM_API_KEY")
return chatLayer({
apiKey,
baseUrl: "https://openrouter.ai/api/v1",
provider: "openrouter",
})
}),
)
const mainLayer = provider.pipe(Layer.provide(FetchHttpClient.layer))

The layer registers the generic LanguageModel tag only: the point is one base for many gateways, so there is no provider-typed tag. model is a plain string (these gateways ship hundreds of models). Streaming, tools, and structured output work as on any other provider.

Config

interface ChatConfig {
readonly apiKey: Redacted.Redacted
readonly baseUrl: string // e.g. https://openrouter.ai/api/v1
readonly provider: string // tags AiErrors from this endpoint
readonly path?: string // defaults to /chat/completions
readonly authHeader?: (req) => req // defaults to Bearer
readonly extraHeaders?: Record<string, string>
readonly extraBody?: (request) => Record<string, unknown>
}

baseUrl and provider are required; the rest cover endpoints that diverge from the defaults. Use authHeader for non-Bearer schemes (Azure’s api-key), extraHeaders for attribution headers, and extraBody for endpoint-specific request fields.

Errors

Failures surface as typed AiError variants, tagged with your provider, and recover per-tag with Stream.catchTag(...):

StatusError
429AiError.RateLimited
408/504AiError.Timeout
401AiError.AuthFailed (auth)
403AiError.AuthFailed (permission)
402AiError.AuthFailed (billing)
413AiError.ContextLengthExceeded
>= 500AiError.Unavailable
other 4xxAiError.InvalidRequest

See also

  • Responses: the protocol to prefer.
  • Gateways: OpenRouter and Requesty, in both dialects.