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.

See

  • make for constructing a decision model service from a provider
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.

See

Signature

declare function make(params: {
readonly decide: (options: ProviderOptions) => Effect<ProviderResponse, AiError>;
}): 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/unstable/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.

See

  • make for constructing a decision model service from a provider
  • 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"