Having Fun with Vercel’s AI SDK and AI Gateway Vercel's AI SDK and AI Gateway enable developers to integrate AI requests into applications, as demonstrated in a tutorial by Adam Rackis for generating fitness workouts. The AI Gateway provides a centralized API for multiple models with fallbacks and billing through Vercel. The tutorial includes code examples using the 'ai' npm package and emphasizes server-side calls to avoid CORS errors. We’ve all used AI tooling like Claude Code and Cursor to help us write code. This is a post about integrating AI features directly into software. In other words, making AI requests from within our application and integrating the responses. There’s no shortage of tools that do this, and for this post we’ll look at Vercel’s AI SDK and AI Gateway . Vercel’s AI SDK is a TypeScript utility that makes it simple to programmatically run AI requests for integration with existing software. It’s model-agnostic, so you can use pretty much any model you want, from Claude Sonnet to GPT-5. Chatbots have been done too many times arguably once is too many , so for this post we’ll do something a little different: we’ll use AI to help us create fitness workouts. We’ll prompt it clearly, provide reference material, and, most importantly, constrain the resulting format and structure so we can easily use the results and save these workouts in our own database for future use. The code for this post comes from my own fitness-tracking app, available here https://github.com/arackaf/fitness-tracker . It’s still a work in progress, so I don’t have a link I’m willing to share just yet. The work is currently in branch feature/ai-workout-template-generation , by the time you read this it might be in main . Installation Installation is simple enough, and Vercel did a genuinely impressive job of choosing a good npm package name here. npm i ai Before we get into actually making our requests, you need to run them against a service that’s hosting the model you want to use. To start, let’s use the lowest friction option: Vercel’s AI Gateway. So let’s head on over there https://vercel.com/adam-rackis/~/ai-gateway . Navigate to the API Keys screen. Create a new key there. Add it as an environment variable, likely in your .env file. AI GATEWAY API KEY="vck xyz" Benefits of the AI Gateway The AI Gateway serves as a single, centralized location to make requests to virtually any model, whether it’s from OpenAI, Anthropic, or others. It even allows you to specify which providers and models to run against and set fallbacks: for example, run this against Claude Sonnet 5, and if that fails, try Claude Sonnet 4.6. Or whatever combination you want, or with the providers themselves, not just the models. What’s also nice is that, even though you’re making requests against models from any provider, you’re interacting with, and getting billed by only Vercel who is charging you listed rates for the api calls, with no markup . The AI Gateway then provides you with detailed info about your requests and spending by model. As well as some breakdowns per API key you have configured. Our First Request We’ll start slow and basic. Like I said, we’ll be using AI to generate some workouts for us. Before doing it in a useful way, let’s write the equivalent of a “ Hello, World ” just to see that things are working. Since there are api keys with our money attached, we naturally need to make these calls from the server you’ll get a nice CORS error if you screw up and try to do this from the browser . I’m using TanStack, so we use Server Functions to specify server-only code. Here’s mine: js import { generateText } from "ai"; export const runVercelAiSdk = createServerFn { method: "GET", } .handler async { data } = { try { const { text } = await generateText { model: "anthropic/claude-sonnet-4.5", prompt: Give me a basic chest workout , } ; console.log { text } ; } catch error { console.error "Error using Vercel AI SDK", { error } ; } } ; I’m calling generateText , while passing a model name, as well as my prompt. Don’t worry about getting the model name exactly right: auto-complete will help you. This works and returns us a workout in the response text. This isn’t very useful yet. Yes, we could just… dump this text into our app for our user to look at, but we’ll look at output validation schemas in a minute. Using Providers Directly If you’re curious about using the ai-sdk directly against providers, without using the AI Gateway, there are clear instructions for doing just that in the docs https://ai-sdk.dev/providers/ai-sdk-providers . Let’s take a very brief look at using Anthropic https://ai-sdk.dev/providers/ai-sdk-providers/anthropic . We’ll go to the Anthropic’s console https://platform.claude.com/settings/keys , hit the Create Key button tell the modal you do in fact need an API key , and create it As before, add it as an env var. ANTHROPIC API KEY="sk-ant-xyz" With that set up, we’ll install a new package https://www.npmjs.com/package/@ai-sdk/anthropic?activeTab . npm i @ai-sdk/anthropic Then import the anthropic function from that package. js import { anthropic } from "@ai-sdk/anthropic"; And pick the model you want to use. As before, you’ll get nice auto-complete for the model selection. We’ll use Sonnet 4.5 again. js const claudeSonnet45Model = anthropic "claude-sonnet-4-5" ; And then that claudeSonnet45Model object gets passed as the model name. js export const runVercelAiSdkWithAnthropic = createServerFn { method: "GET", } .handler async { data } = { try { const { text } = await generateText { model: claudeSonnet45Model, prompt: Give me a basic chest workout , } ; console.log "Anthropic result", { text } ; } catch error { console.error "Error using Vercel AI SDK", { error } ; } } ; Simple as that, and it still works Of course, we’re not using Vercel’s AI Gateway anymore, so if you want to track costs, head over to Anthropic’s console https://platform.claude.com/settings/keys to see what your API key is being billed for. A Real Use Case Getting a random wall of text from an AI model isn’t the most useful result, especially if the goal is to save new things into our database. In this case, we want to save new workouts. Since this is a fitness tracking app, we already have forms for users to manually enter new workouts, components to display these workout templates, and backend endpoints server functions to save those manually created workouts to our database. Wouldn’t it be neat if we could get these AI models to create our new workouts in exactly that same format, so we could reuse those same components to display the workout our AI model created, and add a server function to save them if the user likes them? AI does not change the benefits of component reuse that software engineers have always strived for. The AI SDK allows us to specify a Zod validation schema for the output we get back, which is exactly what we want. If you’re like me, you’re not normally using Zod https://zod.dev/ for regular TypeScript types that don’t cross the wire. Our Zod Schema My normal TypeScript type looks like this for a workout or workout template, really, since an actual workout you do can be based on this . export type WorkoutTemplate = typeof workoutTemplate.$inferInsert; export type WorkoutTemplateState = Prettify< Omit