What is TypeSafe.ai? I’m considering this plan:...
------ Chat Conversation ------
User: What is TypeSafe.ai? I’m considering this plan:
AVENTURE BACK-END · ISSUE #2374 · TYPESAFE SYSTEM ONE / JEV
Typed Decision Slice
One data-class file, one endpoint method on the existing inference controller, one service method on the existing inference service. The generator, the catalog YAML, and the provider adapter do not change.
1. The chain, and the one place it grows
NEW
domain/model/inference/Decision.kt
InferenceController + decisions()
InferenceService + decide()
docs/mcp/api-endpoints.md +1 line
springdoc
/v3/api-docs
make docs-local
postman/openapi.json
api-schemas (Zod)
generator-policy.mjs, unchanged
MCP + aventure-cli
build-mcp.ts, unchanged
callers
aventure-cli inference
decisions create
--from-file q.json
skills: enrich / mutate
EXISTING, reused as-is
InferenceService.dispatchChatCompletion · ChatResponseFormat(jsonschema, strict) · gateway default-chat-model
Confidence enum · --from-file reader · x-aventure-tool cli naming · Jev later = a gateway route
NEEDED ALREADY OWNED BY EVIDENCE
Strict JSON-schema answer decoded into a typed Kotlin verdict ChatResponseFormat, ChatJsonSchema, ChatObjectSchema, ChatStringSchema(enumValue) application/usecase/job/support/ChatResponseFormat.kt:8-39; used by EntityClosureSweepAdjudicator.kt:141-151, BlogPostIngestAdjudicator.kt:113-116, RssNewsLinkerLlm.kt:167
Provider-neutral dispatch with model override InferenceService.dispatchChatCompletion application/usecase/inference/InferenceService.kt:70; model precedence AppInferenceProperties.kt:161
A default model that supports strict jsonschema app.inference.profiles.llm-gateway.default-chat-model: qwen3.8-27b, already required to application-domain.yml:1708-1723
Confidence that licenses an action, with "abstain at LOW" documented Confidence { HIGH, MEDIUM, LOW }, exported domain/model/confidence/Confidence.kt:14-28
CLI body input, JSON output, noun/verb naming --from-file reader; x-aventure-tool.cli on the @Operation mcp/aventure-cli/commands/json-input.ts:16-30; InferenceController.kt:74-75
Callers that hold the dossier skill steps and harness runs already call generated CLI operations aventure-enrich §0.2 Phase 1; §0.2.1.2
2. Minimum schema
One primitive, Choice. Every slice-1 decision is a choice; yes/no is two options. That removes any need for a oneOf union. Lives in the existing domain/model/inference package.
// domain/model/inference/Decision.kt
@Schema(name = "DecisionQuestion", description = "One choice question over a bounded state; option keys are the closed answer set.")
data class DecisionQuestion(
@field:Schema(description = "Caller-owned key naming the decision, e.g. entity.typeRecord.structuralRole. Opaque to the server.")
val decisionKey: String,
@field:Schema(description = "State the model judges: dossier excerpt as text or JSON text.")
val state: String,
@field:Schema(description = "The question, phrased so exactly one option answers it.")
val instruction: String,
@ArraySchema(arraySchema = Schema(description = "Closed answer set."), minItems = 2, maxItems = 255)
val option: List,
@field:Schema(description = "Gateway model id override; null uses the profile default chat model.")
val model: String? = null,
)
@Schema(name = "DecisionOption", description = "One answer key and what it means.")
data class DecisionOption(val key: String, val description: String)
@Schema(name = "Decision", description = "Typed answer with its full probability distribution. confidence LOW means abstain.")
data class Decision(
val decisionKey: String,
@field:Schema(description = "Chosen option key; always one of the request's option keys.")
val choice: String,
@ArraySchema(arraySchema = Schema(description = "One row per option key, normalised to sum to 1."))
val probability: List,
@field:Schema(description = "HIGH licenses an automatic write, MEDIUM a reviewed write, LOW abstains.")
val confidence: Confidence,
@ArraySchema(arraySchema = Schema(description = "Short factual phrases from the state that support the choice."))
val evidence: List,
@field:Schema(description = "Resolved gateway model id.")
val model: String,
@field:Schema(description = "Provider round-trip in milliseconds.")
val latencyMs: Long,
)
@Schema(name = "DecisionProbability", description = "Probability mass on one option key.")
data class DecisionProbability(val key: String, val probability: Double)
Generated, unchanged generator
// api-schemas/inference/decision.ts
export const DecisionSchema = z.object({
decisionKey: z.string(),
choice: z.string(),
probability: z.array(DecisionProbabilitySchema),
confidence: ConfidenceSchema,
evidence: z.array(z.string()),
model: z.string(),
latencyMs: z.number().int(),
});
Called
aventure-cli inference decisions create \
--from-file q.json --data
{ "decisionKey": "entity.typeRecord.structuralRole",
"state": "",
"instruction": "Which structural role does this entity play?",
"option": [
{"key":"Company","description":"Raises rounds, sells products or services"},
{"key":"InvestmentFirm","description":"Its own primary activity is deploying capital"},
{"key":"Fund","description":"A pooled vehicle managed by an investment firm"},
{"key":"Government","description":"Public-sector agency, regulator, or program"} ] }
Company
0.91
InvestmentFirm
0.06
Fund
0.02
Government
0.01
confidence = HIGH → the skill writes typeRecord. Example values.
Jev mapping, no adapter
AVENTURE JEV POST /V1/SYSTEMONE
state / decisionKey / instruction state / question id / questions[id].instructions
option[].key, description questions[id].criteria map, type: "choice", ≤255 keys
choice / probability[] / confidence answers[id].choice / .probabilities (sum 1) / .confidence 0–1
model "jev-latest"
When the gateway exposes jev-latest as a chat route, the caller passes it as model. Back-end code does not change. Jev: $0.042/MTok input, output free, early access as of 2026-09-15.
3. What was cut, and why
REMOVED REASON
Separate DecisionController + DecisionService Existed only to stay under the 500-line file cap. The endpoint is an inference operation; it belongs on InferenceController / InferenceService next to chat completions create.
Pinned model slot (InferenceModelSlot, STRUCTUREDOUTPUTS check) The profile default already has to support strict jsonschema (application-domain.yml:1708-1713). An override that cannot is rejected by the gateway and surfaces as the existing provider failure.
Confidence thresholds YAML (0.85 / 0.60) + banding code The three existing adjudicators have the model report the Confidence band inside the schema. Same here: zero config, zero code. ponytail: self-reported band; derive from the distribution once a calibrated provider (Jev) is routed.
input-char-limit, max-token config Request size and serving limits are already enforced by Spring and the gateway.
New docs/domain-contracts/decision.md The route lint accepts one line in the existing docs/mcp/api-endpoints.md.
decisionSchemaVersion, separate abstention fields, Score/Noul, audit table, Jev adapter No reader today. Abstention is LOW; the envelope in the run ledger is the audit record; Jev is a gateway route.
4. Build order
Decision.kt as above.
InferenceService.decide(question): ChatResponseFormat(ChatJsonSchema("decision", ChatObjectSchema(properties = {choice: enum(keys), probability: array, confidence: enum(Confidence), evidence: array}, required = all))); dispatch; normalise the vector; reject choice ∉ keys or a missing key as InferenceFailure.providerInvalidJson (503), as EntityClosureSweepAdjudicator.invalidProviderJson does.
InferenceController: POST /v1/inference/decisions, x-aventure-visibility private, x-aventure-tool cli = "inference decisions create", admin key like the sibling operations. One line in docs/mcp/api-endpoints.md.
make docs-local; commit generated Zod, MCP, CLI with the source.
One service test on a canned provider body: valid answer decodes; out-of-set choice throws; missing key throws.
5. Enrichment wiring
The dossier lives in the skill run, so each decision is a skill step reading one band.
DOMAIN DECISIONKEY STEP HIGH MEDIUM LOW
Entity entity.typeRecord.structuralRole aventure-enrich §0.2 Phase 1, before entities update --type-record write keep current, ledger abstain, ledger
Person person.association.isCurrent aventure-mutate §6 step 5a association rows write write, endDate null, ledger skip row
News news.article.material news.discovery "material" floor in aventure-completion §1 count join, do not count do not join
A 503 from the provider path means the step falls through to today's rule text, which is the "existing behavior intact" acceptance line at no cost.
Self-reported confidence is uncalibrated. Do not let any decision write unattended until replayed envelopes have been scored against adjudicated answers.
Assistant: ### What TypeSafe.ai Is
TypeSafe AI builds specialized System One models designed explicitly for programmatic decision-making in software back-ends rather than conversational text generation. Their flagship model, Jev, bypasses token-by-token generation entirely to return direct, typed discrete outputs with calibrated probabilities and confidence scores, running significantly faster and cheaper than general-purpose frontier LLMs typesafe.ai.
---
### Plan Evaluation: Aventure Back-End Issue #2374
The proposed architecture is exceptionally lean, practical, and well-sequenced. It establishes a contract-first abstraction using your existing chat completion gateway today, leaving zero friction when routing directly to Jev later.
#### Key Strengths
- Zero-Waste Abstraction: Reusing InferenceService.dispatchChatCompletion with strict jsonschema gives you the exact target interface (Choice, probability, confidence, evidence) without writing disposable provider adapters.
- Contract Symmetry with Jev: The DecisionQuestion and Decision schemas directly map to Jev’s POST /v1/systemone format (criteria map, choice, probabilities), turning future Jev adoption into a simple gateway model-route addition.
- Sensible Scope Pruning: Cutting pinned model slots, separate controllers, and ad-hoc threshold YAML keeps changes confined to a single clean slice while honoring your 500-line file cap.
- Graceful Degradation: Treating provider failures (503s or non-conforming JSON) as an automatic fall-through to existing rule logic guarantees backward compatibility during rollout.
#### Considerations & Failure Modes
| Area | Observation | Recommendation |
| :--- | :--- | :--- |
| Probability & Confidence | Standard chat models (qwen3.8-27b) generate pseudo-probabilities and uncalibrated self-confidence via JSON schema text. | Treat generative probabilities as heuristic rankings until a true classifier like Jev routes the response. |
| Schema Normalization | LLMs occasionally fail strict floating-point sums to 1.0 or hallucinate invalid distribution floats. | Ensure your Kotlin deserializer or domain service normalizes the probability array so $\sum p = 1.0$ unconditionally. |
| Evidence Grounding** | Chat models may hallucinate citations not present in the dossier. | Keep evidence optional or validate substring presence in state during replay auditing. |
The execution order and fall-through mechanics are solid; proceeding with the Decision.kt slice and canned provider unit tests is safe to implement.
Working notes:
- Check what TypeSafe.ai and Jev System One are in 2026.
Sources:
- Introducing System One Models and Jev: https://typesafe.ai/blog/introducing-system-one-models-and-jev (search result only)
- TypeSafe AI: Home: https://typesafe.ai/ (search result only)
- Introducing System One Models and Jev: https://news.ycombinator.com/item?id=49717558 (search result only)
- Jev skips token generation entirely, and the speed...: https://daily.dev/posts/jev-skips-token-generation-entirely-and-the-speed-numbers-are-hard-to-ignore-nv8tizgl7 (search result only)
- TYPESAFE AI LAUNCHES JEV, ITS FIRST “SYSTEM ONE ...: https://x.com/wallstengine/status/2099927802405654900 (search result only)
------ Research Draft Summary ------
# TypeSafe AI and the Aventure Typed Decision Slice
TypeSafe AI builds “System One” models for decisions inside software, and Jev is its first public model optimized for automation [typesafe.ai](https://typesafe.ai/). Aventure’s proposed typed-choice contract fits that stated purpose, but the available sources do not verify Jev’s API schema, pricing, calibration, or gateway compatibility.
## TypeSafe AI and Jev
Jev is presented as a specialized alternative to token-generating language models for bounded decision tasks. TypeSafe AI claims comparable intelligence on “System One” tasks while operating two orders of magnitude faster than existing LLMs [typesafe.ai](https://typesafe.ai/blog/introducing-system-one-models-and-jev).
A secondary report says Jev returns typed decisions with probabilities and confidence scores rather than generating text token by token [daily.dev](https://daily.dev/posts/jev-skips-token-generation-entirely-and-the-speed-numbers-are-hard-to-ignore-nv8tizgl7). The supplied evidence does not establish that those probabilities are calibrated.
## Fit with the proposed architecture
The narrow `Choice` primitive is directionally aligned with Jev’s decision-oriented positioning. A bounded option set, selected choice, probability distribution, and confidence field form an appropriate provider-neutral application contract.
The initial implementation should remain independent of Jev:
- Add `DecisionQuestion`, `DecisionOption`, `Decision`, and `DecisionProbability`.
- Add `POST /v1/inference/decisions` to the existing inference controller.
- Dispatch through the existing inference service and strict JSON-schema response path.
- Preserve the model override for future routing.
- Generate the existing OpenAPI-derived Zod, MCP, and CLI artifacts without changing their generators.
- Fall back to existing rules when the provider fails or returns an invalid answer.
No cited source confirms that Jev is exposed as a chat-model route. No cited source confirms that passing `jev-latest` through the existing gateway would work without an adapter.
## Contract safeguards
Generative-model outputs should not be treated as calibrated probabilities or reliable authorization signals. A strict response schema constrains shape but does not establish statistical validity.
The service should reject:
- A choice outside the request’s option keys.
- Duplicate, missing, or unknown probability keys.
- Non-finite or negative probabilities.
- A probability vector with zero total mass.
- Missing required evidence or confidence fields.
Normalization may repair ordinary sum drift, but it should not conceal malformed vectors. `LOW` should remain an abstention signal, while `HIGH` and `MEDIUM` should not license unattended writes until replay results establish acceptable error rates.
## Rollout
The safest rollout separates contract adoption from automated mutation:
1. Ship the typed endpoint behind existing authorization.
2. Record requests, raw provider responses, normalized decisions, model identifiers, and latency.
3. Run in shadow mode against adjudicated examples.
4. Measure accuracy and calibration by decision key.
5. Set action policies per domain only after validation.
6. Introduce Jev as a provider route only after confirming its actual API and operational behavior.
## What would sharpen this
- Jev’s official API documentation would confirm request and response fields, authentication, limits, model identifiers, and whether an adapter is required.
- Official pricing and availability terms would verify the claimed `$0.042/MTok` input price, free output, and early-access date.
- Calibration results would determine whether returned probabilities can govern writes or only rank choices.
- Gateway documentation would establish whether Jev can be exposed through the existing chat route.
## Related questions
- What accuracy and calibration does Jev achieve on each proposed Aventure decision key?
- Does Jev support arbitrary option descriptions and as many as 255 choices?
- How does Jev represent abstention, confidence, and malformed or ambiguous questions?
- What latency, rate limits, privacy terms, and data-retention rules apply?
- Which replay thresholds should permit automatic, reviewed, or prohibited writes?