The three-file structure
An IMP backend separates concerns across three source files:
The server and worker run as separate processes in production. They share the same
exulu.ts module so configuration is defined once.
src/exulu.ts
app.create() is async and returns a promise that resolves to the initialized ExuluApp. Exporting ready (the promise itself, not awaited) lets both server.ts and worker.ts import and await it independently.
src/server.ts
app.express.init() registers the GraphQL and REST routes, sets up authentication middleware, and — when EXULU_USE_LITELLM=true — starts the LiteLLM proxy supervisor. It returns the Express application, which you listen on directly.
src/worker.ts
REDIS_HOST / REDIS_PORT) and starts processing background jobs: knowledge ingestion, embedding generation, eval runs, and routines. It does not start an HTTP server.
Workers require an Enterprise Edition license (
EXULU_ENTERPRISE_LICENSE). The app.bullmq.workers.create() call throws if the license is absent or invalid.What create() does
When you callapp.create(), IMP:
- Merges built-in contexts — the platform’s internal contexts (including
transcriptions) are merged after your custom contexts, so built-ins always win on key collision. - Registers 19 default providers — Claude Sonnet 4, Claude Sonnet 4.5, Claude Opus 4, GPT-5, GPT-5 Mini, GPT-5 Pro, GPT-5 Codex, GPT-5 Nano, GPT-4.1, GPT-4.1 Mini, GPT-4o, GPT-4o Mini, Gemini 2.5 Flash, Gemini 2.5 Pro, Gemini 3 Pro, Llama Scout 4 (Vertex), GPT-OSS 120B (Cerebras), Llama 3 8B (Cerebras), and Llama 3.3 70B (Cerebras). Pass
providersto add your own alongside the defaults. - Loads built-in tools — todo, question, Perplexity, email, and (if LiteLLM and S3 are both configured) the image-generation widget.
- Validates IDs — every context, tool, and provider ID must start with a letter or underscore, use only letters, digits, and underscores, and be at most 80 characters. Treat 5 characters as the practical minimum — the runtime error message enforces intent at 5, though the current validator accepts shorter IDs; don’t rely on that.
create()throws immediately on validation violations. - Registers the
eval_runsqueue — if Redis is reachable (REDIS_HOST+REDIS_PORT), the evaluation queue is registered automatically. - Probes system binaries — checks for
pandoc,soffice, andpdftoppm. By default (requireSystemDependenciesunset ortrue),create()throws on missing system binaries; setrequireSystemDependencies: falseto downgrade to warnings instead (recommended in development).
ExuluConfig reference
workers and MCP are required top-level fields (no ?). All others are optional.
First run
Start the server in development:initdb runs automatically and prints to stdout:
Environment variables
At minimum, create a.env file with:
Next steps
- ExuluApp deep dive — Introduction, Configuration, and API reference
- Defining contexts — ExuluContext and Defining contexts tutorial
- Custom tools — ExuluTool and Custom tools tutorial
- Custom providers — ExuluProvider