# Add skills to your AI SDK agents

**Author:** Ben Sabic

---

With skill uploads, you can give an agent a reusable skill, which is a bundle of files (such as a `SKILL.md`) that a provider loads inside a sandboxed container. The model can then follow the skill's instructions and run its bundled code while it works.

The AI SDK's `uploadSkill` function sends the bundle to a provider and returns a `ProviderReference` that you attach to later inference calls, so domain-specific behavior and files stay out of your prompt. Anthropic and OpenAI both support skill uploads, and once you've uploaded a skill you can reference it from `generateText`, `streamText`, or a `ToolLoopAgent` call.

## Overview

In this guide, you'll learn how to:

- Upload a skill bundle to a provider with `uploadSkill`
  
- Reference skills from `generateText`, `streamText`, or `ToolLoopAgent`
  
- Attach a skill using [Anthropic's code execution tool](https://ai-sdk.dev/providers/ai-sdk-providers/anthropic#code-execution) or [OpenAI's shell tool](https://ai-sdk.dev/providers/ai-sdk-providers/openai#shell-tool)
  
- Reuse one skill across providers by merging provider references
  

## Prerequisites

Before you begin, make sure you have:

- The `ai` package and a provider package (e.g., `@ai-sdk/anthropic`)
  
- A provider that supports skills (Anthropic or OpenAI)
  
- A skill bundle on disk, with at least a `SKILL.md`
  

## What is a skill?

A skill is a bundle of files (for example, a `SKILL.md` describing the skill's behavior) that a provider can load in a sandboxed container environment. When you upload a skill, the AI SDK returns a `ProviderReference`, a `Record<string, string>` that maps each provider's name to that provider's own skill identifier. The same `ProviderReference` shape identifies other provider assets too, including uploaded media files, so the pattern stays consistent across asset types.

## Steps

### Upload a skill

Call `uploadSkill` with the provider's skill API and the files you want to upload. It returns a `providerReference` that points to the uploaded skill.

`import { uploadSkill } from 'ai'; import { anthropic } from '@ai-sdk/anthropic'; import { readFileSync } from 'fs'; const { providerReference } = await uploadSkill({ api: anthropic.skills(), files: [{ path: 'my-skill/SKILL.md', content: readFileSync('./SKILL.md') }, { path: 'my-skill/helper.py', content: readFileSync('./helper.py') }, ], displayTitle: 'My Skill', });` Each file has a relative `path` and `content`. Provide `content` as a `Uint8Array`, for example from `readFileSync`, or as a base64-encoded string. As a shorthand, you can pass the provider instance directly to `api` (for example, `api: anthropic`) and the SDK calls `.skills()` for you. ### Attach the skill to an inference call Pass the `providerReference` when you run inference. Each provider looks up its own skill ID from the reference, and the SDK throws an error if the reference has no entry for the provider you're using. How you attach the skill depends on the provider. #### Anthropic With Anthropic, enable the code execution tool and pass the `providerReference` in the `container.skills` array under `providerOptions`. `import { generateText } from 'ai'; import { anthropic, type AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; // providerReference comes from uploadSkill const { text } = await generateText({ model: anthropic('claude-sonnet-4-6'), tools: { code_execution: anthropic.tools.codeExecution_20260120(), }, prompt: 'Use the skill to complete the task.', providerOptions: { anthropic: { container: { skills: [{ type: 'custom', providerReference }], }, } satisfies AnthropicLanguageModelOptions, }, });` #### OpenAI With OpenAI, enable the shell tool and pass the `providerReference` in the tool's `environment.skills` array. `import { generateText } from 'ai'; import { openai } from '@ai-sdk/openai'; // providerReference comes from uploadSkill const { text } = await generateText({ model: openai.responses('gpt-5.2'), tools: { shell: openai.tools.shell({ environment: { type: 'containerAuto', skills: [{ type: 'skillReference', providerReference }], }, }), }, prompt: 'Use the skill to complete the task.', });` ## Use a skill in a `ToolLoopAgent` The `ToolLoopAgent` accepts the same `tools` and `providerOptions` as `generateText`, so you attach an uploaded skill to an agent with the same configuration. Define the agent once with the container tool and the skill reference, then reuse it across your app. `import { ToolLoopAgent } from 'ai'; import { anthropic, type AnthropicLanguageModelOptions } from '@ai-sdk/anthropic'; // providerReference comes from uploadSkill const agent = new ToolLoopAgent({ model: anthropic('claude-sonnet-4-6'), tools: { code_execution: anthropic.tools.codeExecution_20260120(), }, providerOptions: { anthropic: { container: { skills: [{ type: 'custom', providerReference }], }, } satisfies AnthropicLanguageModelOptions, }, }); const { text } = await agent.generate({ prompt: 'Use the skill to complete the task.', });` ## Reuse a skill across multiple providers To use one skill with more than one provider, upload it to each provider and merge the references into a single `ProviderReference`. During inference, each provider finds its own skill ID in the merged reference, so the same object works regardless of which provider handles the request. `import { uploadSkill } from 'ai'; import { anthropic } from '@ai-sdk/anthropic'; import { openai } from '@ai-sdk/openai'; const [openaiUpload, anthropicUpload] = await Promise.all([ uploadSkill({ api: openai.skills(), files: [{ path: 'my-skill/SKILL.md', content: skillSource }], }), uploadSkill({ api: anthropic.skills(), files: [{ path: 'my-skill/SKILL.md', content: skillSource }], displayTitle: 'My Skill', }), ]); const mergedReference = { ...openaiUpload.providerReference, ...anthropicUpload.providerReference, }; // mergedReference: { openai: 'sk_...', anthropic: 'sk_...' }` ## What `uploadSkill` returns `uploadSkill` resolves to an `UploadSkillResult` with the following fields: | Field               | Type                | Description                                                         | | ------------------- | ------------------- | ------------------------------------------------------------------- | | `providerReference` | `ProviderReference` | Maps provider names to their skill IDs                              | | `displayTitle`      | `string?`           | Human-readable title, when the provider supports it and you set one | | `name`              | `string?`           | Name the provider infers from the skill files                       | | `description`       | `string?`           | Description the provider infers from the skill files                | | `latestVersion`     | `string?`           | Latest version identifier the provider assigns                      | | `providerMetadata`  | `object?`           | Extra provider-specific metadata, such as timestamps                | | `warnings`          | `Warning[]`         | Warnings for unsupported options, such as `displayTitle` on OpenAI  | ## Supported providers These providers support `skills()` and skill uploads: | Provider  | Factory method       | | --------- | -------------------- | | Anthropic | `anthropic.skills()` | | OpenAI    | `openai.skills()`    | ## Next steps - Read the [`uploadSkill`](https://ai-sdk.dev/v7/docs/reference/ai-sdk-core/upload-skill) [reference](https://ai-sdk.dev/v7/docs/reference/ai-sdk-core/upload-skill) for the full list of options and return fields.
  
- See [Tool calling](https://ai-sdk.dev/docs/ai-sdk-core/tools-and-tool-calling) to set up the code execution and shell tools that run a skill.
  
- Learn to build agents in [Building agents](https://ai-sdk.dev/docs/agents/building-agents) with the `ToolLoopAgent`.
  
- Explore [Skills](https://ai-sdk.dev/v7/docs/ai-sdk-harnesses/skills) in AI SDK Harnesses to use skills with coding-agent harnesses.

---

[View full KB sitemap](/kb/sitemap.md)
