# Worker (`apps/worker`) Minimal first-party agent runtime for convoy automation. Consumes orchestrator jobs from Redis, resolves models via the workspace registry, runs a tool loop against a git worktree, and records `claim_task` / `complete_task` + `convoy_events.role_complete`. ## Run locally ```bash # Dry-run (no Redis consumer — exits after banner) WORKER_DRY_RUN=1 pnpm --filter @tasks/worker dev # Live consumer (requires REDIS_URL + DATABASE_URL) pnpm --filter @tasks/worker dev ``` Pair with the orchestrator: ```bash ORCHESTRATOR_DRY_RUN=0 REDIS_URL=... pnpm --filter @tasks/orchestrator dev WORKER_DRY_RUN=0 REDIS_URL=... pnpm --filter @tasks/worker dev ``` ## Architecture - **Queue** — `BLPOP` on `echodo:orchestrator:jobs` (same key as `apps/orchestrator`) - **Session** — `WorkerSession` interface in `@tasks/shared/worker`; v1 implementation uses Vercel AI SDK `generateText` + tools - **Tools** — `read_file`, `write_file`, `grep` (ripgrep), `run_command` (allowlist: `pnpm lint`, `pnpm type-check`, `pnpm test`, `git status`, `git diff`) - **Worktree** — one git worktree per brief job under `WORKER_WORKTREE_BASE` - **Lifecycle** — DB writes mirroring MCP `claim_task` / `complete_task`; `role_complete` convoy event on finish ## Env | Variable | Default | Purpose | |----------|---------|---------| | `DATABASE_URL` | required | Convoy, backlog, model registry | | `REDIS_URL` | optional | Job queue; missing ⇒ dry-run | | `WORKER_DRY_RUN` | `false` | Skip dequeue loop | | `WORKER_BLPOP_TIMEOUT_S` | `5` | Blocking pop timeout | | `WORKER_MAX_TOOL_STEPS` | `12` | Max tool rounds per session | | `WORKER_REPO_ROOT` | monorepo root | Repo for role prompts + worktree base | | `WORKER_WORKTREE_BASE` | `/tmp/echodo-worker-worktrees` | Worktree parent directory | Provider API keys are read from env vars named in `model_providers.api_key_env_var` (same as web settings).