Skip to content

LanguageModel

Source: src/AWS/Bedrock/LanguageModel.ts

Runtime binding that turns an Amazon Bedrock model into an effect/unstable/ai AiLanguageModel.LanguageModel Layer, so any Effect AI program (LanguageModel.generateText, streamText, Chat, toolkits, …) runs against Bedrock without code changes.

Calls are translated to the Bedrock Converse API — Bedrock’s unified messages API that works across all conversational foundation models (Amazon Nova, Anthropic Claude, Meta Llama, Mistral, …) — so one binding covers every model. Bind one model or a list of models: the function is granted bedrock:InvokeModel and bedrock:InvokeModelWithResponseStream scoped to exactly those models, the first is the default, and runtime code picks between them (and tunes inference parameters) per call with withModelParameters. A model reference may be a foundation-model id, a cross-region inference profile id (e.g. us.amazon.nova-micro-v1:0), or a full Bedrock ARN.

Model access is an account entitlement — enable the model in the Bedrock console (Model access) before invoking, otherwise calls fail with AccessDeniedException. Many newer models are only invocable through a cross-region inference profile id, not their bare foundation-model id.

Generate Text

import { LanguageModel } from "effect/unstable/ai";
// init: bind the model and get a LanguageModel Layer
const model = yield* Bedrock.LanguageModel("us.amazon.nova-micro-v1:0", {
parameters: { maxTokens: 1024, temperature: 0.7 },
});
// runtime: any Effect AI program works against Bedrock
const response = yield* LanguageModel.generateText({
prompt: "Say hello.",
}).pipe(Effect.provide(model));

Stream Text

const parts = LanguageModel.streamText({ prompt }).pipe(
Stream.provide(model),
);
// parts is a Stream of text-start / text-delta / ... / finish parts

Override Parameters Per Call

The binding’s parameters are only defaults — scope overrides onto any call with withModelParameters.

const response = yield* LanguageModel.generateText({ prompt }).pipe(
Bedrock.withModelParameters({ temperature: 0, maxTokens: 64 }),
);

Bind Multiple Models and Pick Per Call

IAM access is fixed at deploy time (scoped to the bound list); which of those models serves a given request is a runtime decision.

// init: one Layer, IAM for both models, Nova Micro is the default
const model = yield* Bedrock.LanguageModel([
"us.amazon.nova-micro-v1:0",
"us.anthropic.claude-sonnet-4-20250514-v1:0",
]);
// runtime: route this call to Claude
const response = yield* LanguageModel.generateText({ prompt }).pipe(
Bedrock.withModelParameters({
modelId: "us.anthropic.claude-sonnet-4-20250514-v1:0",
}),
);
import { Tool, Toolkit } from "effect/unstable/ai";
import * as Schema from "effect/Schema";
const GetWeather = Tool.make("get_weather", {
description: "Get the current weather for a city.",
parameters: Schema.Struct({ city: Schema.String }),
success: Schema.Struct({ temperatureF: Schema.Number }),
});
const WeatherToolkit = Toolkit.make(GetWeather);
const response = yield* LanguageModel.generateText({
prompt: "What's the weather in Seattle?",
toolkit: WeatherToolkit,
}).pipe(
Effect.provide(WeatherToolkit.toLayer({
get_weather: ({ city }) => Effect.succeed({ temperatureF: 72 }),
})),
Effect.provide(model),
);