Skip to content

@standardagents/typesafe

TypeSafe AI decision inference with typed questions, probabilities, and automatic thread logs

First-party TypeSafe AI decision inference for Standard Agents. Jev evaluates explicit context against multiple independent questions in one request. The package implements DecisionProviderInterface (kind: 'decision', decide()), independently of the conversational provider generate() and stream() methods. Use it from hooks, tools, handlers, or thread endpoints; keep prompt-backed conversation models configured separately with defineModel.

Install and configure

pnpm add @standardagents/typesafe

Set TYPESAFE_AI_API_KEY in local .dev.vars or production secrets for BYOK. state.decide() resolves scoped provider credentials and hosted routing. Provider and platform destinations come only from trusted instance-admin or deployment configuration; user/thread URL overrides cannot redirect inherited credentials. Hosted requests use the platform TypeSafe route when supported and configured; platform availability requires a platform-owned TypeSafe credential.

Decide within a thread

import { typesafe } from '@standardagents/typesafe';

const result = await state.decide({
  provider: typesafe,
  model: 'jev-latest',
  context: { ticket: 'My payment failed twice. Please refund it.' },
  questions: {
    department: {
      type: 'choice',
      instructions: 'Which team should handle this ticket?',
      options: { billing: 'Payments and refunds', technical: 'Software failures', other: null },
    },
    severity: {
      type: 'score',
      instructions: 'How disruptive is this problem?',
      levels: ['Minor inconvenience', 'Work blocked', 'Critical outage'],
    },
    refund: {
      type: 'boolean',
      instructions: 'Does the customer explicitly request a refund?',
      criteria: { true: 'An explicit refund request', false: 'No refund requested' },
    },
  },
});

const team = result.answers.department.choice;
const refundRequested = result.answers.refund.probability >= 0.9;

decide(state, options) from @standardagents/spec or @standardagents/builder is an equivalent SDK helper. In Standard Agents Builder, both forms record the request, response, duration, status, usage, and known cost in the thread's application logs, including failure information. They work outside an active conversation turn, and their logs persist even before the thread has its first message. They do not read or write conversation messages implicitly. If an answer belongs in conversation history, explicitly call state.injectMessage() with the selected information. Avoid logging the same decision cost again through state.log().

Automatic logs, state.log(), and log attribution are Standard Agents Builder extensions, not Standard Agent conformance requirements. Import log types such as ThreadLogEntry from @standardagents/builder.

Standard Agents Builder adds optional name and trigger to the thread call to identify the operation and its cause. Pass signal to cancel a request. Context is explicit: a string, JSON object, or array. Select any relevant conversation content yourself rather than assuming Jev receives the thread history. Pre-process images, audio, video, and binary data into text or structured fields.

Questions and native conversion

Every question has a stable name and instructions. Write the full question in instructions: the question's map key is an answer identifier, not an instruction sent to Jev. Instructions, option descriptions, rubric levels, and boolean criteria may be strings, JSON objects, or arrays. Surface the domain's actual options and scoring rubric in each invocation so the decision is unambiguous.

Standard Agent request Native TypeSafe request
context state, preserving its JSON structure
questions.<id>.type: 'choice' with options type: 'choice' with criteria
questions.<id>.type: 'score' with ordered levels type: 'score' with ordered criteria
questions.<id>.type: 'boolean' with optional criteria.true/false type: 'noul' with the same optional criteria
Each question's instructions and identifier Preserved

All questions share one state and are evaluated in one POST /v1/systemone request. Choice accepts up to 255 options; use null for an option that needs no extra description. Score accepts 2–10 ordered levels. Put rules and boundary cases in instructions and criteria; do not put questions in provider connection configuration or represent them as generated tool calls.

Answers and thresholds

result contains the resolved model, named answers, standard usage, and provider metadata. Every answer retains its question identifier:

  • Choice: { type: 'choice', choice, probabilities, confidence }.
  • Score: { type: 'score', score, legend, probabilities, confidence }. The score is a probability-weighted, zero-based rubric value and can be fractional.
  • Boolean: { type: 'boolean', probability }, converted from native noul.

Probabilities and confidence use 0–1. Boolean results are never coerced to JavaScript booleans; choose and validate a threshold for the application's policy. Confidence is provider-reported and is distinct from an option's probability. Preserve the full probability distribution, score legend, and confidence when storing or presenting results. Native rounded distributions can sum slightly above or below one; the provider preserves them without silently renormalizing. metadata.native retains the native response, and metadata.rounding records probability and score precision.

Standalone use

import { typesafe } from '@standardagents/typesafe';

const provider = typesafe({ apiKey: 'your-typesafe-key' });
const result = await provider.decide({
  model: 'jev-latest',
  context: 'The customer asks to cancel their plan.',
  questions: {
    cancel: { type: 'boolean', instructions: 'Does this request cancellation?' },
  },
});

Direct provider.decide() calls have no thread and create no automatic thread logs. Connection configuration supports apiKey, baseUrl, timeout, defaultHeaders, and a custom fetch; the default base is https://api.typesafe.ai/v1. For thread calls, trusted instance-admin or deployment configuration can override it with TYPESAFE_AI_BASE_URL. Authenticated getModels() uses /models. Each attempt makes one HTTP request; the caller or runtime owns retry policy. Invalid questions or mismatched answers raise a ProviderError.

Usage and pricing

Native usage.input_tokens maps to promptTokens. Native output_tokens maps to completionTokens. Their sum maps to totalTokens. Prices change. See the TypeSafe model reference for current rates. State is ingested once for all questions. Use provider-reported input usage unchanged. Do not multiply it by the question count. Hosted router fees are additional. A decision routed through the Standard Agents platform logs the price the router charged, fee included; when the router reports none, the log shows the provider-reported cost plus the fee percent as an estimate.

jev-latest and jev-preview currently resolve to jev-1.14.0. See the TypeSafe model reference for alias updates. Aliases may move to new versions. result.model identifies the actual version; re-audit rates when aliases change, or pin jev-1.13.0 for a fixed version. An unpriced resolved model does not receive an invented usage.cost. Current context limits are 64k tokens for state plus all questions and 32k for state plus the longest question. See the TypeSafe model reference and native API reference for current limits.