**Status**: Production Ready (Deprecated H1 2026) | **Package**: openai@6.9.1
/plugin marketplace add secondsky/claude-skills/plugin install openai-assistants@claude-skillsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/assistants-api-v2.mdreferences/code-interpreter-guide.mdreferences/file-search-rag-guide.mdreferences/migration-from-v1.mdreferences/migration-to-responses.mdreferences/thread-lifecycle.mdreferences/top-errors.mdreferences/vector-stores.mdscripts/check-versions.shtemplates/basic-assistant.tstemplates/code-interpreter-assistant.tstemplates/file-search-assistant.tstemplates/function-calling-assistant.tstemplates/package.jsontemplates/streaming-assistant.tstemplates/thread-management.tstemplates/vector-store-setup.tsStatus: Production Ready (Deprecated H1 2026) | Package: openai@6.9.1 Last Updated: 2025-11-21 | v2 Sunset: H1 2026
OpenAI announced that the Assistants API will be deprecated in favor of the Responses API.
Timeline:
Should you still use this skill?
Migration Path: See references/migration-to-responses.md for complete migration guide.
bun add openai@6.7.0 # preferred
# or: npm install openai@6.7.0
export OPENAI_API_KEY="sk-..."
import OpenAI from 'openai'
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })
// 1. Create an assistant
const assistant = await openai.beta.assistants.create({
name: "Math Tutor",
instructions: "You are a helpful math tutor. Answer math questions clearly.",
model: "gpt-4-1106-preview",
})
// 2. Create a thread (conversation)
const thread = await openai.beta.threads.create()
// 3. Add a message
await openai.beta.threads.messages.create(thread.id, {
role: "user",
content: "What is 12 * 34?",
})
// 4. Create and poll run
const run = await openai.beta.threads.runs.createAndPoll(thread.id, {
assistant_id: assistant.id,
})
// 5. Get messages
if (run.status === 'completed') {
const messages = await openai.beta.threads.messages.list(thread.id)
console.log(messages.data[0].content[0].text.value)
}
CRITICAL:
createAndPoll for simplicity or streaming for real-time4 Key Objects:
Lifecycle:
Assistant (create once) + Thread (per conversation) + Message (add user input) → Run (execute) → Messages (get response)
Load references/assistants-api-v2.md for complete architecture, objects, workflows, and pricing details.
✅ Poll or stream runs - runs are async, don't assume immediate completion
✅ Check run status - handle requires_action, failed, cancelled, expired
✅ Handle function calls - submit tool outputs when requires_action
✅ Store thread IDs - reuse threads for multi-turn conversations
✅ Set timeouts - vector store indexing can take minutes for large files
✅ Validate file uploads - check supported formats and size limits
✅ Use structured instructions - clear, specific assistant instructions
✅ Handle rate limits - implement exponential backoff
✅ Clean up unused resources - delete old assistants/threads to save costs
✅ Use latest API version - Assistants API v2 (v1 deprecated Dec 2024)
❌ Never skip run polling - runs don't complete instantly
❌ Never reuse run IDs - create new run for each interaction
❌ Never assume file indexing is instant - vector stores need time
❌ Never ignore requires_action status - function calls need your response
❌ Never hardcode assistant IDs - use environment variables
❌ Never create new assistant per request - reuse assistants
❌ Never exceed file limits - 10,000 files per vector store, 10GB per file
❌ Never use Code Interpreter for production - use sandboxed execution instead
❌ Never skip error handling - API calls can fail
❌ Never start new projects with Assistants API - use Responses API instead
This skill prevents 15 documented errors. Here are the top 5:
Error: Can't create run: thread_xyz already has an active run
Prevention: Check for active runs before creating new one:
// Get runs and check status
const runs = await openai.beta.threads.runs.list(thread.id)
const activeRun = runs.data.find(r => ['in_progress', 'queued'].includes(r.status))
if (activeRun) {
// Cancel or wait
await openai.beta.threads.runs.cancel(thread.id, activeRun.id)
}
// Now create new run
const run = await openai.beta.threads.runs.create(thread.id, {...})
See: references/top-errors.md #1
Error: File search returns empty results immediately after upload Prevention: Wait for indexing to complete:
// Upload file
const file = await openai.files.create({
file: fs.createReadStream('document.pdf'),
purpose: 'assistants',
})
// Add to vector store
await openai.beta.vectorStores.files.create(vectorStore.id, {
file_id: file.id,
})
// Wait for indexing (poll file_counts)
let vs = await openai.beta.vectorStores.retrieve(vectorStore.id)
while (vs.file_counts.in_progress > 0) {
await new Promise(resolve => setTimeout(resolve, 1000))
vs = await openai.beta.vectorStores.retrieve(vectorStore.id)
}
See: references/top-errors.md #2
Error: Polling never terminates, hangs forever Prevention: Add timeout and terminal status check:
const maxAttempts = 60 // 60 seconds
let attempts = 0
while (attempts < maxAttempts) {
const run = await openai.beta.threads.runs.retrieve(thread.id, run.id)
if (['completed', 'failed', 'cancelled', 'expired', 'requires_action'].includes(run.status)) {
break
}
await new Promise(resolve => setTimeout(resolve, 1000))
attempts++
}
if (attempts >= maxAttempts) {
throw new Error('Run polling timeout')
}
See: references/top-errors.md #3
Error: Run stuck in requires_action status forever
Prevention: Submit tool outputs when required:
const run = await openai.beta.threads.runs.createAndPoll(thread.id, {
assistant_id: assistant.id,
})
if (run.status === 'requires_action') {
const toolCalls = run.required_action.submit_tool_outputs.tool_calls
const toolOutputs = toolCalls.map(call => ({
tool_call_id: call.id,
output: JSON.stringify(executeTool(call.function.name, call.function.arguments)),
}))
await openai.beta.threads.runs.submitToolOutputsAndPoll(thread.id, run.id, {
tool_outputs: toolOutputs,
})
}
See: references/top-errors.md #4
Error: Invalid file format for Code Interpreter
Prevention: Validate file format before upload:
const supportedFormats = {
code_interpreter: ['.c', '.cpp', '.csv', '.docx', '.html', '.java', '.json', '.md', '.pdf', '.php', '.pptx', '.py', '.rb', '.tex', '.txt', '.css', '.js', '.sh', '.ts'],
file_search: ['.c', '.cpp', '.docx', '.html', '.java', '.json', '.md', '.pdf', '.php', '.pptx', '.py', '.rb', '.tex', '.txt', '.css', '.js', '.sh', '.ts'],
}
const fileExtension = path.extname(filePath)
if (!supportedFormats.code_interpreter.includes(fileExtension)) {
throw new Error(`Unsupported file format: ${fileExtension}`)
}
// Now safe to upload
const file = await openai.files.create({
file: fs.createReadStream(filePath),
purpose: 'assistants',
})
See: references/top-errors.md #5
For complete error catalog (all 15 errors): See references/top-errors.md
Template: templates/basic-assistant.ts | Time: 10 minutes
const assistant = await openai.beta.assistants.create({
name: "Support Bot",
instructions: "Answer customer questions professionally.",
model: "gpt-4-1106-preview",
})
// Per conversation: create thread → add message → run → get response
Template: templates/file-search-assistant.ts | Time: 30 minutes
References: Load references/file-search-rag-guide.md and references/vector-stores.md for complete implementation.
Template: templates/code-interpreter-assistant.ts | Time: 20 minutes
References: Load references/code-interpreter-guide.md for setup, alternatives, and troubleshooting.
Template: templates/function-calling-assistant.ts | Time: 25 minutes
Template: templates/streaming-assistant.ts | Time: 15 minutes
Load references/assistants-api-v2.md when:
Load references/code-interpreter-guide.md when:
Load references/file-search-rag-guide.md when:
Load references/migration-from-v1.md when:
Load references/migration-to-responses.md when:
Load references/thread-lifecycle.md when:
Load references/top-errors.md when:
Load references/vector-stores.md when:
Production-ready code examples in templates/:
basic-assistant.ts - Minimal assistant setup (getting started)code-interpreter-assistant.ts - Code execution (Python code runner)file-search-assistant.ts - Document Q&A (RAG application)function-calling-assistant.ts - External tools (API integration)streaming-assistant.ts - Real-time responses (streaming output)thread-management.ts - Multi-turn conversations (chatbot)vector-store-setup.ts - Vector store configuration (file search setup)package.json - Dependencies (project setup)Required:
Optional:
{
"dependencies": {
"openai": "^6.7.0"
}
}
Version Notes:
This skill is based on production usage:
openai@6.7.0OPENAI_API_KEY environment variablerequires_action status (if using function calling)Questions? Issues?
references/top-errors.md for all 15 documented errorstemplates/ for production-ready code examplesreferences/migration-to-responses.md for future-proofing⚠️ Reminder: This API is deprecated. For new projects, use the Responses API instead. See references/migration-to-responses.md for migration guide.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.