# Masterplan — AI Companion Business in 1 Day

**Stack:** Venice AI (brain) · WaveSpeed Qwen Image Edit 2511 LoRA (body) · SecretVoice (voice) · x/friend (optional engine)
**Mode:** build with AI coding tools (opencode / Claude Code / Cursor), Day-1 to MVP
**Date:** Oct 2026

---

## 0. Executive summary

A Candy-AI-style companion product is built from three ingredients:

1. **An uncensored roleplay brain** → Venice `venice-uncensored-role-play` (128K ctx, vision, function-calling, no content filtering).
2. **A character-consistent body** → WaveSpeed Qwen Image Edit 2511 LoRA: edit a fixed base image per companion, keep the face/look stable, apply LoRAs for themed looks.
3. **A sultry voice** → SecretVoice: 29 premade intimate voices (13 F / 16 M), 21 languages, ElevenLabs-drop-in API, ToS-permissive for consensual adult use, **no voice-actor rights needed**. It sounds like an erotic conversation, not a robot assistant.

**x/friend** (MIT, by the SecretVoice team) already implements exactly this trio — rolling-scene memory compaction, durable facts, frustration cleanup, and `send_image` / `send_audio` tools wired to WaveSpeed + SecretVoice. **Use it.** The parts you still build yourself (multitenancy store, API, billing, frontend, deployment) are the parts that don't care which engine you use.

The one design principle that matters: **multitenancy = per-companion memory namespaces under per-account ownership**. Every account can hold many companions, and each companion's memory (`summary + facts + recent turns + media log`) lives and dies inside its own `(account, companion)` namespace. Everything else is plumbing.

---

## 1. The three pillars — service analysis

### 1.1 Venice AI — the brain

| | |
|---|---|
| Model | `venice-uncensored-role-play` (VeniceStats: released Feb 2026, tuned for immersive roleplay / character-driven writing) |
| Context | 128,000 tokens |
| Capabilities | Vision input · function calling · web search · streaming · fp8 |
| Privacy tier | "Private" (zero data retention) |
| Pricing | **$0.50 / M input tokens · $2.00 / M output tokens** |
| API | OpenAI-compatible, `https://api.venice.ai/api/v1`, one key, `venice_parameters` extras |

Why it fits:
- Venice's core design principle is unrestricted text generation — no content filtering. This is the part of the stack where the product's "uncensored roleplay" lives.
- 128K context is more than enough for persona + facts + SCENE SO FAR summary + last N turns.
- Function calling → the companion can call `send_image` / `send_audio` as tools (exactly how x/friend drives the media layer).
- Vision → the companion can *see* user-sent photos and react to them. Strong product feature, zero extra cost.
- fp8 + $0.50/$2.00 is cheap enough for real margins (see §7).

**Fallback brain:** x/friend's default `olafangensan-glm-4.7-flash-heretic` — cheaper/faster. Use it for the *auxiliary* one-shot calls (compaction summaries, fact extraction, frustration audits) and keep the RP-tuned model for the conversation itself. Two models, one budget.

### 1.2 WaveSpeed Qwen Image Edit 2511 LoRA — the body

| | |
|---|---|
| Model | `wavespeed-ai/qwen-image/edit-2511-lora` (20B MMDiT, edit variant) |
| What it does | Prompt-driven **editing** of input images, up to 3 refs; **identity/pose-consistent**, multi-person aware |
| LoRA | Custom LoRA support + multi-LoRA blending with per-LoRA weight (0–2) — including Civitai community LoRAs |
| Seed | `seed` param for deterministic-ish sampling |
| Pricing | **$0.025 per run** (~40 runs/$1) |
| API | `POST https://api.wavespeed.ai/api/v3/wavespeed-ai/qwen-image/edit-2511-lora` → poll `/predictions/{id}/result` (~2s interval) |

Why it fits — **the character-consistency trick:**
- Each companion gets a **fixed base image** (their canonical look: face, style, body). It never drifts.
- When the user asks for a picture, the model *edits* the base image against the scene prompt: *"keep the face unchanged, keep the pose, change the background to a candlelit bedroom…"*
- LoRAs give themed looks by trigger word, exposed to the LLM by name so the companion can pick its own style.
- The model is designed exactly for "identity-preserving edits" — this is the difference between a companion that looks the same every time and one that morphs.

Integration notes:
- Base image can be local (x/friend uploads it as a data URI) or a public URL.
- Async job + poll → frontend shows "she's sending you a picture…" then reveals the result. Latency is a feature here, not a bug.
- Media outputs are temp-hosted (~7 days) → download to your own storage under the per-tenant path.

### 1.3 SecretVoice — the voice (the product moat)

| | |
|---|---|
| Model | `secret-v1` (single model, tuned for closeness: breathy whispers, intimate narration) |
| Voices | **29 premade** — 13 female (Velvet, Whisper, Angel, Chloe, Candy, Honey, Crystal…) · 16 male (Steele, Phoenix, Titan, Blaze, Rico…) |
| Languages | 21 (en/es/de/fr/it/pt/ru/zh/ja/ko/th/id/vi/ms/nl/pl/et/fi/hi/ta/cs) — one voice keeps its character in every language |
| Delivery | Synchronous · HTTP streaming · **realtime WebSocket** (`stream-input`, word timings for captions) |
| Compatibility | **ElevenLabs drop-in**: same paths, `xi-api-key`, model aliases (`eleven_multilingual_v2`, …). Point any EL client at it. |
| Pricing | 1 credit = 1 character. Starter $59/600k · **Pro $99/1.2M** (~25h audio) · Scale $199/2.5M · USDC top-ups (Base) with auto-refill webhooks |
| Limits | 60 req/min/key · 5 concurrent streams · 5,000 chars/request (stitch with `previous_text`) |
| Privacy | Audio never stored; `enable_logging=false` = zero retention (transcripts too) |

Why it wins for this product:
- **Sultry/sensual by design.** The model is tuned for intimate delivery — this is the "erotic conversation, not an agent" feeling users pay for. In blind comparisons the same line spoken by SecretVoice reads as flirtatious and close; generic TTS reads as narration.
- **No voice-actor rights treadmill.** Premade voices, license baked into the API ToS, permissive with consensual adult use. You are not renting a celebrity or managing actor consent — a huge operational relief vs. cloned/celebrity voices.
- **ElevenLabs compatibility** = any existing EL SDK/infrastructure works with a base-URL swap.
- **21 languages** → ship the same companion to JP/KR/ES/etc. with one config line (`language_code`).
- **Realtime WS** → live voice replies with captions, first byte fast. This is the Candy-AI "she talks back to you" moment.

**Voice settings for the sultry feel (tune per companion):**
- `stability` 0.4–0.6 → lower = broader emotional range (more breath, more movement).
- `speed` 0.90–0.95 → slightly slower reads as intimate, deliberate.
- ⚠️ Known server quirk (verified in x/friend source): `similarity_boost` returns 500 for many values — send the `similarity` field instead; the EL-compatible key is accepted but misbehaves.
- `previous_text` / `next_text` → stitch multi-sentence messages so prosody flows across line breaks.
- `seed` accepted (best-effort deterministic) — useful for consistent delivery of repeated lines.
- `enable_logging=false` on sensitive turns → zero retention.

---

## 2. x/friend — what it actually is (verified from source)

`github.com/saudiodev/xfriend` — Python 3.11+, MIT, 4 deps (`openai`, `PyYAML`, `typer`, `requests`), v0.1.1, **written by the SecretVoice team**. A modular companion engine: swappable LLM (Venice default), image (WaveSpeed Qwen + LoRAs), voice (SecretVoice), all in one YAML config.

What it **ships and does well** (I read every file):

| Feature | Implementation | Quality |
|---|---|---|
| Rolling-scene memory | `Compactor` — background thread, trigger at `keep_messages + compact_batch`, "SCENE SO FAR" summary with carry-forward rules (names, promises, numbers, visual identity), **race-guarded** prefix check | ✅ the hard part, already solved |
| Durable facts | `extract_facts` on close/session boundary — append-only, deduped, capped (`facts_max`) | ✅ |
| Frustration cleanup | `frustration_prompt` audit → deletes turns the user pushed back on "as if never happened" | ✅ recovery valve |
| Tools | `send_image` (fixed base_image + LoRA trigger names) · `send_audio` (SecretVoice) — schema + dispatch | ✅ |
| Provider wiring | Venice/Grok/LongCat/custom presets; WaveSpeed submit+poll client; SecretVoice client **with the `similarity` alias bugfix built in** | ✅ |
| Persistence | 3-method `MemoryStore` protocol (`load/save/reset(companion_id)`) — JSON default, **DB-agnostic by design** | ✅ swap point for multitenancy |
| Session isolation | `companion_id` overrides the memory namespace — "one companion per product user" works today | ✅ |

What you **must still build** (identical whether you use x/friend or not): the multitenancy store, the API/auth layer, the frontend, billing, deployment, and guardrails. That's the whole "business" part.

**Honest caveats:** young project (1 star, 6 commits, v0.1.1). Mitigation: it's small (~1,200 LOC), the tests pass, the integration bugs I found are already fixed in-tree, and it's MIT — you own it. Treat it as a well-written reference you can fork and patch, not as a black box.

---

## 3. The multitenancy logic (the design that matters)

> Explicitly architecture-agnostic: these rules hold whether you build FastAPI+Postgres, Next.js+SQLite, a worker pool, or a serverless mesh. The logic is the contract; the stack is an implementation detail.

### 3.1 Identity model — three levels

1. **Account** — one paying human. Owns auth identity, subscription, billing, rate/spend caps. A tenant.
2. **Companion** — one character *instance*, owned by exactly one account. Carries:
   - **Static identity**: persona text, name, base image, voice id, LoRA set, language, sampling settings.
   - **Dynamic state**: its memory (below).
3. **Memory** — the companion's private state:
   `{ summary ("SCENE SO FAR"), facts[], recent turns[], media log[] }`

**The core rule:** *a companion's memory is a namespace, keyed by the pair `(account_id, companion_id)`, and it is reachable only through that pair.* In x/friend terms this is `companion_id = "{account_id}:{companion_id}"` — the framework already isolates sessions by id; the account prefix gives you multitenancy at the store layer.

### 3.2 Isolation rules (non-negotiable)

- **Store-level enforcement, not app-level hopes.** `load/save/reset` take *both* keys. The keys come from the authenticated session (JWT claim), never from user-supplied request bodies. A companion id in a request that doesn't match the session's account → rejected before it touches storage.
- **Ownership check on every companion-scoped route.** List/create/get/update/delete companions always resolve against `account_id`.
- **Per-tenant rate limits and spend caps.** Meter tokens/credits/runs per `(account, companion)` and per account; hard-stop at the cap so one runaway user can't drain the shared API budget.
- **Per-tenant privacy.** TTS sensitive turns → `enable_logging=false`; media files stored under per-tenant paths; no cross-tenant cache keys; metrics keyed by tenant.
- **Deletion cascades.** Account deletion → all companions → their memory → their media. Companion deletion wipes only its own namespace. This must be testable: delete a tenant, prove no other tenant's data changed.

### 3.3 Memory lifecycle per companion ("they remember their own memories")

- **Birth** — companion created: static persona + base image + voice + LoRAs, empty memory.
- **Growth** — every turn appends user + assistant entries. Context = byte-stable persona (prompt caching!) + facts + SCENE SO FAR + last N verbatim turns.
- **Compaction** — when history passes `keep + batch`, a background thread rolls the old turns into a new summary with carry-forward rules (names, promises, numbers, visual identity, preferences — the things that break the illusion if lost). Race-guarded so a concurrent reset can't corrupt state. Never blocks the reply.
- **Durable facts** — extracted at boundaries (session close / after X turns): the user's name, preferences, boundaries, life details. Append-only, deduped, capped. Survives compaction and restarts.
- **Frustration cleanup** — turns the user pushed back on are deleted "as if never happened". Important recovery valve for an intimate product.
- **Death** — cascading delete (§3.2).

### 3.4 Concurrency

- **Within a companion:** one writer (the turn loop) + one background compactor, lock-guarded; the store protocol must be safe from both threads (x/friend's is).
- **Across companions:** fully independent state machines — zero shared mutable state. Every companion is a shardable unit: scale out by sharding on `account_id` or `companion_id`.

### 3.5 Metering & economics per tenant

| Unit | Source | Meter |
|---|---|---|
| LLM tokens in/out | Venice | per (account, companion) + account total |
| TTS characters | SecretVoice | per companion (voice msgs) |
| Image runs | WaveSpeed | per companion |

Tiered plans map to caps — free trial (X turns), Plus (text+voice), Premium (unlimited + images + priority) — and every plan must survive a single tenant's spike.

---

## 4. The two build plans

### Path A — WITH x/friend (recommended)

**Build time: ~1 day. Your to-do list:**
1. **Multitenancy store** — implement `MemoryStore` on Postgres/SQLite with `(account, companion)` keys + companions table (identity, ownership, static config, plan, metering). *(0.5–1h)*
2. **API layer** — auth (JWT), companion CRUD, chat endpoint (stream + tool calls), voice/image request endpoints, media serving, webhooks for billing. *(2–3h)*
3. **Engine config** — swap LLM preset to `venice-uncensored-role-play`; pin one voice per companion; per-companion YAML/config via the store. *(0.5h)*
4. **Frontend** — chat UI + voice player + image viewer + companion gallery/create + onboarding + paywall. *(2–3h)*
5. **Billing & metering** — Stripe Checkout (or crypto) + per-tenant credit ledger + plan caps. *(1h)*
6. **Guardrails** — age gate, consent capture, safety filters on input+output, zero-retention TTS for sensitive turns, delete-user flow. *(1h)*
7. **Deployment** — host, HTTPS, media storage (R2/S3), secrets, one smoke test (text → voice → image → restart → still remembers). *(1h)*

**What x/friend absorbs for you:** the turn loop, tool calling, compaction, facts, frustration cleanup, WaveSpeed + SecretVoice clients, the JSON reply contract, prompt design for persona/memory. That's the hard, subtle 40–50% of the engine.

### Path B — WITHOUT x/friend

**Build time: ~2.5–3 days. You write (from scratch):**
- LLM client (OpenAI-compatible, streaming + tool calls) — *1h*
- Turn engine: chat loop, JSON reply contract (`{"say": ...}` — the companion never writes the user's side), tool rounds, history append — *2h*
- Compactor: rolling summary, background thread, race guards, carry-forward rules, token budgets — ***2.5h, highest risk*** — get this wrong and companions feel forgetful, which kills the product
- Fact extraction + merge/dedupe/cap — *1h*
- Frustration cleanup audit — *1h*
- WaveSpeed client (submit + poll, data-URI base image, LoRAs) — *1h*
- SecretVoice client (sync + stream + WS, `similarity` alias fix) — *1h*
- Tool layer (`send_image` / `send_audio` schemas + dispatch) — *1h*
- Prompt pack (persona, compaction, facts, frustration) — *1.5h* (quality lives here)
- …**then** the same multitenancy store, API, frontend, billing, guardrails, deployment as Path A — *~8h*

### Comparison

| | A: with x/friend | B: without |
|---|---|---|
| Time to MVP | **1 day** | 2.5–3 days |
| Compaction/facts quality | shipped, tested | you must nail it blind |
| Tool wiring (image/voice) | done | rebuild |
| Lines you own | API + frontend + store + billing | + entire engine |
| Risk profile | low (patch a small MIT lib) | high (subtle memory bugs) |
| Flexibility | full — it's MIT, fork anything | full |

**Verdict: Path A.** x/friend is a free head start that is *exactly* the trio you picked, written by the SecretVoice team. The business parts you build anyway are the ones that differentiate.

---

## 5. The SecretVoice "erotic conversation" design

The differentiator is that the voice mimics an intimate conversation, not an agent reading back text. Three layers make that true:

1. **The brain writes spoken lines, not narration.** The persona + reply contract force short, in-character, second-person spoken lines. No stage directions, no "she whispers seductively" narration, never the user's side of the dialogue.
2. **The TTS delivers them intimately.** Low stability (emotional range), slightly slow speed, `similarity` alias, `previous_text` stitching, pinned voice per companion. Realtime WS path for live replies; word timings feed captions.
3. **The timing is the product.** A companion who *occasionally* sends a breathy voice message (model decides via `send_audio` tool) feels alive. Frequency is a config knob, not an accident.

Voice mapping (premade, no actor rights): female companions → Whisper / Velvet / Chloe / Candy / Honey; male → Steele / Phoenix / Titan / Blaze. 21 languages with the same voice character.

---

## 6. The 1-day build timeline (Path A)

| Block | Time | Deliverable |
|---|---|---|
| Pre-flight (can be done any time) | ~1h | **Buy domain + set up email first** (SecretVoice free test tokens for validated-domain projects) → all 3 API accounts + credits + keys; 5 base images; voice picks |
| H0–1 | 1h | Repo scaffold, env/secrets, install x/friend, `xfriend doctor` green |
| H1–2 | 1h | Data model: accounts / companions / memory; multitenant `MemoryStore` + ownership checks |
| H2–4 | 2h | API: auth + companion CRUD + chat (stream + tools) + voice/image endpoints + media serving |
| H4–5 | 1h | Engine: RP model swap, per-companion config, sampling/voice tuning |
| H5–8 | 3h | Frontend: chat, voice player, image viewer, gallery, onboarding, paywall |
| H8–9 | 1h | Billing + per-tenant metering + plan caps |
| H9–10 | 1h | Guardrails: age gate, consent, safety filters, zero-retention TTS, deletion flow |
| H10–11 | 1h | Deploy: host, HTTPS, media storage, monitoring, secrets |
| H11–12 | 1h | E2E smoke: text → voice → image → restart → memory intact → **ship** |

AI coding tools (opencode / Claude Code / Cursor) compress H0–2 and H4–5 hardest; the API/frontend blocks are scaffolding-heavy and benefit from an agent doing the boilerplate while you review.

---

## 7. Unit economics & pricing

| Interaction | Cost |
|---|---|
| Text turn (≈5k in / 250 out tokens @ $0.50 / $2.00 per M) | **≈ $0.003** |
| Voice message (~300 chars @ Pro $0.083/1k) | **≈ $0.025** |
| Image run ($0.025/run) | **≈ $0.025** |
| "Rich" turn (text + voice + image) | **≈ $0.05–0.08** |

Benchmark vs. Candy-AI-style pricing:
- **Free trial** — 20 turns, no voice/image → COGS ≈ $0.06/account
- **Plus ~$9.99/mo** — 1,000 text turns + 40 voice msgs → COGS ≈ $4
- **Premium ~$29.99/mo** — unlimited text + 200 voice + 100 images → COGS ≈ $12–15 at heavy usage, far less at typical usage

Even generous plans keep 50%+ gross margin. SecretVoice credits can be auto-refilled via USDC webhooks (agent-driven), so the TTS leg never stalls.

---

## 8. Guardrails & compliance (brief, non-negotiable for launch)

- **Age gate at signup** — 18+ only, verify at onboarding.
- **Consent record** — per-account explicit agreement to adult content + data handling.
- **Safety filters** — block minors, non-consensual themes, and real-person likenesses on input *and* output; hard vetoes that can't be prompt-engineered away.
- **Zero-retention voice** — `enable_logging=false` for sensitive turns.
- **Deletion rights** — full account+companion+memory+media deletion on request.
- **Payment rails** — use an adult-tolerant processor or crypto; disclose billing descriptor.
- **Jurisdiction** — platform must comply where users are; check your target markets.

---

## 9. Risks (the ones that can actually sink the day)

1. **Venice model drift/pricing** — model IDs and prices move; pin model IDs, keep a fallback model (GLM-4.7 preset) and monitor VeniceStats.
2. **WaveSpeed image latency** — poll up to 300s; build the "she's sending you a picture…" anticipation UX and an async fallback.
3. **Payment processor policy for adult SaaS** — verify in week 1; crypto path as Plan B.
4. **Abuse / runaway cost per tenant** — the per-tenant spend caps in §3.5 are the fix; enforce them from day one.

---

## 10. Infrastructure reuse (optional, if you already have it)

If you or your team already operate production infrastructure, port the proven patterns instead of reinventing them:

- **Media storage** — any object store (S3/R2/MinIO) fits the per-tenant media path.
- **Async job pattern** — submit → poll → signed callback → cleanup is the exact shape the WaveSpeed image pipeline wants; reuse an existing queue/observability playbook if you have one.
- **Billing ledger** — reuse an existing credit/usage ledger concept for per-tenant metering.
- **WS streaming** — a proven WebSocket TTS path beats third-party rate limits; reuse it if you have one.
- **TTS cost control** — if you operate or control a TTS API, the voice leg drops from $0.083/1k chars toward marginal inference cost, and you can ship *exclusive* companion voices no competitor can license. That's the moat inside the moat.

---

## 11. Recommended day-1 order of operations

1. **Buy a domain and set up an email/mailbox first** — SecretVoice grants free test tokens for projects with a validated domain. Then sign up for all three APIs, buy credits, and verify the exact model IDs + a live voice preview + one image edit.
2. `pip install xfriend`, run `xfriend init luna`, wire keys, hear the audio samples.
3. Fork x/friend → implement the multitenant `MemoryStore` → build the API.
4. Build the thinnest frontend that shows off the three pillars (text, voice, image).
5. Bill it, gate it, deploy it, smoke-test it, ship it.