Writing a Worker
Your worker’s code lives in its own git repository, provisioned when you created the worker. The build and deploy pipeline is fixed — you don’t supply a buildspec or a deploy script — so your repository only has to satisfy a short contract.
Start From the Starter Pack
Don’t scaffold by hand. On the worker’s detail page, under AI IDE Setup, download the starter for your editor:
| IDE | What the starter adds |
|---|---|
| VS Code | .vscode/mcp.json plus Copilot instruction files |
| Kiro | .kiro/ with steering, skills, and MCP config |
| Google Antigravity | .agents/skills/ with agent skills and MCP connections |
| Claude Code | CLAUDE.md, agent skills, and subagents in .claude/ |
Every variant contains the same working worker scaffold. What differs is the AI IDE configuration layered on top.
The download is generated on demand, not stored, and it comes ready to push:
.envis filled in with your project’s real RabbitMQ and DaaS values- The MCP config carries live DaaS and Buildpad credentials, so your AI assistant has project context
- A
.gitdirectory is included withoriginalready pointed at the worker’s repository
The downloaded zip contains real credentials. Treat it like a secret: don’t commit the
generated .env, and don’t share the archive.
Downloading requires the create_workers permission and a worker in the active state.
What’s Inside
- index.ts
- package.json
- tsconfig.json
- .env
- .env.example
- README.md
The scaffold is TypeScript, targets Node 20 or later, and depends on amqplib for RabbitMQ
and dotenv for local development.
First Deploy
Unzip and install
unzip <worker-id>-starter.zip -d my-worker
cd my-worker
npm installRun it locally
npm run devThe generated .env already points at your project’s broker and DaaS backend, so a local
run connects to real project infrastructure.
Push to main
git add .
git commit -m "Initial worker"
git push origin mainWatch the build
Open the worker’s Builds page. The push triggers the pipeline; when it succeeds, the deploy step restarts your process on the worker host.
The Contract
Two Required Scripts
// package.json
{
"scripts": {
"build": "tsc", // whatever produces your runnable output
"start": "node dist/index.js" // pm2 runs THIS — must be long-running
}
}Both must exist. If your worker genuinely needs no build step, make it a no-op
("build": "echo no build") rather than removing it.
Push to main
The pipeline watches the main branch of the worker’s repository. Pushes to other branches
do nothing. Work on feature branches freely; merging to main is what deploys.
Target Node 20
The runtime on the worker host is Node 20. Build against the same version to avoid build-versus-runtime drift.
Stay Running
Your process must not exit. A queue consumer, poller, or server is fine. If the process exits, pm2 restarts it, which turns a silent bug into a restart loop.
The Build Is Fixed
You do not provide a buildspec. The pipeline always runs:
install:
- npm install
build:
- npm run build
artifacts:
- '**/*'The entire workspace is the artifact, node_modules included. The runtime does not
reinstall dependencies, so whatever the build produces is exactly what runs. A dependency
that only resolves on your machine will fail in the build, not mysteriously at runtime.
The One Rule That Bites
Your process runs under pm2 with a name the platform derives from the project and worker IDs. The deploy uses this precedence:
APP_NAME="${PROJECT_ID}-${WORKER_ID}"
if [ -f ecosystem.config.js ]; then
pm2 start ecosystem.config.js --only "$APP_NAME"
else
pm2 start npm --name "$APP_NAME" -- start
fiRecommended: no ecosystem file
Ship no ecosystem.config.js. pm2 runs your npm start and names the process
correctly. Nothing to get wrong.
Name the ecosystem app anything else and --only matches nothing, so nothing starts —
silently. The build and deploy both report success, the process status reads “Not
running”, and the logs are empty. If you don’t need pm2 tuning, don’t ship the file.
Where Your Code Ends Up
| Thing | Value |
|---|---|
| Deployment path | /opt/xrad/workers/{ProjectId}-{WorkerId} |
| Environment file | /opt/xrad/workers/{ProjectId}-{WorkerId}/.env |
| pm2 process name | {ProjectId}-{WorkerId} |
| Runtime | Node 20, under pm2, on the project’s shared host |
Workers from the same project co-reside on that host. A deploy only ever touches its own deployment directory and its own pm2 process.
Checklist
-
package.jsonhas abuildscript (a no-op is fine) and astartscript -
startlaunches a process that stays running - Code is Node 20 compatible
- No secrets committed; all config read from
process.env - No
ecosystem.config.js, or one whose app name is`${process.env.PROJECT_ID}-${process.env.WORKER_ID}` - Changes are pushed to
main