Skip to content
Docs

Add skills to your AI SDK agents

Use uploadSkill and provider references in the AI SDK to bundle a SKILL.md and supporting files, then attach the skill to generateText, streamText, or a ToolLoopAgent call on Anthropic or OpenAI.

5 min read
Last updated June 25, 2026

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.

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 or OpenAI's shell tool
  • Reuse one skill across providers by merging provider references

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

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.

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.

scripts/upload-skill.ts
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.

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.

With Anthropic, enable the code execution tool and pass the providerReference in the container.skills array under providerOptions.

app/api/agent/route.ts
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,
},
});

With OpenAI, enable the shell tool and pass the providerReference in the tool's environment.skills array.

app/api/agent/route.ts
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.',
});

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.

lib/ai/skill-agent.ts
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.',
});

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.

scripts/upload-skill.ts
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_...' }

uploadSkill resolves to an UploadSkillResult with the following fields:

FieldTypeDescription
providerReferenceProviderReferenceMaps provider names to their skill IDs
displayTitlestring?Human-readable title, when the provider supports it and you set one
namestring?Name the provider infers from the skill files
descriptionstring?Description the provider infers from the skill files
latestVersionstring?Latest version identifier the provider assigns
providerMetadataobject?Extra provider-specific metadata, such as timestamps
warningsWarning[]Warnings for unsupported options, such as displayTitle on OpenAI

These providers support skills() and skill uploads:

ProviderFactory method
Anthropicanthropic.skills()
OpenAIopenai.skills()
  • Read the uploadSkill reference for the full list of options and return fields.
  • See Tool calling to set up the code execution and shell tools that run a skill.
  • Learn to build agents in Building agents with the ToolLoopAgent.
  • Explore Skills in AI SDK Harnesses to use skills with coding-agent harnesses.

Was this helpful?

supported.