Skip to content

Vercel AI SDK path (TypeScript)

Everyone starts Foundations f1–f7 · the augmented-LLM primitives

Build a trip-planner agent, TripMate, with the Vercel AI SDK in a 90-minute block.

It runs locally on Ollama, so you need no API key to start. If you have a Google Gemini key, swap to that instead.

You need no prior AI SDK experience. The challenges build on each other, so each one adds a single idea to the one before it.

  1. cd vercel-ai-sdk
  2. npm install
  3. ollama pull granite4.1:3b (the default local model; skip if you’ll use Gemini)
  4. npm run verify: don’t go further until you see every check pass
  5. npm run f1: your first agent call
You: Plan a weekend in Lisbon for me

TripMate:
  [calls lookupTraveler]                 -> Jag, London, hiking + food, £500
  [calls getWeather("Lisbon")]           -> 22°C, sunny, wildfire advisory
  [calls getFlights("London","Lisbon")]  -> TAP £142

  Hi Jag. Lisbon for £142 on TAP, 22°C and sunny. Heads up: smoke advisory
  mid-afternoon, so plan hikes for the morning.

By the end you have built that agent, streamed it, given it tools from a server you did not write, put it behind a web UI, and made it survive a tool failure.

You pick a provider by editing one line in shared/model.ts:

export const model = ollama("granite4.1:3b");
// export const model = google("gemini-2.5-flash");

Ollama is the default and needs no API key.

For Gemini, set GOOGLE_GENERATIVE_AI_API_KEY in your environment and swap the line.

Already have a key for another provider (OpenAI, Anthropic, Mistral, …)? Install its AI SDK package (e.g. npm install @ai-sdk/openai) and assign model the same way; the providers list has them all. One edit moves every challenge onto your provider.

Every challenge from f2 on is traced. The best way to read a run is autotel-devtools, a local browser trace viewer. Start it in one terminal, then run challenges in another:

npm run devtools          # terminal 1: autotel-devtools on http://127.0.0.1:4445
npm run f2                # terminal 2: the run streams into the browser, live

Open http://127.0.0.1:4445 and you get the run as a tree of spans you can click into: the model, the prompt and response, the timings, and the token usage.

The same spans also print to your console as a tree, so a run is readable even with no viewer open. This is autotel (debug: "pretty" for the console, devtools: true for the browser), wired in through instrument.ts. The Python path does the same through logfire, so a run looks the same whichever language you are in.

Start with npm run f1, which runs the first challenge once and prints the result.

For an interactive runner, run npm run dev to get a menu, pick a challenge, and it watches that file and re-runs on every save. If you already know which one you want, npm run dev -- p1 skips the menu and watches p1 directly.

A common Foundations trunk, then the tracks you choose between. Everyone does Foundations, then picks one track for the room session (Patterns, RAG, or Full-Stack). The others are take-home. Jump straight to a track if you already know the basics.

The workshop ends with a 20-minute discussion (see DISCUSSION.md): wherever you got to, the closing questions are the same — was working with the model what you expected, what surprised you, what did you learn. You can stop after Foundations and still contribute fully.

The arc follows Anthropic’s “Building effective agents”: first the augmented LLM, then workflows + agents (the Patterns track), retrieval (the RAG track), or a real app (the Full-Stack track).

Foundations (f1–f7): the augmented LLM

#ChallengeGoalCommand
f1Hello + the two inputsCall an agent; shape it with instructions vs prompt; stream the replynpm run f1
f2See the loop + tokensRead the message loop, count tokens, read the console tracenpm run f2
f3Structured outputTyped TripPitch via Output.object, no parsingnpm run f3
f4ToolsA tool fills a gap the model cannot; the loop needs steps to use itnpm run f4
f5GuardrailsA cheap check runs first and refuses off-topic or unsafe requestsnpm run f5
f6Descriptions (authoring lab)A description routes the model to the right toolnpm run f6
f7TestingProve the gate’s branches with a fake agent you inject, no real model callnpm run f7

Don’t just complete Foundations: experiment. Rerun each challenge with different instructions and watch what changes. How short can a prompt get before the agent loses the plot? Find where you have to spell things out, and where the model works it out on its own.

Then your choice of track. (The Discussion closes the workshop at the end.)

Patterns track (p1–p7): you orchestrate, then the model does

#ChallengeGoalCommand
p1Prompt chainingDraft, check with a code gate, then fix only what failednpm run p1
p2RoutingClassify the input, then branch in code to a specialistnpm run p2
p3ParallelizationFan out independent reviewers at once, then aggregatenpm run p3
p4Evaluator-optimizerScore and improve in a loop until a bar or a capnpm run p4
p5AgenticOne agent sequences three tools itself, no if/elsenpm run p5
p6DelegationAn orchestrator agent whose tools are other agentsnpm run p6
p7ConversationA multi-turn chat loop that streams and remembersnpm run p7

RAG track (r1–r2): ground the model in your own data

Needs a local embedding model: ollama pull embeddinggemma (separate from the chat model, and needed even if you chat on Gemini).

#ChallengeGoalCommand
r1RetrievalEmbed your docs, rank by similarity, hand the top matches to the model as a toolnpm run r1
r2ChunkingSplit long documents into passages so a specific question matches a specific paragraphnpm run r2

Full-stack track: the agent behind a web UI (assumes some frontend comfort)

You start from a ready, production-shaped template, a single Hono server on Node serving both the React useChat UI and the AI SDK agent, and build on it. Clone it with the workshop CLI, then add your own tool and watch its tool-call card render. See app/fullstack/ for the full lesson.

npx @jagreehal/ai-workshop fullstack-hono
cd fullstack-hono && npm install && npm run dev

Every challenge has a solution:<id> (e.g. npm run solution:f3). If the room moves on, run the solution and keep going; pace beats perfect completion.

Three self-serve tracks go further, top-level siblings of patterns and rag (do them any time after Foundations, not in the live block): npm run mcp (tools from a separate server), npm run resilience (errors as data on its own), and npm run guardrails-middleware (the output half of f5’s guardrail).

Each one has:

  • start/agent.ts: runs as-is, with TODOs to do
  • finish/agent.ts: the reference solution (npm run solution:<id>)
  • README.md: the lesson. It walks through the real code, gives you numbered build steps, lists the common traps, and ends with a verify step

Each challenge is self-contained. Open one file and the whole world is there, with the tools and data inlined. The only shared file is shared/model.ts.

Tools are duplicated across challenges on purpose, so you never have to dig through shared folders to follow a lesson.

The full-stack track is shaped differently: it is a separate template you clone with the workshop CLI (npx @jagreehal/ai-workshop fullstack-hono) and build on, not a start/ finish pair. See app/fullstack/.

The mcp track is also multi-process: a standalone MCP server in one terminal (npm run mcp:server) and the agent in another (npm run mcp).

If you get lost, ask four questions:

  1. What does the model know right now?
  2. What tool is available to help it?
  3. What shape of input does that tool expect?
  4. What does the tool return back into the loop?

Everything in the workshop is a variation on that loop: the model generates, decides when it needs a tool, you run the tool, the result goes back, and it repeats until the model can answer.

  • Node.js 22+
  • One of: Ollama with granite4.1:3b pulled, or a Google Gemini API key
  • For the RAG track only: Ollama with embeddinggemma pulled (a local embedding model, needed even on Gemini)
  • 8GB RAM recommended (for the local model)
ollama pull granite4.1:3b   # if using Ollama
ollama pull embeddinggemma  # if doing the RAG track
npm install
npm run verify

npm run verify checks that embeddinggemma is pulled when Ollama is up; that check is for the RAG track only and is not required if you are doing Foundations, Patterns, or Full-Stack.

  • Vercel AI SDK (ai): ToolLoopAgent, the agent class used in every challenge
  • Zod: typed tool argument schemas
  • Ollama (ai-sdk-ollama) or Google (@ai-sdk/google): the model
  • autotel: OpenTelemetry tracing, printed to the console with debug: "pretty"
  • Model Context Protocol (@ai-sdk/mcp, @modelcontextprotocol/sdk): mcp
  • Vite + React (@ai-sdk/react): the full-stack track’s chat UI
  • Playwright: the full-stack track’s end-to-end check

Stuck? See TROUBLESHOOTING.md.

  • Code (starter and solution files, scripts) — MIT; the LICENSE file ships alongside it.
  • Lessons (this and the challenge READMEs, diagrams) — CC BY-NC 4.0: share and adapt with attribution, not commercially. Build on the code freely; don’t resell the lessons.

© 2026 Jag Reehal.