Skip to content

AI

Effect’s AI modules provide a provider-agnostic interface for large language models. You describe what you want — generate text, decode a structured object, stream a response, call tools — against a single LanguageModel service. Which provider answers (OpenAI, Anthropic, OpenRouter, …) is a Layer you wire up once at the edge of your application.

Because everything is an Effect, AI calls compose with the rest of the ecosystem: typed errors, retries and fallbacks via scheduling and ExecutionPlan, streaming, observability spans, and dependency injection through services and layers.

import { Effect } from "effect"
import { LanguageModel } from "effect/unstable/ai"
// The program depends only on the abstract LanguageModel service —
// it knows nothing about which provider will run it.
const program = Effect.gen(function*() {
const response = yield* LanguageModel.generateText({
prompt: "Explain what an Effect is in one sentence."
})
return response.text
})

The core API lives in effect/unstable/ai. Provider implementations ship as separate packages — @effect/ai-openai, @effect/ai-anthropic, @effect/ai-openrouter — each exposing a client Layer and a model(...) helper that supplies a concrete LanguageModel.

Tools

Define tools and toolkits the model can call. The framework resolves parameters, runs your handlers, and feeds results back to the model.

Chat

Stateful chat sessions that track conversation history automatically — the foundation for assistants and agentic loops.

There are three layers to an AI feature in Effect:

  1. The program — your business logic, written against the abstract LanguageModel, Tool, Toolkit, and Chat modules. No provider details.
  2. The model — a Layer from a provider package (e.g. OpenAiLanguageModel.model("gpt-5.2")) that provides a concrete LanguageModel plus Model.ProviderName / Model.ModelName metadata.
  3. The client — a Layer holding credentials and an HttpClient (e.g. OpenAiClient.layerConfig({ ... })), which the model Layer depends on.

Keeping these separate means you can swap providers, run the same program against a fake model in tests, or try several providers in sequence with an ExecutionPlan — all without touching your business logic.