Typesafe / Jev Use Typesafe Jev models with @ax-llm/ax in TypeScript. Covers boolean/class signatures with value descriptions, provider trueThreshold, native Noul/Choice/Score questions, structured criteria, probability-based decisions, and explicit hybrid generation. typescript skills skill-typesafe src/ax/skills/ax-typesafe.md skill Typesafe / Jev

Typesafe / Jev with Ax (TypeScript)

Use Typesafe Jev models with @ax-llm/ax in TypeScript. Covers boolean/class signatures with value descriptions, provider trueThreshold, native Noul/Choice/Score questions, structured criteria, probability-based decisions, and explicit hybrid generation.

Install

Install only this skill for TypeScript:

Shell
npx skills add https://ax-llm.github.io/ax/typescript/ --skill 'ax-typesafe'

Published skill file: ax-typesafe/SKILL.md.

Source

Skill Instructions

Typesafe / Jev with Ax (TypeScript)

Use name: 'typesafe' for the Typesafe System One API. Jev is the model family; jev-latest is the default model. Use the Ax exports below when integrating with Ax. Python, Java, C++, Go, and Rust also support the adapter and native client. Use their generated ax-<language>-typesafe skills for native syntax and types.

Choose the Interface

NeedInterfaceResult
Required booleans and fixed classesai({ name: 'typesafe', ... }) with ax(...).forward()Ordinary signature-shaped values
Probabilities, structured criteria/state, or scoringtypesafe(...).systemOne(...)Native answers, model, and usage
Decisions followed by prose or tool useA Typesafe decision step followed by a generative providerExplicitly composed program results

A reply:string output requests freeform text and is unsupported by Typesafe. An output team:class "support, billing" returns one of those two strings. Numbers, even with min/max bounds, do not define native scoring rubrics.

Boolean and Class Signatures

TypeScript
import { ai, ax } from '@ax-llm/ax';

const apiKey = process.env.TYPESAFE_API_KEY ?? process.env.TYPESAFE_APIKEY;
if (!apiKey) throw new Error('Set a Typesafe API key.');

const model = ai({ name: 'typesafe', apiKey, trueThreshold: 0.9 });
const triage = ax(`
  ticket:string ->
  urgent:boolean(
    true "Customers cannot complete a core task",
    false "A routine request or minor inconvenience"
  ) "Does this need immediate attention?",
  team:class "support, billing, engineering"(
    support "Product usage questions",
    billing "Individual invoice or charge disputes",
    engineering "Broken functionality or service outages"
  ) "Which team should investigate?"
`);

const decision = await triage.forward(model, {
  ticket: 'Checkout fails for every customer. Payments cannot complete.',
});
// decision.urgent: boolean
// decision.team: 'support' | 'billing' | 'engineering'

trueThreshold defaults to 0.5 and must be finite in [0, 1]. A boolean is true when noul >= trueThreshold, including equality. This setting applies to every boolean output on that provider instance. It is local conversion policy and is never sent to Typesafe. Choice returns the selected label without an automatic confidence cutoff or abstention.

Field names and descriptions become question instructions. Boolean value descriptions become criteria.true/criteria.false; class descriptions become criteria keyed by the exact class labels. Descriptions may be partial; class labels without descriptions map to null. Duplicate/unknown keys and empty descriptions fail validation. Quote class labels containing spaces or punctuation. The fluent equivalent is f.boolean(...).describeValues({ true: '...', false: '...' }) or f.class([...], ...).describeValues({ label: '...' }).

The same signature works with conventional providers: Ax renders the base description plus value: description lines in the prompt and JSON schema. Annotations survive serialization and do not change inferred types or allowed values. Use the signature skill for the complete syntax. Structured JSON criteria and numeric rubrics belong in native requests below, rather than encoded JSON inside a quoted description.

The adapter sends the normal Ax prompt as native state and batches the outputs in one request. Required boolean/class outputs are supported; optional, array, nested, numeric, and freeform outputs fail before network access. Media, tools, multiple completion samples, and generation controls such as temperature or maxTokens are unsupported. There is no token streaming; Ax’s streamingForward() can deliver a completed result.

Native Questions and Application Decisions

TypeScript
import { typesafe } from '@ax-llm/ax';

const apiKey = process.env.TYPESAFE_API_KEY ?? process.env.TYPESAFE_APIKEY;
if (!apiKey) throw new Error('Set a Typesafe API key.');

const client = typesafe({ apiKey });
const result = await client.systemOne({
  state: { ticket: 'Checkout fails for every customer.', recentEvents: [] },
  questions: {
    urgent: {
      type: 'noul',
      instructions: 'Does this require immediate incident response?',
      criteria: {
        true: { description: 'Core task blocked', examples: ['Cannot pay'] },
        false: 'Routine request or minor inconvenience',
      },
    },
    team: {
      type: 'choice',
      instructions: 'Which team should investigate?',
      criteria: {
        support: 'Product usage questions',
        engineering: 'Broken functionality or service outages',
      },
    },
    severity: {
      type: 'score',
      instructions: 'How severe is the customer impact?',
      criteria: ['Minor inconvenience', 'Feature impaired', 'Core task blocked'],
    },
  },
});

const escalate = result.answers.urgent.noul >= 0.9;
const team = result.answers.team.choice; // 'support' | 'engineering'
const severity = result.answers.severity.score; // May be fractional, from 0 to 2.
const severityOnTen = (severity / 2) * 10; // Explicit application scale.
const models = await client.listModels();

Keep inline questions or use as const satisfies AxAITypesafeQuestions for reusable definitions so question keys and Choice labels retain their literal types. Noul returns noul in [0, 1] and no separate confidence field. The adapter’s trueThreshold does not apply to the native client. Choice returns choice, probabilities, and confidence; Score returns score, probabilities, legend, and confidence. The response also includes model and usage.input_tokens/usage.output_tokens.

Native state, instructions, and individual criteria accept text, JSON objects, arrays, or null. Nested JSON may contain finite numbers and booleans; a bare number or boolean is not a top-level entry. Instructions are optional in the Ax/native types, but provide an explicit question: native question keys identify answers and are not themselves instructions. Choice needs 1–255 labels; Score needs 2–10 ordered levels. null leaves an outcome without a description.

For Jev question design:

  • Phrase Noul as one clear yes/no judgment. A value near 0.5 expresses uncertainty about that judgment; use Score to measure a degree or severity.
  • Give similar Choice labels distinct descriptions. Add a catch-all label only when it belongs in the application’s allowed output set.
  • Define one dimension per Score rubric. Preserve its fractional, zero-based position; choose rounding, normalization, and weighting explicitly in code.
  • Evaluate independent questions together. A question cannot consume another answer from the same request; use a later call when that dependency exists.
  • Test wording and decision thresholds against representative labeled inputs. Confidence describes the distribution and does not establish correctness.

These practices follow the provider’s Noul, Choice, and Score guidance. The official API types describe native entries and response fields; Ax’s transport configuration uses the settings below.

Models, Transport, and Diagnostics

SettingSignature providerNative client
Default model overrideconfig: { model: 'jev-latest' }model: 'jev-latest'
Per-call model overrideThird forward() argument: { model }systemOne({ state, questions, model })
EndpointapiURL (default https://api.typesafe.ai)Same
AuthenticationapiKey or credentialProviderSame; optional static headers
Transportoptions.fetch, timeout, retry, abortSignalSame; methods accept a second transport-options argument, or the first for listModels()

listModels() returns native model cards with name, description, and release_date; it does not change Ax’s configured model aliases. Renewable credential callbacks receive { profile, operation, method, url } on each attempt: inference uses operation chat, discovery uses models. Native instance and per-call cancellation signals both apply.

Context limits apply to the combined state, instructions, and criteria. Consult the provider’s model documentation when choosing input size. Ax neither silently truncates input nor claims an exact local token count. Token usage is returned; Ax does not assume token prices for these models.

For adapter calls, use program.getUsage() and program.getChatLog(). Chat log entries retain providerMetadata.typesafe.answers; direct .chat() responses retain the same metadata. Native calls return usage and full answers directly. No separate generic metadata getter or alternate forward result is needed.

Routing and Hybrid Workflows

Typesafe-only balancers preserve schema-required generation for scalar signatures. Mixed pools retain their normal prompting; Typesafe is eligible only when the actual request already includes a supported output schema. Incompatible requests are excluded from selection and fallbacks even when degradation is allowed. A bare chat request without a supported schema fails.

For prose, run a second ax() program with a generative provider and pass the ticket plus the decision fields to it. Ax does not split a mixed urgent:boolean, reply:string signature automatically. For agents that need tools or code generation, use a generative actor and call Typesafe as a separate decision step.

Runnable Examples

Run from the repository root; the tsx command loads .env:

Shell
npm run tsx src/examples/typescript/generation/typesafe.ts
npm run tsx src/examples/typescript/generation/typesafe-native.ts
npm run tsx src/examples/typescript/generation/typesafe-hybrid.ts
npm run tsx src/examples/typescript/generation/value-descriptions.ts

The first two use TYPESAFE_API_KEY or TYPESAFE_APIKEY. The last two also use OPENAI_API_KEY or OPENAI_APIKEY. The comparison example uses the same described signature with both providers. The native example covers all primitives and model discovery; the hybrid example shows the two-program composition. Assert response contracts in live checks, not exact model probabilities.

Docs