Skip to content
Adapters

TypeSafe

The TypeSafe adapter calls Jev through decide(). Jev returns a typed answer about your data. The adapter has no chat.

1. Install

shell
npm i @tanstack/ai @tanstack/ai-typesafe

2. Set the API key

Get a key from TypeSafe. Put it in the environment of your server:

shell
TYPESAFE_API_KEY=your-typesafe-api-key

typesafeDecider reads TYPESAFE_API_KEY. To pass the key in code, use createTypesafeDecider:

ts
import { createTypesafeDecider } from "@tanstack/ai-typesafe";

const adapter = createTypesafeDecider("jev-latest", process.env.MY_TYPESAFE_KEY!);

3. Ask your first questions from the server

This route reads a support ticket and asks Jev three questions about it:

ts
import { decide, choice, score, boolean } from "@tanstack/ai";
import { typesafeDecider } from "@tanstack/ai-typesafe";

export async function POST(request: Request) {
  const ticket = await request.text();

  const result = await decide({
    adapter: typesafeDecider("jev-latest"),
    state: ticket,
    questions: {
      queue: choice({
        instructions: "Which team should handle this ticket?",
        options: {
          billing: "Payments, invoices, refunds",
          tech: "Bugs, outages, integrations",
          sales: "Pricing, upgrades, new accounts",
        },
      }),
      urgency: score({
        instructions: "How urgent is this ticket?",
        levels: ["low", "medium", "high"],
      }),
      refund: boolean({
        instructions: "Is the customer asking for a refund?",
      }),
    },
  });

  return Response.json({
    queue: result.queue.value,
    urgency: result.urgency.value,
    refund: result.refund.value,
  });
}

Each answer also has a probability. result.meta.usage has the token count.

4. Call the route from the client

decide() needs your API key, so it stays on the server. The client sends the ticket text to the route:

ts
export async function evaluateTicket(ticket: string) {
  const response = await fetch("/api/evaluate", {
    method: "POST",
    body: ticket,
  });
  return response.json();
}

Call evaluateTicket("Charged twice for the same invoice. Please refund the extra payment.") and you get back something like { queue: "billing", urgency: "medium", refund: true }.

For the question helpers, the result shape, abort, and middleware, see Evaluate. For a full TanStack Start app, see Evaluate a ticket.

Models and options

ModelDescription
jev-latestThe current stable Jev release
jev-1.13.0A pinned Jev release

You can also pass other TypeSafe model ids as a string. The package exports the known ids as TYPESAFE_EVALUATE_MODELS.

Advanced

Behind a proxy

To send every request through a gateway, set baseURL and defaultHeaders. All TanStack AI adapters use these two option names:

ts
import { createTypesafeDecider } from "@tanstack/ai-typesafe";

const adapter = createTypesafeDecider("jev-latest", process.env.TYPESAFE_API_KEY!, {
  baseURL: "https://gateway.example.com/typesafe",
  defaultHeaders: {
    "cf-aig-authorization": `Bearer ${process.env.GATEWAY_TOKEN}`,
  },
});

baseUrl and headers are aliases of the same two options. If you set both forms, baseURL and defaultHeaders win.

Bring your own key

typesafeByok from @tanstack/ai-typesafe/byok declares TypeSafe for the BYOK store, with TYPESAFE_API_KEY as its env var. See Bring Your Own Key.

API reference

The adapter sends POST /v1/systemone to the base URL with fetch. There is no TypeSafe SDK.

FactoryCreates
typesafeDecider(model, config?)An evaluate adapter. Reads TYPESAFE_API_KEY.
createTypesafeDecider(model, apiKey, config?)The same adapter with an explicit API key.

The config fields:

  • baseURL: the API base URL. The default is https://api.typesafe.ai. baseUrl is an alias.
  • defaultHeaders: extra request headers. headers is an alias.
  • fetch: your own fetch function.