Build stateful chatbots with OpenAI Assistants API v2 - Code Interpreter, File Search (10k files), Function Calling. Deprecated (sunset August 2026); use openai-responses for new projects. Use when: maintaining legacy chatbots, implementing RAG with vector stores, or troubleshooting thread errors, vector store delays.
Installation
Details
Usage
After installing, this skill will be available to your AI coding assistant.
Verify installation:
skills listSkill Instructions
name: openai-assistants description: | Build stateful chatbots with OpenAI Assistants API v2 - Code Interpreter, File Search (10k files), Function Calling. ⚠️ Deprecated (sunset August 26, 2026); use openai-responses for new projects.
Use when: maintaining legacy chatbots, implementing RAG with vector stores, or troubleshooting "thread has active run", vector store delays, polling timeouts, or file upload errors.
OpenAI Assistants API v2
Status: Production Ready (⚠️ Deprecated - Sunset August 26, 2026) Package: openai@6.15.0 Last Updated: 2026-01-03 v1 Deprecated: December 18, 2024 v2 Sunset: August 26, 2026 (migrate to Responses API)
⚠️ Deprecation Notice
OpenAI is deprecating Assistants API in favor of Responses API.
Timeline: v1 deprecated Dec 18, 2024 | v2 sunset August 26, 2026
Use this skill if: Maintaining legacy apps or migrating existing code (12-18 month window)
Don't use if: Starting new projects (use openai-responses skill instead)
Migration: See references/migration-to-responses.md
Quick Start
npm install openai@6.15.0
import OpenAI from 'openai';
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
// 1. Create assistant
const assistant = await openai.beta.assistants.create({
name: "Math Tutor",
instructions: "You are a math tutor. Use code interpreter for calculations.",
tools: [{ type: "code_interpreter" }],
model: "gpt-4o",
});
// 2. Create thread
const thread = await openai.beta.threads.create();
// 3. Add message
await openai.beta.threads.messages.create(thread.id, {
role: "user",
content: "Solve: 3x + 11 = 14",
});
// 4. Run assistant
const run = await openai.beta.threads.runs.create(thread.id, {
assistant_id: assistant.id,
});
// 5. Poll for completion
let status = await openai.beta.threads.runs.retrieve(thread.id, run.id);
while (status.status !== 'completed') {
await new Promise(r => setTimeout(r, 1000));
status = await openai.beta.threads.runs.retrieve(thread.id, run.id);
}
// 6. Get response
const messages = await openai.beta.threads.messages.list(thread.id);
console.log(messages.data[0].content[0].text.value);
Core Concepts
Four Main Objects:
- Assistants: Configured AI with instructions (max 256k chars in v2, was 32k in v1), model, tools, metadata
- Threads: Conversation containers with persistent message history (max 100k messages)
- Messages: User/assistant messages with optional file attachments
- Runs: Async execution with states (queued, in_progress, requires_action, completed, failed, expired)
Key API Patterns
Assistants
const assistant = await openai.beta.assistants.create({
model: "gpt-4o",
instructions: "System prompt (max 256k chars in v2)",
tools: [{ type: "code_interpreter" }, { type: "file_search" }],
tool_resources: { file_search: { vector_store_ids: ["vs_123"] } },
});
Key Limits: 256k instruction chars (v2), 128 tools max, 16 metadata pairs
Threads & Messages
// Create thread with messages
const thread = await openai.beta.threads.create({
messages: [{ role: "user", content: "Hello" }],
});
// Add message with attachments
await openai.beta.threads.messages.create(thread.id, {
role: "user",
content: "Analyze this",
attachments: [{ file_id: "file_123", tools: [{ type: "code_interpreter" }] }],
});
// List messages
const msgs = await openai.beta.threads.messages.list(thread.id);
Key Limits: 100k messages per thread
Runs
// Create run with optional overrides
const run = await openai.beta.threads.runs.create(thread.id, {
assistant_id: "asst_123",
additional_messages: [{ role: "user", content: "Question" }],
max_prompt_tokens: 1000,
max_completion_tokens: 500,
});
// Poll until complete
let status = await openai.beta.threads.runs.retrieve(thread.id, run.id);
while (['queued', 'in_progress'].includes(status.status)) {
await new Promise(r => setTimeout(r, 1000));
status = await openai.beta.threads.runs.retrieve(thread.id, run.id);
}
Run States: queued → in_progress → requires_action (function calling) / completed / failed / cancelled / expired (10 min max)
Streaming
const stream = await openai.beta.threads.runs.stream(thread.id, { assistant_id });
for await (const event of stream) {
if (event.event === 'thread.message.delta') {
process.stdout.write(event.data.delta.content?.[0]?.text?.value || '');
}
}
Key Events: thread.run.created, thread.message.delta (streaming content), thread.run.step.delta (tool progress), thread.run.completed, thread.run.requires_action (function calling)
Tools
Code Interpreter
Runs Python code in sandbox. Generates charts, processes files (CSV, JSON, PDF, images). Max 512MB per file.
// Attach file to message
attachments: [{ file_id: "file_123", tools: [{ type: "code_interpreter" }] }]
// Access generated files
for (const content of message.content) {
if (content.type === 'image_file') {
const fileContent = await openai.files.content(content.image_file.file_id);
}
}
File Search (RAG)
Semantic search with vector stores. 10,000 files max (v2, was 20 in v1). Pricing: $0.10/GB/day (1GB free).
// Create vector store
const vs = await openai.beta.vectorStores.create({ name: "Docs" });
await openai.beta.vectorStores.files.create(vs.id, { file_id: "file_123" });
// Wait for indexing
let store = await openai.beta.vectorStores.retrieve(vs.id);
while (store.status === 'in_progress') {
await new Promise(r => setTimeout(r, 2000));
store = await openai.beta.vectorStores.retrieve(vs.id);
}
// Use in assistant
tool_resources: { file_search: { vector_store_ids: [vs.id] } }
⚠️ Wait for status: 'completed' before using
Function Calling
Submit tool outputs when run.status === 'requires_action':
if (run.status === 'requires_action') {
const toolCalls = run.required_action.submit_tool_outputs.tool_calls;
const outputs = toolCalls.map(tc => ({
tool_call_id: tc.id,
output: JSON.stringify(yourFunction(JSON.parse(tc.function.arguments))),
}));
run = await openai.beta.threads.runs.submitToolOutputs(thread.id, run.id, {
tool_outputs: outputs,
});
}
File Formats
Code Interpreter: .c, .cpp, .csv, .docx, .html, .java, .json, .md, .pdf, .php, .pptx, .py, .rb, .tex, .txt, .css, .jpeg, .jpg, .js, .gif, .png, .tar, .ts, .xlsx, .xml, .zip (512MB max)
File Search: .c, .cpp, .docx, .html, .java, .json, .md, .pdf, .php, .pptx, .py, .rb, .tex, .txt, .css, .js, .ts, .go (512MB max)
Known Issues
1. Thread Already Has Active Run
Error: 400 Can't add messages to thread_xxx while a run run_xxx is active.
Fix: Cancel active run first: await openai.beta.threads.runs.cancel(threadId, runId)
2. Run Polling Timeout Long-running tasks (Code Interpreter, File Search) may exceed polling windows. Fix: Set max timeout (e.g., 5 min) and cancel if exceeded
3. Vector Store Not Ready
Using vector store before indexing completes.
Fix: Poll vectorStores.retrieve() until status === 'completed' (see File Search section)
4. File Upload Format Issues Unsupported file formats cause silent failures. Fix: Validate file extensions before upload (see File Formats section)
See references/top-errors.md for complete catalog.
Relationship to Other Skills
openai-api (Chat Completions): Stateless, manual history, direct responses. Use for simple generation.
openai-responses (Responses API): ✅ Recommended for new projects. Better reasoning, modern MCP integration, active development.
openai-assistants: ⚠️ Deprecated H1 2026. Use for legacy apps only. Migration: references/migration-to-responses.md
v1 to v2 Migration
v1 deprecated: Dec 18, 2024
Key Changes: retrieval → file_search, vector stores (10k files vs 20), 256k instructions (vs 32k), message-level file attachments
See references/migration-from-v1.md
Templates: templates/basic-assistant.ts, code-interpreter-assistant.ts, file-search-assistant.ts, function-calling-assistant.ts, streaming-assistant.ts
References: references/top-errors.md, thread-lifecycle.md, vector-stores.md, migration-to-responses.md, migration-from-v1.md
Related Skills: openai-responses (recommended), openai-api
Last Updated: 2025-11-27 Package: openai@6.9.1 Status: Production Ready (⚠️ Deprecated - Sunset H1 2026)
More by jezweb
View allSelf-hosted auth for TypeScript/Cloudflare Workers with social auth, 2FA, passkeys, organizations, RBAC, and 15+ plugins. Requires Drizzle ORM or Kysely for D1 (no direct adapter). Self-hosted alternative to Clerk/Auth.js. Use when: self-hosting auth on D1, building OAuth provider, multi-tenant SaaS, or troubleshooting D1 adapter errors, session caching, rate limits.
/review-skill - Skill Audit Command: Comprehensive skill documentation audit with automated checks and manual review phases.
Build rich text editors with Tiptap - headless editor framework with React and Tailwind v4. Covers SSR-safe setup, image uploads, prose styling, and collaborative editing. Use when creating blog editors, comment systems, or Notion-like apps, or troubleshooting SSR hydration errors, typography issues, or image upload problems.
Run LLMs and AI models on Cloudflare's GPU network with Workers AI. Includes Llama 4, Gemma 3, Mistral 3.1, Flux images, BGE embeddings, streaming, and AI Gateway. Handles 2025 breaking changes. Use when: implementing LLM inference, images, RAG, or troubleshooting AI_ERROR, rate limits, max_tokens, BGE pooling.
