Integrate Jev AI Routing into TanStack Start Apps

A guide to building intelligent, server-side ticket triage with TanStack AI and Vercel Gateway.

GeoDetect PipelineSeptember 27, 2026
Share

Overview

Integrating Jev into TanStack Start applications allows developers to automate support ticket routing using AI-driven evaluation. By leveraging TanStack AI's decide() function alongside the Vercel Gateway adapter, applications can process user inquiries and direct them to the appropriate team without manual intervention.

This integration transforms unstructured customer messages into actionable data. The system evaluates the subject and body of a request, determines the most suitable queue, and returns a decision that the interface can display or the application can act upon.

Jev returns constrained decisions that the form can display once the evaluation completes, ensuring that tickets are routed based on evidence rather than guesswork.

The workflow involves four distinct components: TanStack Start receives the submission, TanStack AI defines the routing logic, the Vercel Gateway adapter handles authentication and evaluation, and Jev selects the final option from the defined queue.

Architecture and Responsibilities

Understanding the division of labor is essential for a successful implementation. Each component in the stack has a specific responsibility in the support form workflow.

  • TanStack Start: Acts as the entry point, receiving the form submission from the client and returning a standardized response.
  • TanStack AI: Expresses the routing question and exposes a typed result structure, ensuring type safety throughout the evaluation process.
  • Vercel Gateway adapter: Forwards the evaluation request through AI Gateway, handling the complex authentication layer so developers do not need to manage raw API keys directly.
  • Jev: Selects from the queue options supplied by the developer, providing a probability score for each selection.
  • Application code: Accepts the proposed queue and applies business logic, such as requiring human review if confidence thresholds are not met.

The Vercel Gateway adapter exposes createVercelGatewayDecider, which pairs with decide() and the model ID typesafe-ai/jev. This setup ensures that the evaluation is secure and that the routing decision is both fast and accurate.

Defining the Routing Decision

Before writing code, developers must define what constitutes a valid routing decision. Consider a scenario where a customer submits a message regarding an unexpected invoice. The application needs to choose a support queue before any human investigation begins.

The system should be fed the subject and message as evidence. Destinations must be defined in terms of the work each team owns:

  1. Billing: Handles charges, invoice amounts, and payment questions.
  2. Technical Support: Investigates product failures, outages, and integration issues.
  3. Review: Covers requests with unclear or overlapping responsibilities, such as a message reporting a payment error while also asking for help restoring product access.

The core question posed to the AI is simple: "Which team should handle this request first?" This assignment gives the support team a starting point but does not establish the cause of the problem or confirm that the account has been checked.

Implementation Steps

Install Dependencies

In an existing TanStack Start React project, install the necessary evaluation packages, the Vercel OIDC helper, and Zod for request validation:

npm install @tanstack/ai @tanstack/ai-vercel-gateway @vercel/oidc zod

The core package provides the decide() function and the choice() helper. The Gateway adapter handles authentication and the evaluation request, meaning this integration does not require a separate TypeSafe API key for basic operation.

Configure Authentication

Vercel deployments can utilize OIDC authentication without managing static API keys. For local development, link the project and pull an OIDC token into the environment file:

vercel link
vercel env pull .env.local

Local tokens expire after 12 hours, so developers must refresh the file when the token expires. Alternatively, an AI Gateway API key can be created and set via the AI_GATEWAY_API_KEY environment variable. Note that an existing API key takes precedence over OIDC; updating the token will not fix a request still using an invalid key.

The adapter's convenience factory reads OIDC tokens from the environment. However, to avoid retaining expired tokens in long-running Node.js processes, it is recommended to call getVercelOidcToken() within each request. This fetches the current token from Vercel's request context, falling back to VERCEL_OIDC_TOKEN for local development.

Keep the evaluation strictly in the server route. The browser submits the ticket and receives the result without ever seeing the credentials.

Define the Routing Logic

Create a server file, such as src/lib/route-ticket.server.ts, to handle the model call. TanStack AI's evaluation API takes an adapter, shared state, and named questions.

import { choice, decide } from '@tanstack/ai';
import { createVercelGatewayDecider } from '@tanstack/ai-vercel-gateway';
import { getVercelOidcToken } from '@vercel/oidc';

export type Ticket = {
  subject: string;
  body: string;
};

export async function routeTicket(ticket: Ticket) {
  const credential = process.env.AI_GATEWAY_API_KEY || (await getVercelOidcToken());
  
  const result = await decide({
    adapter: createVercelGatewayDecider('typesafe-ai/jev', credential),
    state: ticket,
    questions: {
      queue: choice({
        instructions: 'Which team should handle this request first?',
        options: {
          billing: 'Invoice amounts, charges, and payment questions',
          technical: 'Product errors, outages, and integration failures',
          needs_review: 'Unclear requests or overlapping responsibilities',
        },
      }),
    },
    abortSignal: AbortSignal.timeout(10_000),
  });

  const { value, probability } = result.queue;
  const reviewRequired = value === 'needs_review' || probability < 0.85;

  return {
    proposedQueue: value,
    selectedProbability: probability,
    destination: reviewRequired ? 'needs_review' : value,
    reviewRequired,
  };
}

In this example, result.queue.value represents the selected option key, while probability describes the model's confidence. The code requires human review when Jev selects the review category or when the selected queue falls below a threshold (e.g., 0.85).

The 0.85 cutoff and ten-second deadline are application-specific choices. Developers should establish their threshold using labeled requests and choose a deadline that fits the form's expected response time. Even a high probability for needs_review sends the ticket to review, which is why the explicit category check remains separate from the probability cutoff.

Add the Server Route

Finally, create src/routes/api.triage.ts. The TanStack Start server-route convention exposes this file at /api/triage, allowing the handler to return a standard Response. This route receives the validated ticket data, calls routeTicket, and returns the routing decision to the client for further action.

Share

Sources

Tools mentioned