Skip to content
MrJev

typesafeai-dotnet-sdk

.NET SDK.

View on GitHub →

Hands-on review

A community .NET client for Jev with real depth: typed answers, mapped errors, retries and forward compatibility. Everything we threw at it behaved.

Good for

  • C# and .NET teams that want Jev's typed answers without hand-rolling HTTP
  • Apps that need retries, mapped exceptions and DI wiring out of the box
  • Codebases where trimming or AOT rules out reflection-based serialization

Watch out for

  • The README's install command fails: only a prerelease is on NuGet, so pass --prerelease
  • Alpha and days old; the package was renamed once already, so expect churn
  • A community project, not TypeSafe's own SDK — no official support path

Tested Sep 20, 2026 at 6be669e0d0b1 · .NET 10 in Docker, against the live Jev API with a real key; 16 checks written against the SDK's own API

How we reviewed this: we built the repository at commit 6be669e in Docker on .NET 10, ran its test suite, and then wrote 16 of our own checks against the live Jev API with a real key, covering every question type, state shape, error mapping, and the SDK’s option limits. We also installed the published NuGet package into a clean project the way the README says.

What it does

This is a community .NET client for TypeSafe’s System One API, by Majdi Saibi. It is not TypeSafe’s own SDK, and the README says so twice, in bold, with a pointer to TypeSafe for anything about accounts, billing or the service itself. We like that this is the first thing you read.

The shape is what a .NET developer would expect:

var client = new TypeSafeClient();               // reads TYPESAFE_API_KEY
var result = await client.SystemOneAsync(
    "My card was charged twice, please fix this ASAP.",
    [
        new NoulQuestion("is_urgent", "Does this convey urgency?"),
        new ChoiceQuestion("department", "Which team should handle this?", ["billing", "technical", "sales"]),
        new ScoreQuestion("frustration", "How frustrated is the customer?", ["Calm", "Frustrated", "Very angry"]),
    ]);

Underneath there’s more than a wrapper: mapped exception types for every documented status, a retry policy with backoff, jitter, Retry-After handling and a total budget, an IHttpClientFactory-based DI package, a trimming- and AOT-safe overload that takes a JsonTypeInfo<TState>, and a forward-compatibility story — unknown answer kinds become UnknownAnswer instead of failing the whole response, and unmodelled fields survive in RawJson and AdditionalProperties.

What we checked against the live API

The repository’s own suite ran first: 147 tests passed on .NET 10, with 5 integration tests skipped because they need a key. (The net8.0 half of the run failed to start in our container, which only has the .NET 10 runtime — that’s our environment, not the SDK.)

Then our own checks, through the real API:

  • All three question types in one request. Noul probability, Choice label, Score value — each parsed into its own type, with the versioned model id echoed back.
  • Every state shape. Plain text, a chat-message array as JsonNode, and an arbitrary C# object through the reflection overload.
  • Noul with true/false criteria, and a Choice with descriptions and no instructions. Both accepted.
  • Choice size. 64, 240 and 255 options all answered. 256 is rejected by the SDK before any call, with an error message that explains the practical ceiling and suggests a two-stage classification instead. That’s the kind of message you want at 2am.
  • Score extras. Legend, LegendTextAtLevel, Variance and NormalizedEntropy() all returned sensible values, and the README is explicit that these are the SDK’s own arithmetic over the distribution, not the API’s confidence.
  • Usage and request id. Both surfaced; the request id is on the exceptions too, which is what you need when you file a ticket.
  • models.list returned the models our key can see.
  • A pinned model version was accepted and echoed back.
  • Error mapping. A wrong key raised TypeSafeAuthenticationException with status 401. An unknown model name raised TypeSafeBadRequestException — the API answers that with a 400, and the SDK maps it faithfully rather than guessing at 404.

Two of our checks came back “failed” and were, on inspection, the SDK being right. A ScoreQuestion with one level threw an ArgumentException client-side, before any request — the API never saw it, and the message tells you to use a Noul instead. And a RawQuestion with an invented question type was rejected by the API with a 400, which is the API’s answer, not the SDK’s fault; the escape hatch works, there is simply nothing on the other side to accept a made-up kind yet.

So: everything we could exercise behaved, and the client-side validation saved two pointless round trips.

The install command in the README doesn’t work

$ dotnet add package TypeSafeAI.Sdk
error: There are no stable versions available, 0.1.0-alpha.2 is the best available.
       Consider adding the --prerelease option

That’s the README’s own quickstart, run in a clean project. dotnet add package TypeSafeAI.Sdk --prerelease installs 0.1.0-alpha.2 and our test program compiled against it fine. A one-word docs fix, but it’s the first command a new user runs.

Related: the packages were renamed from TypeSafe.Sdk to TypeSafeAI.Sdk a day into the project’s life, and the old name still sits on NuGet at 0.1.0-alpha.1. There’s a migration document for it. Fine for an alpha; worth knowing before you pin anything.

Permissions and data

  • The SDK sends your request and nothing else. No telemetry endpoint, no phone-home.
  • The key comes from TYPESAFE_API_KEY or from options you pass, and the transport only attaches it as a bearer header.
  • Headers are redacted in debug logs, and the DI package redacts credentials from the framework’s own HTTP logging too. Bodies are not redacted when debug logging is on — a deliberate choice the code documents, and matching the sibling SDKs. If your state holds anything sensitive, don’t run debug logging in production.

Maintenance

Created on September 16 and pushed hard: 42 commits, a CI workflow, CodeQL, dependency review, an OpenSSF scorecard workflow, a docs site, locked package files, and checked-in public API surface files that fail the build when the API changes. Much of the recent history is release-pipeline plumbing, which tracks with an author trying to get a first package out properly. MIT licensed, no open issues at the time of writing.

The documentation deserves a mention: a docs folder covering quickstart, questions, answers and confidence, retries and errors, forward compatibility and patterns, plus XML docs on every public member. That’s unusual care for a five-star repository.

Verdict

If you’re on .NET and want Jev, this is a real option rather than a stopgap: it behaved correctly on every check we ran against the live API, it validates what it can before spending a call, and it’s built to survive the API growing new fields. The README explains the confidence question — what the API reported, versus what the SDK computes — better than most first-party documentation we read.

Set your expectations to alpha: one rename already, a version number below 1.0, a single maintainer, and a community project with no support commitment. For anything production-shaped, pin the version, and remember that --prerelease until a stable release appears.

For clients in other languages, see the Community SDKs in our projects list.

See how it compares with other tools in Best Jev tools, tested hands-on.

Review updated Sep 20, 2026. Numbers quoted from the project are its author's own; we don't publish our own measurements of Jev.

More in Community SDKs

laya-php

★ 110

marcreichel/laya-php

Laravel-ready PHP client for Laya, the open System One model, so a typed decision is a PHP enum rather than a parsed sentence. Self-hosted, no Jev key.

PHPReviewed

spring-ai-community/spring-ai-typesafe

Java client for the System One API on Spring RestClient, plus Spring AI integrations that use it as a judge, a guardrail, a RAG post-processor and a tool index.

JavaReviewed

obie/ruby_decision_model

Ruby gem with one client for decision models behind several providers: TypeSafe's Jev, OpenRouter (the default), OpenAI, Cloudflare Clef, Perplexity and any /v1/systemone server.

Ruby

Get new Jev projects every week

New Jev releases, pricing changes, and the best new projects, once a week. No spam; unsubscribe anytime.

Powered by Buttondown. See our privacy policy.