Vercel AI SDK Usage Notes (from the archives)

aivercel-ai-sdktypescriptnotes

A collection of code examples and notes from working with the Vercel AI SDK.

Code Execution

Basic example using Claude's code execution tool:

import {
  anthropic,
  createAnthropic,
} from "@ai-sdk/anthropic";
 
const anthropicClient = createAnthropic();
await generateText({
  model: anthropicClient("claude-haiku-4-5"),
  prompt:
    "Calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].",
  tools: {
    code_execution: anthropic.tools.codeExecution_20250825(),
  },
});

Using Skills

Generating Word Docs

We need to use the Vercel AI SDK piece to send messages, but we have to use the Anthropic Foundry SDK to download the generated files using the beta files API.

import { writeFileSync } from "node:fs";
import {
  type AnthropicProviderOptions,
  anthropic,
  createAnthropic,
} from "@ai-sdk/anthropic";
import { AnthropicFoundry } from "@anthropic-ai/foundry-sdk";
import { generateText } from "ai";
 
const main = async () => {
  const anthropicClient = new AnthropicFoundry();
  const anthropic = createAnthropic();
 
  const result = await generateText({
    model: anthropic("claude-haiku-4-5"),
    prompt:
      "Write a haiku about the sea and include it in a word doc that also explains the history of haikus.",
    tools: {
      code_execution: anthropic.tools.codeExecution_20250825(),
    },
    maxRetries: 0,
    providerOptions: {
      anthropic: {
        container: {
          skills: [
            {
              type: "anthropic",
              skillId: "pdf",
            },
          ],
        },
      } satisfies AnthropicProviderOptions,
    },
  });
 
  console.log("Result:", result.text);
 
  const fileIds = [];
  for (const toolResult of result.toolResults) {
    if (
      toolResult.type === "tool-result" &&
      toolResult.toolName === "code_execution"
    ) {
      for (const content of toolResult.output.content) {
        if (content.type === "bash_code_execution_output") {
          fileIds.push(content.file_id);
        }
      }
    }
  }
 
  // Download the generated files
  for (const fileId of fileIds) {
    const fileMetadata = await anthropicClient.beta.files.retrieveMetadata(
      fileId,
      { betas: ["files-api-2025-04-14"] },
    );
    const fileContent = await anthropicClient.beta.files.download(fileId, {
      betas: ["files-api-2025-04-14"],
    });
 
    writeFileSync(
      fileMetadata.filename,
      Buffer.from(await fileContent.arrayBuffer()),
    );
    console.log(`Downloaded: ${fileMetadata.filename}`);
  }
};

Connecting to Claude Connectors

PubMed Data Connector

const result = await generateText({
  model: anthropicAiSdkClient("claude-haiku-4-5"),
  prompt,
  providerOptions: {
    anthropic: {
      mcpServers: [
        {
          type: "url",
          name: "pubmedMcp",
          url: "https://pubmed.mcp.claude.com/mcp",
        },
      ],
    } satisfies AnthropicProviderOptions,
  },
});

Clinical Trials Data Connector

const result = await generateText({
  model: anthropicAiSdkClient("claude-haiku-4-5"),
  prompt,
  providerOptions: {
    anthropic: {
      mcpServers: [
        {
          type: "url",
          name: "clinicalTrialsMcp",
          url: "https://mcp.deepsense.ai/clinical_trials/mcp",
        },
      ],
    } satisfies AnthropicProviderOptions,
  },
});

Random Tips

  • Claude, and most LLMs, love assuming that anything that happens after their training cutoff date is not real or relevant. This means that when using connectors that provide up-to-date information, it's often useful to include the current date in the system prompt.