openai-assistants — quality + safety report

In the Skillier index (secondsky__openai-assistants) · scanned 2026-06-03 · engine: builtin+triage

A
Quality
90/100
Safety

2 heuristic flags to review

Heuristic flags from the builtin scanner, which is known to over-flag (it trips on legitimate env-reading integrations, security skills, and library .eval calls). This is NOT an authoritative malicious verdict — re-scan with SkillSpector for the authoritative result. Run the authoritative scan →

Skillproof quality grade A

📇 This skill is in the Skillier index (curated · deduped · quality-filtered). Install Skillier to route & load it into your AI client.

Quality notes

Skill is large (~3460 tokens)
medium · quality · body
→ Tighten to the essential procedure; move long reference material to linked files.
No explicit trigger / 'when to use'
low · quality · body
→ Add a 'When to use' section or 'Use this when …' line listing trigger conditions.

About this skill

OpenAI Assistants API v2 for stateful chatbots with Code Interpreter, File Search, RAG. Use for threads, vector stores, or encountering active run errors, indexing delays. ⚠️ Sunset August 26, 2026.

📄 Read the SKILL.md
---
name: openai-assistants
description: "OpenAI Assistants API v2 for stateful chatbots with Code Interpreter, File Search, RAG. Use for threads, vector stores, or encountering active run errors, indexing delays. ⚠️ Sunset August 26, 2026."
license: MIT
metadata:
  version: "2.0.0"
  openai_version: "6.9.1"
  last_verified: "2025-11-21"
  api_version: "v2"
  v1_deprecated: "2024-12-18"
  v2_sunset: "H1 2026"
  production_tested: true
  token_savings: "~60%"
  errors_prevented: 15
  templates_included: 8
  references_included: 8
  keywords:
    - openai assistants
    - assistants api
    - openai threads
    - openai runs
    - code interpreter assistant
    - file search openai
    - vector store openai
    - openai rag
    - assistant streaming
    - thread persistence
    - stateful chatbot
    - thread already has active run
    - run status polling
    - vector store error
---
# OpenAI Assistants API v2

**Status**: Production Ready (Deprecated H1 2026) | **Package**: openai@6.9.1
**Last Updated**: 2025-11-21 | **v2 Sunset**: H1 2026

---

## ⚠️ Important: Deprecation Notice

**OpenAI announced that the Assistants API will be deprecated in favor of the Responses API.**

**Timeline:**
- ✅ **Dec 18, 2024**: Assistants API v1 deprecated
- ⏳ **H1 2026**: Planned sunset of Assistants API v2
- ✅ **Now**: Responses API available (recommended for new projects)

**Should you still use this skill?**
- ✅ **Yes, if**: You have existing Assistants API code (12-18 month migration window)
- ✅ **Yes, if**: You need to maintain legacy applications
- ✅ **Yes, if**: Planning migration from Assistants → Responses
- ❌ **No, if**: Starting a new project (use openai-responses skill instead)

**Migration Path:** See `references/migration-to-responses.md` for complete migration guide.

---

## Quick Start (5 Minutes)

### 1. Installation

```bash
bun add openai@6.7.0  # preferred
# or: npm install openai@6.7.0
```

### 2. Environment Setup

```bash
export OPENAI_API_KEY="sk-..."
```

### 3. Basic Assistant

```typescript
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:**
- Assistants are persistent (stored server-side)
- Threads are persistent (conversation history)
- Runs execute the assistant on a thread
- Always poll or stream runs (they're async)
- Use `createAndPoll` for simplicity or streaming for real-time

---

## Core Concepts

**4 Key Objects:**

1. **Assistant** = AI agent with instructions + tools
2. **Thread** = Conversation (persists messages)
3. **Message** = Single message in thread (user or assistant)
4. **Run** = Execution of assistant on thread

**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.

---

## Critical Rules

### Always Do

✅ **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 Do

❌ **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

---

## Top 5 Errors Prevention

This skill prevents **15 documented errors**. Here are the top 5:

### Error #1: "Thread Already Has Active Run"
**Error**: `Can't create run: thread_xyz already has an active run`
**Prevention**: Check for active runs before creating new one:
```typescript
// 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 #2: Vector Store Indexing Timeout
**Error**: File search returns empty results immediately after upload
**Prevention**: Wait for indexing to complete:
```typescript
// 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 #3: Run Status Polling Infinite Loop
**Error**: Polling never terminates, hangs forever
**Prevention**: Add timeout and terminal status check:
```typescript
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 #4: Function Call Not Submitted
**Error**: Run stuck in `requires_action` status forever
**Prevention**: Submit tool outputs when required:
```typescript
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 #5: File Upload Format Not Supported
**Error**: `Invalid file format for Code Interpreter`
**Prevention**: Validate file format before upload:
```typescript
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`

---

## Common Use Cases

### Use Case 1: Simple Q&A Chatbot
**Template**: `templates/basic-assistant.ts` | **Time**: 10 minutes
```typescript
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
```

### Use Case 2: Document Q&A with RAG
**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.

### Use Case 3: Code Execution Assistant
**Template**: `templates/code-interpreter-assistant.ts` | **Time**: 20 minutes
**References**: Load `references/code-interpreter-guide.md` for setup, alternatives, and troubleshooting.

### Use Case 4: Function Calling Assistant
**Template**: `templates/function-calling-assistant.ts` | **Time**: 25 minutes

### Use Case 5: Streaming Chatbot
**Template**: `templates/streaming-assistant.ts` | **Time**: 15 minutes

---

## When to Load Detailed References

**Load `references/assistants-api-v2.md` when:**
- User needs complete API reference
- User asks about specific endpoints or parameters
- User needs rate limit information or quotas
- User wants architecture details

**Load `references/code-interpreter-guide.md` when:**
- User implementing code execution
- User asks about supported file formats for Code Interpreter
- User needs Code Interpreter alternatives (E2B, Modal)
- User encounters Code Interpreter errors

**Load `references/file-search-rag-guide.md` when:**
- User building RAG application
- User asks about vector stores setup
- User needs file search optimization strategies
- User scaling document search beyond basic setup

**Load `references/migration-from-v1.md` when:**
- User mentions Assistants API v1
- User upgrading from v1 to v2
- User asks about breaking changes (retrieval → file_search)
- User encounters v1 deprecation errors

**Load `references/migration-to-responses.md` when:**
- User planning future migration to Responses API
- User asks about Responses API comparison
- User mentions deprecation timeline
- User building new projects (recommend Responses API)

**Load `references/thread-lifecycle.md` when:**
- User building multi-turn conversations
- User asks about thread persistence patterns
- User needs conversation management strategies
- User optimizing thread usage or cleanup

**Load `references/top-errors.md` when:**
- User encounters any error (all 15 documented)
- User asks about troubleshooting
- User wants to prevent known issues
- User debugging production issues

**Load `references/vector-stores.md` when:**
- User scaling file search beyond basic setup
- User asks about file limits (10,000 files)
- User needs indexing optimization
- User managing vector store costs ($0.10/GB/day)

---

## Templates Available

**Production-ready code examples in `templates/`:**

- **`basic-assistant.ts`** - Minimal assistant setup (getting started)
- **`code-interpreter-assistant.ts`** - Code execution (Python

… (truncated)
Scan or optimize your own skill →

Want a live grade + an embeddable README badge? Run your skill through the free scanner.

Graded independently by Skillproof — nothing to sell the author. Quality is mechanical + corpus-grounded; safety flags are heuristic (builtin+triage), not a malicious verdict.