Node SDK
modelreins-worker (Node) is the official JavaScript SDK and CLI for running silicon workers against ModelReins. It ships providers for Claude, Aider, Codex, Ollama, LM Studio, Nocturne, 1min.ai, and Playwright (headless-browser automation), plus a full killswitch + rate-limit classification surface.
Published on npm: npmjs.com/package/modelreins-worker
Install
Section titled “Install”# Run without installing (simplest)npx modelreins-worker
# Or install globallynpm install -g modelreins-worker
# Or as a project dep (to use the Worker class programmatically)npm install modelreins-workerRequires Node ≥ 18.
One-shot launch
Section titled “One-shot launch”# Env-basedMODELREINS_URL=https://app.modelreins.com \MODELREINS_TOKEN=<your-worker-token> \npx modelreins-worker
# Or flag-basednpx modelreins-worker \ --server https://app.modelreins.com \ --token <your-worker-token> \ --name my-worker \ --provider claudePersistent config
Section titled “Persistent config”modelreins-worker config set server https://app.modelreins.commodelreins-worker config set token <your-worker-token>modelreins-worker config set provider playwrightmodelreins-worker config list # dumps config (secrets masked)modelreins-worker config path # prints config file locationmodelreins-worker config reset # nukes configGuided setup
Section titled “Guided setup”modelreins-worker --setupWalks through server URL, token (pasted from the one-time-view URL), worker name, provider pick. Writes to the config file. Any flag on the command line overrides config.
Providers
Section titled “Providers”Pick a provider with --provider <name> or MODELREINS_WORKER_TYPE=<name>. Each provider is a thin shim that translates a ModelReins job into the provider’s execution shape.
| Provider | What it runs | Use when |
|---|---|---|
claude | claude CLI (Anthropic) | You have a Claude Code install and want the worker to dispatch jobs through it |
aider | aider CLI | Code editing + git-aware flows |
codex | OpenAI codex CLI | OpenAI-hosted coding agent |
ollama-http | Ollama HTTP API | Local GGUF inference on any machine running Ollama |
lmstudio | LM Studio’s OpenAI-compatible API | Local inference via LM Studio |
nocturne | Nocturne endpoint | Self-hosted Mediagato inference cluster |
onemin | 1min.ai API | Paid managed API |
http | Generic HTTP endpoint | Any OpenAI-compatible server |
playwright | Headless Chromium via Playwright | Browser-automation workers (scraping, form-filling, UI actions) |
spawn | Arbitrary shell command | Custom executor — see executor option |
Playwright provider
Section titled “Playwright provider”Uses playwright to spawn a headless Chromium for each job. The job prompt is delivered as JSON containing the browser instructions; the output is whatever the page produced (screenshot URL, extracted text, form submission result).
# Ensure playwright + chromium are installed on the worker machine:npm install playwrightnpx playwright install chromium
# Launch the worker with the playwright provider:modelreins-worker --provider playwright --name pw-worker-01Artifacts the worker produces (screenshots, downloaded files) can be streamed back to the fleet via the artifact tunnel; use upload_artifact() from the Python SDK from inside a custom executor, or post to /artifacts/upload directly. Node-side upload_artifact is on the roadmap.
Programmatic API
Section titled “Programmatic API”const { Worker, ERROR_TYPES, classifyError } = require('modelreins-worker');
const w = new Worker({ url: 'https://app.modelreins.com', token: process.env.MODELREINS_TOKEN, name: 'my-worker', type: 'claude', // provider model: 'opus', tags: 'code,review', networks: 'lan', pollMs: 5000, workDir: '/tmp/work', // Custom executor — bypasses provider selection entirely executor: async (job, ctx) => { await ctx.output(`starting job ${job.id}\n`); // ... do the work ... await ctx.output('done\n'); return 0; },});
w.on('ready', ({ name }) => console.log(`${name} ready`));w.on('job:start', ({ id, prompt }) => console.log(`start ${id}`));w.on('job:done', ({ id, exitCode }) => console.log(`done ${id} (${exitCode})`));w.on('job:error', ({ id, error, errorType, retryable }) => console.error(`err ${id}: ${error}`));w.on('killswitch', ({ reason }) => console.warn(`killswitch fired: ${reason}`));w.on('error', ({ type, error }) => console.error(`${type}: ${error}`));
await w.start(); // begin polling// ... later ...await w.stop(); // graceful shutdownEvents
Section titled “Events”| Event | Payload | Fires when |
|---|---|---|
starting | { name, url } | Before first heartbeat |
connected | { name } | First heartbeat acked |
ready | { name } | Provider initialized + polling |
stopped | { name } | After .stop() completes |
job:start | { id, prompt } | Job claimed |
job:done | { id, exitCode } | Handler returned (exit 0) |
job:error | { id, error, errorType, retryable } | Handler threw; errorType is one of ERROR_TYPES |
output | { jobId, content, stream } | Stdout/stderr line from the job |
killswitch | { reason } | Server-side killswitch activated (see below) |
error | { type, error } | Any non-job error (heartbeat, config, output flush) |
context | { policy, size, context } | Context loaded for a job via /context |
config:applied | { key, value } | Hot-reloaded config took effect |
Killswitch
Section titled “Killswitch”The worker polls GET /killswitch every ~60 seconds (once per 12 inbox polls). When the server returns { active: true }, the worker emits a killswitch event, stops cleanly, and exits. Use this for fleet-wide halts during incidents or budget cut-offs.
Listen for it if you want to do local cleanup before exit:
w.on('killswitch', ({ reason }) => { console.warn(`Killswitch fired: ${reason}`); // ... close local files, notify ops, etc. ...});The server endpoint is tenant-scoped, so a killswitch in tenant A doesn’t halt tenant B’s workers.
Rate-limit classification
Section titled “Rate-limit classification”Worker errors get classified by classifyError(error, exitCode, stderr) into one of:
ERROR_TYPES constant | Retryable | Triggered by |
|---|---|---|
SPAWN_FAILED | no | ENOENT, “not found”, “permission denied” |
AUTH_FAILED | no | ”not logged in”, “unauthorized”, 401, 403 |
RATE_LIMITED | yes | ”rate limit”, “429”, “too many”, “hit your limit”, “usage limit”, “limit reached”, “resets “ |
TIMEOUT | yes | ”timeout”, “etimedout” |
NETWORK | yes | ”econnrefused”, “enotfound”, “dns” |
OOM | no | exit code 137 |
EXIT_ERROR | no | any non-zero exit |
UNKNOWN | no | fallback |
The RATE_LIMITED classifier is intentionally fuzzy — the phrases were drawn from real provider responses across Claude, Codex, 1min.ai, Ollama, etc. If your provider phrases a rate-limit message differently, file an issue with the exact stderr line and it’ll get added.
Retryable errors emit job:error with retryable: true; ModelReins’ scheduler uses that to put the job back into retry status rather than failed.
const { classifyError } = require('modelreins-worker');
const cls = classifyError({ message: 'HTTP 429 Too Many Requests' });// { type: 'rate_limited', message: 'Rate limited', retryable: true }Environment variables
Section titled “Environment variables”All WorkerOptions have matching env-var defaults:
| Option | Env var |
|---|---|
url | MODELREINS_URL |
token | MODELREINS_TOKEN / MODELREINS_API_KEY |
name | MODELREINS_WORKER |
type | MODELREINS_WORKER_TYPE |
model | MODELREINS_WORKER_MODEL |
tags | MODELREINS_WORKER_TAGS |
networks | MODELREINS_WORKER_NETWORKS |
pollMs | MODELREINS_POLL_MS |
workDir | MODELREINS_WORKDIR |
command | MODELREINS_COMMAND |
promptArg | MODELREINS_PROMPT_ARG |
extraArgs | MODELREINS_EXTRA_ARGS |
outputFormat | MODELREINS_OUTPUT_FORMAT |
Precedence: constructor option → env var → config file → default.
Debug logging
Section titled “Debug logging”DEBUG=modelreins:* npx modelreins-workerSource
Section titled “Source”- Package: npmjs.com/package/modelreins-worker
- License: BSL-1.1
See also
Section titled “See also”- Python SDK — the sister SDK with
upload_artifact()+submit_review() - Providers — full provider catalog and provider-specific guides
- Jobs — job lifecycle, context policies, retry states
- What’s new — release history