Skip to content
Effect Days 2026 Get your ticket

DecisionModel

Defines the provider-neutral service for structured decisions. decide encodes one input as JSON, sends its named decisions in one provider call, and validates the answers. Failures are reported as AiError values.

15 exports Added in v4.0.0 Source

Constructors

make

Added in v4.0.0 Source

Creates a DecisionModel that encodes inputs as JSON and validates provider answers. Answers must cover every decision and use its labels. Distributions must sum to 1 within 1e-6, optional confidence must be in [0, 1], and ratings must be in [0, criteria.length - 1]. Invalid answers fail with AiError.InvalidOutputError; encoding failures use AiError.InvalidUserInputError.

Details

Providers that round each probability to probabilityPrecision decimal places may return distributions whose sum drifts from 1 by up to half a unit of the last place per label. Setting probabilityPrecision accepts that drift and rescales the distribution to sum to 1; larger drift still fails.

See

Signature

declare function make(params: {
readonly decide: (options: ProviderOptions) => Effect<ProviderResponse, AiError>;
readonly probabilityPrecision?: number;
}): Effect<DecisionModel>

Decisions

decide

Added in v4.0.0 Source

Answers a decision definition using the current DecisionModel service. Encodes the input with Schema.toCodecJson, requiring the schema's encoding services. Explicit undefined fields become null; absent fields stay absent. Custom declarations need a JSON codec annotation or encoding fails. Returned answers and probability dictionaries have null prototypes.

See

Signature

declare function decide<Input extends Constraint, Decisions extends Record<string, Any>>(definition: Definition<Input, Decisions>, options: DecideOptions<Input>): Effect<DecideResponse<Decisions>, AiError, DecisionModel | Input["EncodingServices"]>

Example

(Triaging a ticket)

import { Effect, Schema } from "effect"
import { Decision, DecisionModel } from "effect/ai"
const TicketTriage = Decision.make({
input: Schema.String,
decisions: {
urgent: Decision.probability({
instructions: "The message is time-sensitive",
criteria: { false: "No time pressure", true: "Needs action now" }
})
}
})
const program = Effect.gen(function*() {
const { answers, usage } = yield* DecisionModel.decide(TicketTriage, {
input: "My card was charged twice, please fix this today"
})
return { probability: answers.urgent.probability, usage }
})

Models

DecideResponse interface

Added in v4.0.0 Source

Answers for every decision in a definition together with usage metadata.

See

Signature

interface DecideResponse<Decisions extends Record<string, Decision.Any>> {
readonly answers: Decision.Answers<Decisions>;
readonly usage: DecisionUsage;
}

DecisionModel interface

Added in v4.0.0 Source

Decision operations over a definition.

Signature

interface DecisionModel {
readonly "~effect/ai/DecisionModel": "~effect/ai/DecisionModel";
readonly decide: <Input extends Constraint, Decisions extends Record<string, Any>>(definition: Definition<Input, Decisions>, options: DecideOptions<Input>) => Effect<DecideResponse<Decisions>, AiError, Input["EncodingServices"]>;
}

Provider-reported token usage. Unreported counts are undefined.

Signature

declare class DecisionUsage extends {
readonly inputTokens?: number;
readonly outputTokens?: number;
} {
constructor(...args: [props?: {
readonly inputTokens?: number;
readonly outputTokens?: number;
}, options?: MakeOptions]);
}

ProviderAnswer type

Added in v4.0.0 Source

Provider answer for any decision kind.

Signature

type ProviderAnswer = ProviderClassifyAnswer | ProviderRateAnswer | ProviderProbabilityAnswer

ProviderClassifyAnswer interface

Added in v4.0.0 Source

Provider answer for a classify decision.

Signature

interface ProviderClassifyAnswer {
readonly _tag: "Classify";
readonly confidence?: number;
readonly label: string;
readonly probabilities: Readonly<Record<string, number>>;
}

ProviderProbabilityAnswer interface

Added in v4.0.0 Source

Provider answer for a probability decision.

Signature

interface ProviderProbabilityAnswer {
readonly _tag: "Probability";
readonly probability: number;
}

ProviderRateAnswer interface

Added in v4.0.0 Source

Provider answer for a rate decision. The core derives the label from the highest probability, choosing the first criteria entry on ties.

Signature

interface ProviderRateAnswer {
readonly _tag: "Rate";
readonly confidence?: number;
readonly probabilities: Readonly<Record<string, number>>;
readonly rating: number;
}

ProviderResponse interface

Added in v4.0.0 Source

Provider response for a decision request. answers is keyed like the requested decisions. Each answer is validated against its decision before it is returned to the caller.

Signature

interface ProviderResponse {
readonly answers: Readonly<Record<string, ProviderAnswer>>;
readonly usage: {
readonly inputTokens: number | undefined;
readonly outputTokens: number | undefined;
};
}

Options

DecideOptions interface

Added in v4.0.0 Source

Options for answering a decision definition.

Signature

interface DecideOptions<Input extends Schema.Constraint> {
readonly input: Input["Type"];
}

ProviderOptions interface

Added in v4.0.0 Source

Provider input options for a decision request. state is encoded with Schema.toCodecJson, not stringified. All decisions must be answered in one call.

Signature

interface ProviderOptions {
readonly decisions: Record<string, Decision.Any>;
readonly state: Json;
}

Services

Service key for answering decisions about an input. Create implementations with make.

See

  • decide for answering a definition through the current service

Signature

declare const DecisionModel: Context.Service<DecisionModel, DecisionModel>

Type IDs

TypeId

Added in v4.0.0 Source

Brand for DecisionModel implementations.

Signature

declare const TypeId: "~effect/ai/DecisionModel"

TypeId type

Added in v4.0.0 Source

Brand type for DecisionModel.

Signature

type TypeId = "~effect/ai/DecisionModel"