AI

AI Setup

Configure Vercel AI SDK providers and models in VitNode API config to use with c.get("ai").

VitNode integrates the Vercel AI SDK. Register models in vitnode.api.config.ts once, then resolve them inside any API handler via c.get("ai").

Quick start

1. Configure Models in API Config

You can configure models via string identifiers (using AI Gateway) or direct provider instances:

apps/api/src/vitnode.api.config.ts
import { openai } from '@ai-sdk/openai'
import { buildApiConfig } from '@vitnode/core/vitnode.config'

export const vitNodeApiConfig = buildApiConfig({
  ai: {
    models: [
      {
        id: 'default',
        name: 'GPT-4o Mini',
        model: openai('gpt-4o-mini'),
      },
    ],
  },
})

Set OPENAI_API_KEY in your .env file.


2. Use in Route Handlers

import { generateText } from 'ai'

handler: async (c) => {
  const { text } = await generateText({
    model: c.get('ai').model(), // Resolves the configured "default" model
    prompt: 'Write a summary of this discussion.',
  })

  return c.json({ text })
}

Multiple Models & Embeddings

Configure dedicated models for fast completions, reasoning, and vector embeddings:

apps/api/src/vitnode.api.config.ts
ai: {
  models: [
    { id: "default", name: "GPT-4o Mini", model: openai("gpt-4o-mini") },
    { id: "reasoning", name: "Claude 3.5 Sonnet", model: anthropic("claude-3-5-sonnet-20241022") },
  ],
  embeddingModels: [
    { id: "default", name: "Text Embedding 3", model: openai.embedding("text-embedding-3-small") },
  ],
}

Resolve specific models by ID:

const smartModel = c.get('ai').model('reasoning')
const embedModel = c.get('ai').embeddingModel()

Reading the Model List in the Browser

Provider instances and API keys stay on the server. What the browser gets is the public half of each entry - id, name, and the provider's model id string - published on the middleware route and read with useMiddlewareConfigQuery():

plugins/writer/src/pages/model-picker.tsx
import { useMiddlewareConfigQuery } from '@vitnode/core/tanstack/auth'

export const ModelPicker = () => {
  const { data } = useMiddlewareConfigQuery()

  if (data.ai.models.length === 0) return <p>AI is not configured.</p>

  return (
    <select className="w-full">
      {data.ai.models.map((model) => (
        <option key={model.id} value={model.id}>
          {model.name}
        </option>
      ))}
    </select>
  )
}

The first entry is the default - the one c.get("ai").model() resolves when a handler is given no id. The list is empty when no ai.models are configured, so a picker can hide itself rather than offering nothing.

Learn More