24 KiB
TypeSafe AI / JEV integration research
Checked: 2026-09-18
Scope: current official TypeSafe AI/Jev documentation only. Research was gathered with Firecrawl CLI, using sequential scrapes of the official documentation index/full corpus and JavaScript SDK page (global scrape concurrency was 2). No implementation was added.
Summary
Use JEV as a small, typed intent router in front of the existing asset workflows—not as a chat model, valuation calculator, search engine, authenticator, or function executor. The recommended first call is one JavaScript SDK Choice question with exactly asset_valuation, asset_search, and unsupported options. Treat low Choice.confidence as an application-level abstention and route to a deterministic clarification/manual path; JEV has no native abstain answer.
For an asset-valuation result, code should call the reference-data/valuation service and perform any arithmetic. For an asset-search result, code should query the asset index. For unsupported, code should return a fixed product response. Keep authentication, authorization, tool execution, response text, and all side effects in application code.
Findings
-
System One is bounded decision infrastructure, not an agent or chat model. TypeSafe says System One evaluates a
stateand returns typed answers and probabilities; it does not write replies, generate code, explain reasoning, or choose its own next action. The intended architecture is ordinary software control flow with narrow AI decisions embedded in it. System One · How to build with System OneImplications for this integration:
- Not generative chat: use deterministic/canned UI responses or another separately approved component for user-facing text; do not ask JEV to compose the clarification or unsupported message.
- Not calculation: do not ask JEV to compute a reference valuation, normalize currency, or perform exact arithmetic. Keep those operations in code. TypeSafe explicitly recommends using code for work it can compute exactly. Advanced structure/failure modes
- Not authentication or authorization: the SDK API key authenticates calls to TypeSafe; it does not authenticate the end user or authorize an asset action. Perform application identity, entitlements, and permissions before/after routing in code.
- Not execution: the function-calling cookbook maps closed-set values to ordinary typed functions, but the functions remain application code. Function calling cookbook
-
State is shared, questions are independent. A request evaluates one
stateagainst one or more questions. State may be a string or structured JSON object/array containing the text and relevant application context; JEV currently supports text input and does not support image, audio, or video. Every question sees the same state and one question's answer does not become context for another. State · API request bodyFor the router, send only the user request plus any text/JSON metadata required to disambiguate it, for example
{ message, asset_context }. Do not send unrelated records. Current docs warn that context rot lowers accuracy and recommend decomposing both state and questions. -
The primitives have distinct, typed semantics.
- Choice: selects exactly one member of a fixed criteria map and returns
choice, all optionprobabilities, andconfidence. It is the correct primitive for the three-way router. Include an explicitunsupportedoption rather than forcing every request into a supported route; TypeSafe recommends another/none of the aboveoption when a list may not cover every input. A Choice supports up to 255 options. Choice - Noul: returns
noul, the probability that a yes/no statement is true. It has no separateconfidence; values near 0.5 indicate an ambiguous yes/no judgment. Use it for a separate boolean such as “does the request mention a specific asset identifier?”, not as a replacement for the three-way router. Noul - Score: returns an expected numeric position over an ordered list of 2–10 descriptive levels, the level probabilities, a legend, and confidence. It is appropriate for a dimension such as evidence quality or urgency, not for exact valuation arithmetic. Score
- Confidence: is derived from the Choice/Score probability distribution. It is a useful uncertainty signal, not a correctness guarantee. Full probabilities should be retained for auditing and policy decisions. Noul answers do not carry
confidence. Confidence
- Choice: selects exactly one member of a fixed criteria map and returns
-
Exact recommended router labels and boundaries. Use one
Choicewhose criteria are deliberately contrastive:asset_valuation: the user asks to estimate, compare, look up, or understand the reference worth/valuation of an identified asset or asset candidate. The downstream valuation implementation owns data freshness, methodology, and arithmetic.asset_search: the user asks to find, browse, list, filter, or retrieve assets or reference records; valuation is not the primary requested operation.unsupported: the request is neither supported asset browsing nor reference valuation (including unrelated chat, unsupported transactions, or unrelated domains).
Avoid overlapping descriptions such as “anything involving prices” in both supported options. In particular, “find assets priced below X” is primarily
asset_search; “what is this asset worth?” isasset_valuation. A low-confidence result is not a fourth JEV label: it is an application-level abstention. -
Confirmed JavaScript package and API. The official JavaScript SDK docs specify Node.js 20+, package
@typesafe-ai/sdk, ESM/CommonJS support, and TypeScript declarations. The current SDK reference exposesVERSION0.6.0and the changelog records v0.6.0 on 2026-09-15. JavaScript SDK · JavaScript changelogConfirmed API/type surface:
new TypeSafeClient(config?);TypeSafeClientConfigincludesapiKey,baseURL,defaultModel,defaultHeaders,fetch,logger,logLevel,retry,timeout, anddangerouslyAllowBrowser.client.systemOne<Q>(request, options?)returnsAPIPromise<SystemOneResult<Q>>.systemOnerequest fields arestate: EntryType,questions: Q, and optionalmodel: string.EntryTypeis a string, JSON object, JSON array, ornull.choice<T>(instructions, criteria)returnsChoiceQuestion<T>;noul(instructions?, criteria?)returnsNoulQuestion;score<T>(instructions, criteria)returnsScoreQuestion<T>.SystemOneResult<Q>.answersmaps each question key toResultFor<Q[K]>;ResultForpreserves the criteria keys.ChoiceResponse<T>.choiceis typed askeyof T & string, with typedprobabilities,confidence, andtype: "choice".- Environment defaults are
TYPESAFE_API_KEY,TYPESAFE_BASE_URL,TYPESAFE_DEFAULT_MODEL, andTYPESAFE_LOG_LEVEL; default base URL ishttps://api.typesafe.ai, default model isjev-latest, default log level iswarn, and default per-attempt timeout is 10,000 ms. TypeSafeClient · choice() · SystemOneRequest · SystemOneResult · ResultFor · ChoiceResponse · TypeSafeClientConfig
-
Exact typed-router call (SDK-confirmed). This is the integration shape to implement later; the snippet uses the confirmed package and methods, not an inferred SDK name:
import { choice, TypeSafeClient } from "@typesafe-ai/sdk"; const client = new TypeSafeClient({ // Pin while calibrating thresholds; jev-latest is the SDK default. defaultModel: "jev-1.13.0", }); const result = await client.systemOne({ state: { message: userMessage }, questions: { intent: choice("What is the user's primary supported intent?", { asset_valuation: "The user wants a reference valuation or wants to understand the worth of an identified asset.", asset_search: "The user wants to find, browse, list, filter, or retrieve assets or reference records; valuation is not the primary request.", unsupported: "The request is outside asset browsing and reference valuation, including unrelated chat or unsupported actions.", }), }, }); const answer = result.answers.intent; // answer.choice is inferred as the criteria-key union: // "asset_valuation" | "asset_search" | "unsupported". // answer.probabilities and answer.confidence are also available.The current model page says
jev-latestcurrently resolves tojev-1.13.0. Use the pinned ID while calibrating the abstention policy; use the alias only when accepting model movement is intentional. The responsemodelfield reports the version that actually answered. Models -
Recommended dispatch and abstention policy. JEV should return a classification, after which code owns the route:
- if
answer.confidence < CONFIDENCE_FLOOR, return an application-levelabstainresult and use a deterministic clarification/manual-review flow; - otherwise, route
asset_valuationto the reference valuation service,asset_searchto the asset index, andunsupportedto a fixed unsupported response.
Start with a configurable
CONFIDENCE_FLOOR = 0.80for this medium/high-consequence router, then calibrate it against labeled requests and the cost of each routing error. This is an application policy, not a TypeSafe default. The official guidance gives examples of 0.5/0.6 floors for human routing and >0.85/>0.9 for higher-risk actions, and says thresholds must match risk and be tested on the application's data. Confidence · Confidence-gated routing · Intent routingRecommended local result shape (not a JEV response shape):
abstain | { route: "asset_valuation" | "asset_search" | "unsupported", confidence, probabilities, model }. Do not pretend a low-confidencechoiceis a reliable route. Preserve the raw answer, probability map, model version, usage, and request ID for evaluation. - if
-
There is no native abstention field. A Choice always selects one supplied option. Therefore:
unsupportedis the explicit semantic escape hatch for out-of-scope input;- low confidence is the uncertainty escape hatch and must be converted to
abstainby application code; - if a future requirement needs a separate “in-scope but missing details” class, add a fourth criteria key or use the same low-confidence abstention path; do not infer that behavior from a missing SDK field.
This is preferable to using an independent Noul for each route: separate Nouls are absolute yes/no judgments and are not guaranteed to be mutually exclusive or comparable. A Choice is the relative one-of-N classifier needed here. Choice · Noul · Confidence
-
Transport and SDK failure behavior is distinct from semantic abstention. The HTTP API documents
POST https://api.typesafe.ai/v1/systemone, bearer authentication, and these error meanings: 401 missing/invalid key, 422 invalid request body, 429 rate limit, and 529 temporary overload. API referenceThe JavaScript SDK exposes:
AuthenticationError(401),BadRequestError(400),PermissionDeniedError(403),NotFoundError(404),RateLimitError(429),UnprocessableEntityError(422), andInternalServerError(5xx), all carrying the parsedbody, headers, status, and usuallyrequestIdthroughAPIError.APIConnectionErrorfor connection/response delivery failures,APITimeoutErrorfor a response that exceeds the configured timeout, andAPIUserAbortErrorfor anAbortSignalcancellation.- Default retry policy: connection errors and timeouts are retryable; HTTP statuses 408, 429, and 500–599 are retried, up to 2 retries after the initial attempt, with exponential backoff starting at 500 ms, capped at 5,000 ms, 25% jitter, and
Retry-Afterhonored up to 60,000 ms. Per-calltimeout,retry,headers, andsignalare supported viaRequestOptions. APIError · RateLimitError · APITimeoutError · RequestOptions · RetryPolicy
Handle 401/403/422/configuration failures as non-retryable integration failures; let the SDK handle transient 408/429/5xx/connection/timeout retries, then fail closed to an application fallback. A transport error is not an
unsupportedclassification and must not be converted into one. Never expose the API key in a browser: the SDK defaultsdangerouslyAllowBrowserto false. -
Fan-out is the right composition strategy for independent router features. TypeSafe recommends sending independent questions about one state together: they are evaluated in parallel, and code may ignore answers that do not apply. If a later question genuinely depends on the first answer or requires newly fetched state, make a second request in code. Speculative fan-out · Parallel questions cookbook
For the first implementation, keep the request to the single intent Choice. If later needed, add independent questions in the same request—for example a Noul for whether an asset identifier is explicitly present—but do not add an extraction/calculation question merely because it is available. The parallel-questions cookbook reports that batching 13 questions over one document avoids resending the document and, in its dated example, was 12.2× cheaper and 10.0× faster than 13 serial calls with no answer change. The exact benchmark is workload-specific, but the architectural lesson applies.
-
Composite scoring belongs after classification and remains deterministic. Break a broad judgment into independent Score dimensions, normalize each score to 0–1, and combine with weights in application code. Preserve each component and its probabilities rather than asking JEV for one opaque “overall valuation.” Composite scoring · Score
This can support a later reference-ranking policy (for example evidence quality, recency, and match quality), but it must not replace the authoritative valuation formula. Scores are judgments over descriptive levels; they are not exact financial numbers.
-
Function-calling cookbook: closed sets only, with code in control. The official example maps a function selector to a Choice, fixed-list arguments to Choice,
boolflags to Noul, and set-valuedlist[Literal]arguments to one Noul per member. Optional arguments use a separate “was this argument stated?” Noul so the function default can remain in effect. The cookbook reports call confidence as the least certain judgment rather than a product of probabilities. Function callingThis pattern is useful later for deterministic asset-search/valuation handlers, but it is not a JEV tool-execution API. Do not pass open-ended numeric calculations, authorization decisions, or arbitrary generated function arguments to JEV. Validate every route and argument in application code.
-
Reranking is a candidate-scoring pattern, not an asset search replacement. The official reranking cookbook first uses a fast search method (BM25) to produce a shortlist, then scores each query/candidate pair with a Noul and sorts by the returned probability. TypeSafe cannot add a candidate omitted by the fast search stage. The dated example reranked 30 candidates for each of 40 legal queries and improved top-1 from 5% to 18% and top-10 from 38% to 62%. Reranking cookbook
If asset search eventually needs semantic ordering, keep the asset index/retrieval system first, then use one Noul per query-candidate pair (or batch independent signals per pair) and sort in code. Do not invoke JEV against the entire asset corpus.
-
Extraction should be candidate-first and lossless. The official pre-parsed extraction cookbook uses regex to over-find candidate emails, phone numbers, or amounts; a Choice selects one candidate verbatim; code copies and normalizes it. It adds a
noneChoice option as an escape hatch and notes the 255-option limit. It explicitly says JEV should choose among candidates, not invent an unbounded value or transpose digits. Pre-parsed value extractionApply this to asset IDs/tickers only when the candidate finder is owned by code or another approved extractor: provide the candidate strings as Choice options, include
none, copy the selected identifier exactly, and validate it against the asset index. Do not ask JEV to generate a new identifier or exact valuation. -
Routing cookbook evidence supports graceful degradation. The official classification-with-confidence cookbook classifies into a fine-grained Choice taxonomy, then reports a broader parent label when confidence is below a threshold rather than forcing a specific answer. The intent-routing pattern similarly sends low-confidence requests to a human and routes high-confidence labels to deterministic handlers or specialist systems. Classification using confidence · Intent routing
For this scope, the equivalent broader fallback is the local
abstainroute, which can request required asset details through a fixed form or send to manual review. There is no official evidence that JEV itself should generate the clarification text.
Exact integration recommendation
- Run the router server-side with
@typesafe-ai/sdkon Node.js 20+. - Pin
model: "jev-1.13.0"(ordefaultModel) while measuring; log the returnedmodel. Move tojev-latestonly with an explicit threshold-recalibration policy. - Send a minimal state containing the incoming user text and only relevant text/JSON context.
- Ask one
choice()question with the three contrastive keysasset_valuation,asset_search, andunsupported. - Convert
confidence < 0.80to a local typedabstain; validate/recalibrate this floor with a labeled evaluation set. Keep all probabilities, not only the winner. - Dispatch high-confidence results in ordinary code: valuation service, asset index, or fixed unsupported response. Keep user auth, authorization, exact calculations, data fetching, and side effects outside JEV.
- Treat SDK/API failures as failures, not as semantic
unsupported. Retry only according to the SDK policy; fail closed after retries and retain the request ID/error body for diagnosis. - Add fan-out questions only when independent and useful. Add extraction/reranking/composite scoring as separate, deterministic stages—not inside the initial router.
Gaps and caveats
- No native abstain result: the SDK/API always returns a Choice label when the request succeeds. Local
abstainis required. - No official asset-domain rubric or benchmark: current docs provide generic routing examples, not accuracy for asset browsing/reference valuation. Build a labeled test set containing near-boundary requests, missing asset details, price-search wording, unsupported requests, and adversarial/ambiguous text.
- Threshold calibration is application-specific: official docs give guidance and examples but no universal confidence threshold. Validate the proposed 0.80 floor and separately measure false valuation routing versus false search routing.
- No clarification-label requirement in the chosen scope: the three requested labels do not include
clarification. Low-confidence in-domain requests will abstain; if product analytics need a distinct typedneeds_detailsoutcome, add it deliberately rather than overloadingunsupported. - No JEV-generated response or valuation: current docs do not provide a chat-generation method, calculator, finance data source, valuation methodology, or authorization system. Those are integration responsibilities.
- Current SDK documentation is precise, but cookbook code is mostly Python: the official JavaScript API confirms the client and types, while the requested cookbooks show Python examples. Porting cookbook architecture to TypeScript will require local implementation and tests; do not infer undocumented helper classes from Python cookbook names.
- Alias movement:
jev-latestcan point to a future release; thresholds tuned to a pinned model must be retested after any model change.
Sources
All kept sources below are official TypeSafe AI documentation and were current at the checked date.
- System One — model purpose and distinction from LLM agents/generative output.
- How to build with System One — code-controlled architecture, decomposition, fan-out, confidence gates.
- State — supported state shapes and text-only Jev input.
- Choice, Noul, Score, Confidence — primitive and uncertainty semantics.
- API reference and Models — HTTP shape, errors, current model ID/alias.
- JavaScript SDK, JavaScript changelog, TypeSafeClient, choice(), SystemOneRequest, SystemOneResult, ChoiceResponse, ResultFor — confirmed package/API/types.
- Speculative fan-out, Composite scoring, Confidence-gated routing, Intent routing — required architecture patterns.
- Function calling, Parallel questions, Reranking, Pre-parsed value extraction, Classification using confidence — required cookbook coverage.
Dropped by scope: third-party articles, reviews, hosted-provider documentation, social posts, and non-official examples were not used as evidence.