Skip to content

Infer

Infer

Model calls run only in automations and agent turns: a transform, a query and an action have no AI. An automation reaches the host’s AI facility through ctx.ai — sys_2.infer for a language-model answer, sys_1.decide for a fast structured decision, and embed for embeddings. A page that needs one starts the automation and watches its run.

Model classes

// src/+workspace.ts (templates/field-operations)
ai: { models: ['default'], default: 'default', embeddings: ['scene'] }

// inside a generator in src/lib/suspicion-review.ts: an absent embedding provider is allowed
import { Effect } from 'effect';
const scene = yield* ctx.ai.embed([photo.photo], { model: 'scene' }).pipe(
  Effect.catchTag('Unavailable', () => Effect.succeed(null))
);
const vector = scene?.[0];
const scene_embedding = vector === undefined ? null : [...vector];

A workspace declares the model classes it uses in +workspace.ts under ai (models, default, and embeddings for embedding models). Code names a class such as default, fast or strong, never a provider id, and the host maps each class to a model. An unmapped class answers Unavailable when called.

sys_2.infer

// src/lib/suspicion-review.ts (templates/field-operations, excerpt), called from an automation's run
export const DECISION = {
  kind: 'object',
  fields: {
    job_site_review: {
      kind: 'object',
      fields: {
        suspicious: { kind: 'bool' },
        reason: { kind: 'text' },
        evidence_asset_name: { kind: 'text', max: 256 }
      }
    }
    // …
  }
} as const;

const decision = yield* ctx.ai.sys_2.infer({
  model: 'default',
  prompt: suspicionPrompt(facts, representatives),
  files: photos, // FileRefs the run may read; the engine checks and reads them, the host encodes them
  output: DECISION
});

ctx.ai.sys_2.infer({ model, prompt, files?, output }) returns one value of the declared output kind — typed and validated, never free text. Every mapped model is multimodal, so files may carry images and PDFs the run may read: the engine checks each read and hands the bytes to the host, which encodes them for the provider.

sys_1.decide

ctx.ai.sys_1.decide({ state, questions }) asks a fast structured-decision model one or more questions about a structured, text-only state. A question is a noul (a probability of true), a choice among named options, or a score on ordered levels, and each answer’s type is inferred from its question literal. It is one call of at most 3 s, with no fallback to sys_2.

embed

ctx.ai.embed(inputs, { model? }) returns one vector per input, and a file is embedded in the same space as text. A model’s search.semantic uses the same facility on its own.

Failures

Each I/O response has a 20 s idle deadline, refreshed by streamed progress. A failure is a typed error — Upstream, Timeout, RateLimited, Invalid, TooLarge, Unsupported or Unavailable — thrown by the call, or returned by its .try form. A host without an AI facility answers Unavailable, and nothing in the build requires one. Calls are journalled by content, so a retried run does not pay twice for the same request.