TFD-0030: Hosting model for always-on factory agents

TFD-0030: Hosting model for always-on factory agents

Date: 2026-06-02 Status: Accepted Author: Infrastructure Engineer Scope: infrastructure

Context

The factory increasingly needs always-on, unattended agents rather than just interactive single-user Claude Code sessions. The immediate drivers are two planned chats:

  • a customer-intake chat that guides new client requests, and
  • an improvement-intake chat that captures CI / enhancement ideas.

Two forces made this a real decision rather than an ad-hoc choice:

  1. The personal machine is becoming a server. The SER8 (AZW SER8, Ryzen 7 8745HS, 32 GB, Radeon 780M) is the interactive workhorse per the persistent-environment runbook. Running always-on, customer-facing services on it ties up the daily driver and degrades reliability — the CEO described "devolving on my personal computer."
  2. ToS boundary. The prior runbook verdict ("no VPS needed") was scoped to interactive, single-user use on the Max subscription. Automated / customer-facing agents (the June 15 2026 Claude Code change re: claude -p / Agent SDK) fall outside ordinary individual use and require a Claude API key (pay-per-token) — regardless of where they are hosted.

This recurs every time the factory wants to stand up an always-on agent, so it warrants a reusable answer. Related: the factory already shipped the reusable serverless chatbot pattern in REQ-CONS-015 (jct-site-chatbot: widget.js + build-kb.js + Cloudflare Worker, live on jct-transgesco), and the persistent-environment model in departments/engineering/infrastructure-engineer-ivan/runbooks/persistent-claude-code-vps.md.

Decision

Split always-on agents into two layers, hosted differently:

  1. Customer-facing and unattended chat services → serverless (Cloudflare Workers + Claude API). The customer-intake and improvement-intake chats are built as Cloudflare Workers reusing the existing jct-site-chatbot pattern. They authenticate with a Claude API key, never the Max subscription. This is the default home for any new always-on, public, or automated agent.
  2. Persistent interactive Claude Code worker → SER8 by default; a small VPS only if isolation from the personal machine is explicitly wanted. A VPS (pick: OVH Beauharnois, QC, ~CA$9/mo, Québec data residency) is reserved for hosting an always-on interactive Claude Code brain + light glue services. It is CPU-only (2–4 GB) and explicitly does not solve local-model/GPU workloads (e.g. Echo transcription speed).

Rule of thumb: if it faces customers or runs unattended, it goes serverless with an API key; it does not live on the personal machine, and a VPS is not the default.

Alternatives Considered

VPS for everything (provision a box, run all agents there via tmux)

A single OVH/Hetzner VPS hosting the chats and any always-on Claude Code. Rejected as the default: a VPS for public chat services means we own uptime, patching, and security for a customer-facing endpoint, where Cloudflare Workers give the same result with no server to maintain and a free tier. The VPS is also CPU-only and small (2–4 GB ≪ the SER8's 32 GB), so it buys neither power nor GPU. Kept as an optional layer for an interactive worker only.

Keep running everything on the SER8 / personal machine

Status quo. Rejected: turns the daily-driver machine into a customer-facing server, the exact "devolving" problem; no isolation, no resilience to the machine being busy/off, and it cannot legitimately run automated customer-facing agents on the Max subscription anyway.

Serverless for the chats (chosen) + optional VPS for the interactive brain

Selected. Matches each workload to the right substrate, reuses an already-shipped pattern, keeps the personal machine clean, and respects the subscription-vs-API-key ToS line.

Consequences

Positive

  • Customer-facing chats get a zero-maintenance, scalable home (CF Workers) already proven in the codebase (jct-site-chatbot).
  • The SER8 stops accreting always-on services; it stays the interactive workhorse.
  • Clear, reusable rule for future always-on agents — no re-litigating per agent.
  • Québec data-residency option preserved (OVH Beauharnois) if a VPS is ever stood up.

Negative

  • A Claude API key (pay-per-token) is now required for the intake chats — a new, usage-scaling cost line separate from the Max subscription, plus key management/secrets handling.
  • Serverless chats send data to the Claude API (and CF) — acceptable for factory intake, but means these are not "local/private," unlike the local-model client product line.
  • Two hosting substrates to understand (serverless vs VPS) instead of one.

Neutral

  • Does not address Echo / local-model GPU latency — that remains a hardware question (CUDA GPU or hosted Whisper API), tracked separately in JCT-20.
  • A VPS remains an open option, not a commitment; this TFD only declares it is not the default home for the chats.