Skip to content
Tools

Provider Skills

A provider skill is a hosted skill, such as a PowerPoint skill, that Anthropic or OpenAI runs in its own sandbox.

Attach the skill IDs to the execution tool of the provider. The provider installs the skills and runs them. You only give the IDs.

  • Anthropic: attach skills to codeExecutionTool from @tanstack/ai-anthropic/tools.
  • OpenAI: put skills inside shellTool from @tanstack/ai-openai/tools. This needs the Responses API.

A skill does nothing without its execution tool. The tool starts the sandbox, and the skills run inside it.

Portable vs hosted skills

TanStack AI has two kinds of skills. Pick the one that fits:

  • Portable skills (withSkills) show a catalog and let the model call load_skill. They work on any model that can call tools. They need no sandbox on the server, and they read SKILL.md from a folder, a bundle, or your own store. Start with these.
  • Hosted skills (this page) run in the sandbox of the provider, by ID. They work with one provider only, and they need an execution tool. The provider runs them.

If you need the sandbox of the provider, for example to run code or make files, use hosted skills. For everything else, use portable skills.

Use only one kind in a chat() call. If you attach hosted skills to a code_execution or shell tool and also add withSkills, the middleware throws. The reason: the model gets two catalogs and two protocols.

Anthropic: skills on codeExecutionTool

1. Install the package

shell
npm i @tanstack/ai-anthropic

2. Add codeExecutionTool with skills

Import codeExecutionTool from @tanstack/ai-anthropic/tools, not from the root of the adapter. Pass a skills array as the second argument:

ts
import {
  chat,
  chatParamsFromRequest,
  toServerSentEventsResponse,
} from '@tanstack/ai'
import { anthropicText } from '@tanstack/ai-anthropic'
import { codeExecutionTool } from '@tanstack/ai-anthropic/tools'

export async function POST(request: Request) {
  const { messages, threadId, runId } = await chatParamsFromRequest(request)

  const stream = chat({
    adapter: anthropicText('claude-opus-5-5'),
    messages,
    threadId,
    runId,
    tools: [
      codeExecutionTool(
        { type: 'code_execution_20250825', name: 'code_execution' },
        {
          skills: [{ type: 'anthropic', skill_id: 'pptx', version: 'latest' }],
        },
      ),
    ],
  })

  return toServerSentEventsResponse(stream)
}

3. Try it

Ask your chat "Make a three-slide deck about our Q3 results." The model loads the pptx skill and makes the file in the sandbox of Anthropic.

The adapter does the setup for you:

  • It moves your skills into the top-level container.skills parameter of the request. The Anthropic API wants them there.
  • It adds the code-execution-2025-08-25 beta header. When skills are present, it also adds the skills-2025-10-02 beta header.

You do not set beta headers yourself.

Skill shape

Each item in the skills array is an AnthropicContainerSkill:

FieldTypeRequiredNotes
type'anthropic' | 'custom'yes'anthropic' for skills that Anthropic hosts. 'custom' for your own bundles.
skill_idstringyes1 to 64 characters.
versionstringnoA version string, or 'latest'. The default is 'latest'.

You can attach at most 8 skills to a request. If you pass more, or a skill_id that is not valid, the factory throws when you call it.

OpenAI: skills in shellTool (Responses API only)

The OpenAI shellTool takes an environment object, and that object can hold a skills array. This works only with the Responses API. The Chat Completions API does not support the shell tool.

1. Install the package

shell
npm i @tanstack/ai-openai

2. Add shellTool with skills

ts
import {
  chat,
  chatParamsFromRequest,
  toServerSentEventsResponse,
} from '@tanstack/ai'
import { openaiText } from '@tanstack/ai-openai'
import { shellTool } from '@tanstack/ai-openai/tools'

export async function POST(request: Request) {
  const { messages, threadId, runId } = await chatParamsFromRequest(request)

  const stream = chat({
    adapter: openaiText('gpt-6.1-sol'),
    messages,
    threadId,
    runId,
    tools: [
      shellTool({
        environment: {
          type: 'container_auto',
          skills: [
            { type: 'skill_reference', skill_id: 'skill_abc', version: '2' },
          ],
        },
      }),
    ],
  })

  return toServerSentEventsResponse(stream)
}

Replace skill_abc with the ID of your skill.

Skill shape

Each item in the skills array is a SkillReference:

FieldTypeRequiredNotes
type'skill_reference'yesAlways 'skill_reference' for OpenAI.
skill_idstringyesThe skill ID that OpenAI gives you.
versionstringnoA positive integer as a string (for example '2'), or 'latest'.

version is a string, not a number.

Advanced

What these factories support

The factories wire only hosted skills that you reference by ID:

  • Anthropic: type: 'anthropic' or type: 'custom'.
  • OpenAI: type: 'skill_reference'.

codeExecutionTool and shellTool do not handle inline bundles, local paths, or skill creation through the upload API.

Upgrade from 0.x

modelOptions.container.skills is not in 1.0. Pass skills to codeExecutionTool(config, { skills }).