Viberator Worker
The Viberator Worker runs the AI agents that carry out work on tickets and related tasks.
What it does
When work is started, the worker:
- receives the task details
- opens the repository
- runs the chosen agent
- reports progress
- saves the result
- creates a pull request when needed
Supported agents
The worker can use several different agents, including:
- Claude Code
- Qwen CLI
- Gemini CLI
- OpenAI Codex
- OpenCode
- Mistral Vibe
- Kimi Code
How it runs
The same worker can run in different ways depending on the setup:
- locally for development
- in the cloud for regular jobs
- in a serverless environment for shorter jobs
Worker lifecycle
- A job is created.
- The worker receives the job details.
- The worker gets the information it needs.
- The agent runs the task.
- Progress is reported back.
- The work is finished and recorded.
Container images
Different worker images are used depending on how the worker is deployed.
Phase prompts
The worker follows instructions prepared by the platform for each type of task.
Workspaces and isolation
Each job runs in its own clean workspace so work stays separate and does not affect other jobs.
Failure modes
Sometimes a worker can fail because:
- a required secret is missing
- the repository cannot be opened
- the job takes too long
- the pull request cannot be created
When that happens, the job is marked as failed and can usually be retried.
- Node.js 20+, TypeScript 5.0, built with
tsup. @anthropic-ai/claude-code2.x for the Claude Code agent harness.- All other agents (Qwen CLI, Gemini CLI, OpenAI Codex, OpenCode, Mistral Vibe, Kimi Code) are installed as global CLIs inside the Docker images and shelled out to from the worker.
simple-git3.x for clone, commit, and push.- AWS SDK clients for S3 (asset upload, bootstrap payload retrieval) and SSM (credential resolution).
- Winston for structured logs.
Entry points
A single TypeScript codebase, three entry points:
- CLI — used in local Docker runs and in the multi-agent self-hosted image. Reads the bootstrap payload from a local file or S3 URI and exits when the run finishes.
- Lambda handler — used by clankers with
deployment_strategy = aws_lambda_container. Receives the payload as the Lambda event. - ECS entrypoint — used by clankers with
deployment_strategy = aws_ecs. Reads payload metadata from environment variables wired byecs.runTaskand pulls the full payload from S3 if needed.
All three eventually call into the same ViberatorWorker core class.
Worker lifecycle
- Receive payload. The bootstrap payload contains the project, ticket (or claw), source repo URL, branch, agent type, prompt template, and the list of secret references.
- Resolve clanker config. Either the payload contains the clanker definition inline, or the worker fetches it from the platform backend using the callback token.
- Fetch credentials. For each referenced secret, look it up in env vars (local), the platform database (encrypted), or SSM Parameter Store (production). Materialise the values into the agent's environment.
- Initialise the agent harness. Pick the right CLI (
claude,codex,qwen,gemini,opencode,mistral,kimi), set its env, and apply anyAGENTS.mdandskills/files attached to the clanker. - Clone the repo. Use
simple-gitto clone into/tmp/viberator-work/<job-id>. The branch is the project's base branch. - Run the agent. Pipe the rendered prompt into the agent CLI and stream output back through the platform callback.
- Commit and push. The agent's working tree changes are committed with a structured commit message and pushed to the repository.
- Open a PR. For Execution-phase jobs the worker calls the SCM API (GitHub for now) to open a pull request against the configured PR base branch. The branch name is rendered from the project's
branchNameTemplatewith{{ ticket }},{{ original_ticket }}, and{{ clanker }}placeholders. - Report result. The worker POSTs the final job status (and the PR URL, when applicable) back to the platform.
Supported agents
| Agent slug | Description | Distribution |
|---|---|---|
claude-code | Anthropic Claude Code, the default general-purpose coding agent. | npm package @anthropic-ai/claude-code |
qwen-cli | Alibaba Qwen CLI; flexible endpoints for Qwen-compatible APIs. | global CLI in image |
codex | OpenAI Codex; reasoning-focused coding agent. | global CLI in image |
opencode | OpenAI-compatible orchestration with customisable base URL and model. | global CLI in image |
kimi-code | Moonshot/Kimi K2.5 coding agent tuned for high-context completion. | shell-installed in image |
gemini-cli | Google Gemini CLI with selectable model profile. | global CLI in image |
mistral-vibe | Mistral-native coding option, installed via uv. | uv-installed in image |
The agent type is set on the clanker. Switching agents is purely a matter of changing the clanker definition (and ensuring the relevant API key secret is attached).
Container images
Worker images live under infra/workers/docker/:
viberator-docker-worker.Dockerfile— Claude Code only, intended for local Docker.viberator-ecs-worker.Dockerfile— Claude Code only, ECS Fargate.viberator-lambda.Dockerfile— All agents, Lambda compatible.viberator-worker-multi-agent.Dockerfile— All agents pre-installed, ECS or Docker.agents/viberator-worker-<agent>.Dockerfile— Single-agent specialised images for ECS.
The base image is node:24-slim with git, curl, and python3 installed and a non-root viberator user. Global npm installs add Claude Code, Qwen, Gemini, Codex, OpenCode, plus TypeScript and Jest. Mistral Vibe is installed through uv; Kimi Code through a shell installer.
For the build/push process and image selection logic, see Clanker Images.
Phase prompts
The worker doesn't hard-code the prompt for each phase. Instead, the platform passes a rendered prompt template along with the bootstrap payload. Templates are stored in the prompt_templates table; the resolver picks the project-specific override if one exists, otherwise falls back to the system default.
The seven templates the worker can be invoked with:
ticket_researchticket_research_revision_taskticket_planning_with_researchticket_planning_without_researchticket_planning_revision_taskticket_developing(Execution phase)claw_scheduled_task
Templates can reference variables that the platform fills in: ticket title, ticket description, severity, repo URL, branch, prior phase document (for revisions), and so on.
Workspaces and isolation
Each worker invocation gets its own working directory under /tmp/viberator-work/. The directory is recreated on every run, so there is no cross-job state. For Lambda this is the /tmp writable scratch space; for ECS it's the container's ephemeral storage.
The worker runs as a non-root user inside the container and can only see its own scratch directory plus whatever environment variables the bootstrap injected. Secrets are passed in as env vars and are never written to disk.
Failure modes
The most common ways a worker fails:
- Missing secret. The agent boots but cannot authenticate against its API. The worker reports
failedwith a clear message indicating which secret was missing. - Repository clone failure. Usually a missing or expired
GITHUB_TOKENintegration credential. Check the project's SCM Execution settings. - Agent timeout. Lambda has a 15-minute hard limit; ECS workers can run longer (the timeout is the project's
workerSettings.maxExecutionTime). - PR creation failure. Push succeeds but the SCM API rejects the PR. Inspect the worker log for the SCM error.
The platform records the failure on the job row and (for ticket-driven jobs) leaves the phase document in the previous state so a retry can pick up where the run failed.