Experts.js
Build OpenAI Assistant workflows where specialized assistants operate as callable tools.
What does this agent do, and when should you use it?
Experts.js is a JavaScript library that wraps the OpenAI Assistants API around three primary objects: Assistant, Tool, and Thread. An application creates a Thread and an Assistant, then uses ask() to send a message and receive output while the library manages Runs and Run Steps. Tool extends Assistant, allowing a parent Assistant or another Tool to invoke a specialized assistant through function-tool definitions. Tools may be LLM-backed or implement their own ask() behavior with llm set to false. Streaming lifecycle events expose text, image-file, tool-call, and run-step activity. For production, an Assistant or Tool can be initialized with an existing asst_ id so the same remote assistant is reused and local configuration can update it.
The application imports Assistant, Tool, and Thread from experts, creates a context with Thread.create(), creates an assistant with Assistant.create(), and calls assistant.ask(message, threadID). ask() accepts either a string or a native OpenAI message object and handles the Run lifecycle. Event handlers such as on("textDelta") receive streaming text, while other documented events surface tool calls, image files, and completed run steps. A parent adds an assistant-backed tool through addAssistantTool; the child Tool's response is submitted as the parent tool output. For nested LLM-backed tools, the library finds or creates separate child threads and stores the parent-to-child relationship in OpenAI thread metadata.
- A Node.js team building an internal assistant that wants a concise `ask()` interface instead of directly managing OpenAI Run objects.
- An application developer splitting catalog lookup and OpenSearch query generation into specialized Tools called by a company assistant.
- An Express backend that streams assistant response chunks to a client using the `textDelta` event.
- A knowledge-search application configuring `file_search` with `vector_store_ids` for an OpenAI Vector Store.
- A multi-assistant workflow that needs separate context threads for child tools to avoid documented thread-locking issues.
What are this agent's strengths and limitations?
- Provides a small object model—Assistant, Tool, and Thread—while hiding Run and Run Step management behind `ask()`.
- Lets assistants serve as reusable function tools, including multi-tier parent and child orchestration.
- Exposes both standard streaming events and post-run async variants for response streaming, tool handling, and usage reporting.
- Supports documented OpenAI tool configuration including function calling, `file_search`, `code_interpreter`, and Vector Store resources.
- Its documented execution model is tied to the OpenAI Assistants API, with no documented alternative-provider adapter.
- Every question requires a thread ID, so a chat application still needs to persist that identifier.
- Function names for Tools must be unique across a parent's complete tool set, creating a naming constraint in larger systems.
- OpenAI server-sent events are documented as not async/await friendly; asynchronous listeners need the library's Async event extensions.
How do you install or deploy this agent?
Install with npm install experts, then import Assistant, Tool, and Thread from experts. The documented development setup creates .env.development.local with OPENAI_API_KEY=sk-... and POST_IMAGES_API_KEY=..., followed by ./bin/setup and ./bin/test. A minimal invocation is: const thread = await Thread.create(); const assistant = await Assistant.create(); const output = await assistant.ask("Say hello.", thread.id);.
How do you use this agent?
Pass options such as name, instructions, model, tools, and tool_resources to an Assistant subclass through super(); the documented default model is gpt-4o-mini. Add a specialized tool after super() with this.addAssistantTool(EchoTool). For streaming output, register assistant.on("textDelta", (delta) => process.stdout.write(delta.value)) before calling ask(). In production, supply an existing asst_... id in constructor options; set skipUpdate: true when the remote assistant should not be updated from local configuration.
How does this agent compare with similar options?
Compared with direct use of the OpenAI Chat Completions API, Experts.js is organized around Assistants, Threads, Runs, and assistant-backed tools. Unlike Custom GPTs, its documented interface is application code using the OpenAI Assistants API.