Home / Ops / More in this area
Affirmology Hybrid Render Architecture (v1)
Updated Jul 04, 2026 · Affirmology_HybridRenderArchitecture_v1.md
Summary. Written 2026-07-04 for Jeff. The plan for running Affirmology cheaply and safely in super-beta by using Jeff's local Mac as the preferred render engine and the cloud as an always-on router plus fallback. No em dashes.
Affirmology Hybrid Render Architecture (v1)
Written 2026-07-04 for Jeff. The plan for running Affirmology cheaply and safely in super-beta by using Jeff's local Mac as the preferred render engine and the cloud as an always-on router plus fallback. No em dashes.
1. The problem this solves
- Every heavy generation (a Mirror reading, a Soul Song, a bulk batch) burns Anthropic API credits.
- Today the live demo and every batch share ONE Anthropic account (verified 2026-07-04: the local key and the Render key are the same, sha8 e1266416). So a batch drains the same pool the demo needs, and when it hits zero the live demo silently stops rendering new signups. This has bitten us repeatedly.
- The paid cloud instance also does all the compute, and it is a single standard box that a heavy batch can strain.
2. Credit facts (so the design is grounded)
- Anthropic bills the API PER TOKEN at the same rate no matter where the request originates. Running locally is NOT cheaper per token.
- The agents draw from prepaid API CREDITS (Anthropic Console balance), NOT from a Claude Pro/Max subscription. Subscriptions do not cover API usage.
- The two real wins from going local are: (a) compute runs on Jeff's Mac for free instead of the paid cloud box, and (b) credit ISOLATION, but ONLY if the local work uses a SEPARATE Anthropic account from the cloud. With one shared account there is no isolation.
3. The model
Cloud = the always-on storefront and router. Local Mac = the preferred render engine when it is awake, on its own credit pool.
App (Maya) / Atlas / Demo web
|
v
CLOUD Studio API (Render, always on) <-- account A credits (demo only)
| is the LOCAL node alive? (health ping over the tunnel)
|-- YES --> forward the render to the LOCAL node
| LOCAL Mac render engine <-- account B credits (batch/offload)
| renders, uploads mp3 to R2, returns the URL
|-- NO --> render on the CLOUD (fallback) <-- account A credits
|
v
Output in R2 + mirror_url/audio_url attached + email sent
The apps never change. They call the cloud as they do now. The cloud decides, invisibly, whether to offload to the Mac or render itself.
4. Components to build
- Local render node. The existing engine (affirmology-agent / affirmology-studio, already mirrored from GitHub on the Mac) run as a small local HTTP render service. It exposes:
GET /health (alive check) and POST /render (takes a person id or profile + a structure + a brief, renders locally on account B credits, uploads the mp3 to R2, returns the URL). It git pulls on start so it is always current.
- A stable tunnel so the cloud can reach the Mac over the internet. Revive the Tailscale Funnel we used before (it exposed the Mac's local server at a fixed
*.ts.net URL), or a Cloudflare Tunnel. The cloud stores that URL as LOCAL_NODE_URL.
- Cloud router logic. In the cloud Studio, before any heavy render: ping
LOCAL_NODE_URL/health with a short timeout. If healthy, POST the job to the local node and use its result. If not (timeout, Mac asleep, tunnel down), render on the cloud as today. This is transparent to the caller.
- Second Anthropic account (account B). A new Anthropic API key with its own prepaid balance, used ONLY by the local node. Set
ANTHROPIC_API_KEY=<account B> in the LOCAL .env. Keep account A on Render for the demo. Now a local batch can never touch the demo's credits.
- Local overnight runner. A script that (a)
caffeinates so the Mac does not sleep while plugged in, (b) pulls the batch worklist (held recipients excluded), (c) renders each locally on account B, (d) uploads to R2 and calls the cloud's attach + email endpoints. Runs while Jeff sleeps; he wakes to a finished batch.
5. Request flow, step by step
New signup or an app generation request:
1. Hits the cloud Studio API (unchanged entry point).
2. Cloud pings the local node health.
3. If alive: cloud forwards {profile, structure, brief} to the local node. The Mac renders on account B, uploads the mp3 to R2, returns the URL. Cloud attaches it and delivers.
4. If not alive: cloud renders on account A (the current path). Nothing breaks; it just costs cloud credits.
Overnight batch (Mirror readings, once the structure is validated):
1. Jeff leaves the Mac plugged in and connected.
2. The local overnight runner wakes, git pulls, reads the worklist minus .mirror_hold.
3. Renders each reading locally on account B, uploads to R2, attaches mirror_url, sends the customer email (BCC jeff@affirmology.ai).
4. Idempotent: it skips anyone already delivered, so an interrupted run resumes cleanly.
6. Why this is the right shape for beta
- The demo is always reachable and never starves, because its credits (account A) are firewalled from batch work (account B).
- Heavy compute and heavy spend move to the Mac, which is free compute and a separate wallet.
- It degrades gracefully. Mac asleep or tunnel down means the cloud quietly handles it. No customer ever sees a difference.
- It is incremental. We already render locally; this formalizes it into health-checked routing.
7. What Jeff needs to do (setup)
- Open a SECOND Anthropic account and generate an API key (account B). Fund it. This is the batch/local pool.
- Keep the Mac plugged in and connected overnight during the trip (already planned).
- Approve reviving a tunnel (Tailscale Funnel is fastest; it worked before).
Everything else is code I build.
8. Guardrails that still apply
- Spend cap and stop-on-credit-error on the batch (from the reading-craft build list), so even account B cannot overspend a run.
.mirror_hold is always honored; nothing sends to held recipients.
- Auto-reload on BOTH accounts in the Anthropic Console so neither ever hits zero.
9. Build phases
- Phase 1: second Anthropic account (Jeff) + point the local node at it.
- Phase 2: local render node service (
/health, /render) + revive the tunnel.
- Phase 3: cloud router (health-check then offload-or-fallback).
- Phase 4: local overnight runner with caffeinate + idempotent worklist.
- Phase 5: extend the same routing to the app generation paths (Maya/Atlas), so app requests also prefer local.
Status 2026-07-04: DESIGN. No code built yet. Nothing runs (all Mirror sends held). Build starts on Jeff's go, after the Mirror structure rebuild is validated.