SkillTask Two-Worker Architecture
How the SaaS Worker and runtime Worker split responsibilities after merging the old projects.
Why two Workers?
SkillTask combines two old codebases. The old SaaS sandbox project owned the product UI, auth, billing, credits, schedules, chat pages, and browser-facing API shape. The old skill-workers project owned the execution runtime: skill jobs, artifacts, chat gateway, queues, D1 runtime state, and Cloudflare Sandbox container execution.
Keeping two Workers preserves that boundary. The root TanStack Start app is the SaaS Worker. The runtime Worker under workers/skill-runtime owns isolated execution.
SaaS Worker
The SaaS Worker owns product and business concerns:
- Public pages, workspace pages, admin pages, auth, RBAC, payments, subscriptions, credits, and settings.
- Browser-facing REST routes under the app API routes.
- Signed-in AI chat and its chat/chat_message rows in the SaaS database.
- Skill schedule definitions in the business database.
- Authenticated proxy routes that call the runtime Worker through the SKILL_RUNTIME service binding or SKILL_RUNTIME_URL in local development.
It does not start Cloudflare Sandbox containers directly.
Runtime Worker
The runtime Worker owns execution concerns:
- Cloudflare Sandbox and container-backed command execution.
- Skill jobs, job events, artifacts, uploaded skills, and model presets.
- Runtime D1 state and R2 artifacts.
- Sandbox workspace files, terminal sessions, Codex history, and command logs.
- Chat provider gateway webhooks for Slack, Discord, Telegram, LINE, Teams, WeChat, Meta, and generic webhooks.
Request Boundary
Browser requests hit the SaaS Worker first. The SaaS Worker authenticates the user, strips browser credentials before proxying, and forwards only internal identity headers to the runtime Worker.
Public chat provider webhooks terminate on the runtime Worker because those platforms need a stable runtime webhook URL.
Migration Map
| Old feature | New owner | Notes |
|---|---|---|
| Sandbox workspace, exec, terminal, and files | Runtime Worker | SaaS exposes authenticated sandbox proxy APIs. |
| Codex terminal sessions and history | Runtime Worker | Execution state stays in runtime D1. |
| Skill jobs, built-in skills, uploaded skills, and artifacts | Runtime Worker | Exposed through runtime job and skill APIs. |
| Chat provider gateway and webhook events | Runtime Worker | Webhooks terminate on runtime; SaaS proxies dashboard controls. |
| Signed-in AI chat | SaaS Worker | Stores user chats in the SaaS database and talks to OpenRouter. |
| Skill schedules | SaaS Worker | Definitions live in the SaaS DB; Cron dispatches to runtime. |
| Auth, credits, payments, RBAC, and admin settings | SaaS Worker | Business concerns stay in SaaS. |
Local Development
Run the runtime Worker on port 8787, then run the SaaS app with SKILL_RUNTIME_URL pointing at that runtime. Deploy the runtime first, then deploy the SaaS Worker with the SKILL_RUNTIME service binding.