Kaizen AI Lab · Operations

Client Automation Workflow

Operational workflow for onboarding Kaizen clients. Internal stack: Basecamp (canonical) + Mission Control (UI layer) + Campfire (chat). Client delivery: per-client Campfire + Kai corporate brain.

v1.1 Date 2026-06-07 Author Sebastian, for Don Ho Status Draft for review Supersedes v1.0

What changed from v1.0 → v1.1

  1. Canonical source of truth: Fizzy → Basecamp. Mission Control becomes a bi-directional sync UI layer.
  2. Internal chat: Slack → Campfire (self-hosted, one-time license). 10+ Hermes agents confirmed feasible.
  3. Kanban: Fizzy → Basecamp Card Tables. Migration plan in §9.
  4. Adjacent Media: Removed all partner/co-delivery language. Acquired by Kaizen 2026-05. Internal team, external brand preserved.
  5. Bot brand: "Kai" is the corporate brain default. "Sebastian" is never client-facing. Top-tier clients can white-label.
  6. Sequence fix: MSA + SOW + intake link sent together immediately after the discovery call.
  7. Status page: Use Basecamp's native public-link toggle, not a custom subdomain.
  8. First-value rule: 7 days → 3 business days.
  9. Client portal: Each client gets an isolated Campfire instance with Kai installed. Carson is building this.
  10. Staging URLs: Now use native {slug}.pages.dev.
  11. Products (intake): Multi-select — Website / SEO-GEO / Kai / Other.
  12. Agents: Killed Cosmo/Juno/Bonnie (v1.0 fabrication). Only Percy is named in Hermes so far.
  13. Open decisions: Most resolved per your direction.

Contents

  1. TL;DR
  2. Principles
  3. Generic onboarding workflow
  4. Applied per product (Website · Kai)
  5. Automation spec
  6. Build sequence
  7. Open decisions for Don
  8. intake.kaizenailab.com build spec
  9. Campfire feasibility for Hermes agents
  10. Fizzy → Basecamp migration
  11. Appendix (frameworks, glossary, deployment math)

TL;DR

Kaizen needs one repeatable, low-friction onboarding pipeline that takes a signed deal from "yes" to "first update shipped" without manual ops drudgery.

Build target: Day-1-to-kickoff in under 24 hours. One Don decision point (sign the contract). First visible client update within 3 business days.

Stack pivot in this rev: Off Linear, off Slack, off Fizzy. Onto Basecamp + Mission Control + Campfire — all 37signals tooling for internal ops, all open or one-time license. Per-client Campfire instances become the client portal. Kai is the corporate brain.

1. Principles

1.1 The onboarding IS the product

Patterns: Stripe Atlas, Linear, Mercury, Ramp.

The first days set client expectations. Every status change (intake submitted → contract sent → workspace provisioned → kickoff scheduled) is system-triggered, not human-triggered. They watch their workspace get built.

1.2 One source of truth per concern

Patterns: Basecamp / Shape Up; Linear's single inbox.

ConcernSource of Truth
Tasks, deadlines, project structureBasecamp
Smart task surfacing (queue, energy, urgency)Mission Control (bi-directional sync)
Synchronous internal chatCampfire (self-hosted, single instance)
Synchronous client chatPer-client Campfire instance
Contracts & SOWsPandaDoc → PDFs in Basecamp project
Client metadataSupabase clients
Files & deliverablesBasecamp Docs & Files
Long-form SOPs (Kai)Obsidian vault

If two systems claim the same fact, the system NOT in this table is wrong by definition.

1.3 Provisioning is idempotent and reversible

Patterns: Pulumi, Terraform.

Declarative state: "this client should have a Basecamp project, a Card Table, a Campfire instance at {slug}.kaizenportal.com, a Supabase row, a Kai instance (if applicable)." The provisioner checks each, creates what's missing, reports diffs.

1.4 Defer the contract until intent is qualified

Patterns: Apollo / Outreach playbooks; Basecamp's "the work is the proposal."

Revised sequence: Discovery call → client says "yes, go" → MSA + SOW (one PandaDoc envelope) AND intake form link (separate email) sent in parallel within 1 hour. Provisioning fires on signed contract regardless of intake state. Intake fields enrich the workspace as they arrive.

1.5 Bot does boring; human does trust

Patterns: Mercury, First Round Review.

Automate project creation, card tables, file folders, agent provisioning, calendar invites, welcome emails, kickoff agendas. Leave for Don: discovery, kickoff, first Loom, strategic calls.

Litmus: if Don has to manually do something an intern could do, the workflow is wrong.

1.6 Status transparency > status updates

Patterns: Stripe status pages, Basecamp's native public link.

Don't email status — show it. Percy toggles on Basecamp's native public-link feature for the relevant card tables / lists per the client SOW. No custom subdomain build required.

1.7 The 3-business-day first-update rule

Revised down from v1.0's 7 days.

Something built, shipped, or measurably progressed within 3 business days. Websites: staging URL with brand applied. Kai: live in client's Campfire, answering one real question. Day 4 with nothing shipped = off-tempo.

1.8 One client portal per client = one isolated Campfire

Each client gets a dedicated Campfire instance at {slug}.kaizenportal.com. Their Kai bot lives inside it. Carson is building this layer.

Why per-client Campfire: it's single-tenant by design — "to support entirely distinct groups of customers, deploy multiple instances." That's a feature. Hard architectural isolation = HIPAA/SOC2/GDPR-friendly by default.

Clients use the portal to ask Kai questions, request website changes (Kai files them as Basecamp cards), see status, and chat with the Kaizen team.

2. Generic onboarding workflow

0~24h, manual

Inbound qualification

Owner: Don (with Brandwyn on marketing deals) · Tools: Cal.com

  • 30-min discovery call
  • Exit: client agrees → contract + intake fire automatically
1<1h, automated

Contract + intake sent together

Owner: Percy + Don approval · Tools: PandaDoc + intake.kaizenailab.com

  • Don clicks "go" (or replies to MC prompt)
  • Percy creates Supabase row (qualified), drafts SOW
  • Don reviews SOW in Campfire (~1 min)
  • Percy fires PandaDoc envelope (MSA + SOW together)
  • Percy sends separate intake email (not gated by signature)
  • Status → contract_sent + intake_sent
2async, parallel

Signatures and intake

Owner: Client + Percy (watcher)

  • PandaDoc webhookPOST /api/onboarding/contract-signed → status = signed
  • Intake webhookPOST /api/onboarding/intake → status += intake_complete
  • Provisioning starts on signed. Personalization continues as intake arrives.
3<5 min, automated

Provisioning

Owner: Percy · Trigger: contract-signed

  • Basecamp project Kaizen × {Client Name}
  • Card Table + default columns (Triage / Discovery / In Progress / In Review / Done)
  • To-do lists for Onboarding / Engagement / Off-boarding
  • Mission Control registration + bi-directional sync on
  • Team invites (Don, Brandwyn, Carson)
  • Client primary contact invited as Basecamp client-tier user
  • Per-client Campfire deployed at {slug}.kaizenportal.com (Docker, one VM)
  • Kai bot installed in client Campfire (Kai clients)
  • Basecamp public link generated for client status page
  • Welcome email via Resend
  • Kickoff call auto-booked within 3 business days
  • Status email to client: "Your workspace is ready"

Logged to Supabase provisioning_runs. Failures → Campfire #ops-alerts + retry (max 3, exponential backoff).

460 min, manual

Kickoff

Owner: Don (+ Brandwyn for marketing-heavy clients) · Tools: Zoom/Meet, Granola

  • Agenda pre-populated as Basecamp Message
  • Scope confirmation, success metrics, comms norms, day-3 deliverable commitment
  • Granola transcript → MC → Basecamp cards via Vision pipeline
  • Client introduced to Kai in their Campfire portal (Kai clients)
5<3 business days

First update

Owner: Engagement-specific (Carson for websites/Kai builds)

  • Day-3 deliverable tracked as red-priority Basecamp card
  • MC pings on day 2 if not on track
  • Status auto-published to Basecamp public link
6ongoing

Steady-state ops

  • Weekly Basecamp digest → client Campfire portal (Monday 9am client-local)
  • Monthly recap email to primary contact
  • Quarterly business review pre-booked at engagement start (Cal.com recurring)
7end of engagement

Off-boarding

  • Basecamp project archived (searchable forever)
  • Client Campfire: maintenance tier OR exported + spun down per SOW
  • Kai instance: per §3.2 off-boarding
  • 30-day post-engagement check-in auto-scheduled

3. Applied per product

3.1 Website client

~$15k–$50k SOW · 4–8 week engagement · Astro/Next.js → Cloudflare Pages

Intake additions

  • Current domain + hosting situation
  • Brand assets (logo, fonts, colors)
  • 3 competitor sites + 3 inspirations
  • Analytics access (GA4, Search Console)
  • DNS access situation
  • Content readiness

Provisioning additions

  • GitHub repo client-{slug}-site from kaizen-website-template
  • Cloudflare Pages project with preview branch deploys
  • Figma file from Kaizen template
  • Weekly check-in Calendly embedded in Basecamp

Removed in v1.1: "Adjacent Media Slack Connect" handoff. AM is internal Kaizen now.

Day-3 deliverable

Live staging URL at {slug}.pages.dev with brand applied (logo + colors + typography), nav structure, hero section.

Steady-state cadence

  • Weekly 30-min check-in (auto-booked)
  • Daily Cloudflare Pages deploy log → client's Basecamp Message Board
  • Basecamp Card Table surfaces design/dev/content lanes in parallel

Off-boarding

  • Domain handoff via documented DNS migration template
  • Source repo: client gets read access, Kaizen retains 90 days then archives
  • SEO/content (if scoped): handed off as documentation + access transfer

3.2 Kai / Corporate Brain

~$5k–$15k setup + $2k–$10k/mo retainer (TBC) · Hermes runtime · Per-client isolation · Default name "Kai" (white-label at top tier)

Hard rule: per-client isolation by architecture, never multi-tenant. Each client gets own Supabase, own repo, own vault, own Hermes workspace, own Campfire instance, own Kai bot.

Bot name policy

  • Default: Kai
  • Top-tier (white-label): client picks the name
  • "Sebastian" is never used for the corporate brain. Sebastian is Don's internal COS only.

Intake additions

  • Company size + headcount in scope
  • Existing tools the bot reads from (Gmail, Slack/Teams, Notion, Drive)
  • Compliance posture (HIPAA / SOC2 / GDPR / none)
  • EU residency required? (→ Frankfurt-region deployment)
  • Day-3 question — one thing they want Kai to answer in week 1
  • Primary internal champion
  • Sensitive data exclusions
  • Tier (standard "Kai" vs white-label)

Provisioning additions

  • Supabase project via Management API → migrated from kaizen-client-template
  • GitHub repo kaizen-{slug}-colony
  • Obsidian vault kaizen-{slug}-vault
  • Hermes workspace with client config
  • Per-client Campfire at {slug}.kaizenportal.com (Docker, single VM)
  • Kai bot registered, webhook → Hermes workspace, display name Kai or white-label override
  • Integration connectors wired (OAuth queued for client to authorize)
  • Vector store seeded with intake seed docs
  • Secrets vault per-client .secrets/ (chmod 600)

Day-3 deliverable

Kai is live in client's Campfire portal, has ingested seed docs, correctly answers the "day-3 question" from intake. One question, real data, working bot — within 3 business days.

Steady-state cadence

  • Weekly 30-min "what's the bot learning" call
  • Daily MC digest → client Campfire portal
  • Monthly bot-tuning session
  • Quarterly SOC2-style usage report from Supabase logs

Off-boarding

  • Client owns Supabase project — transferable to their account
  • Client owns data (Basecamp export, vault repo handoff, Campfire export)
  • Per-client Hermes workspace: deprovisioned 30 days post-engagement OR maintenance tier
  • Per-client Campfire: snapshot + decommission OR transfer to client's infra
  • Kai instance: archived read-only for 90 days, then permanently spun down

4. Automation spec

4.1 Intake schema (multi-product, v1.1)

client_name: string (required)
primary_contact_name: string (required)
primary_contact_email: email (required)
primary_contact_phone: string (optional)
billing_email: email (required)
company_size: enum [1-10, 11-50, 51-200, 201-1000, 1000+]
products_interested: MULTI-SELECT [website, seo_geo, kai_corporate_brain, other]
budget_range: enum [<10k, 10-25k, 25-50k, 50-100k, 100k+]
timeline_urgency: enum [yesterday, this_month, this_quarter, exploratory]
how_did_you_find_us: string
decision_makers: string
success_criteria_3mo: textarea

Conditional fields load per selected product (see §3). SEO/GEO additions: target keywords, geographic markets, existing rankings, current tooling, content production capacity.

4.2 Webhook contracts

Intake submission → Mission Control

POST https://mission-control.kaizenailab.com/api/onboarding/intake
Headers: X-Intake-Signature: <hmac>
Body: { submission_id, fields: { ...schema... } }
Response: 200 { client_id, supabase_row_id, ops_message_ts }

PandaDoc contract-signed → Mission Control

POST https://mission-control.kaizenailab.com/api/onboarding/contract-signed
Headers: X-PandaDoc-Signature: <hmac>
Body: { document_id, client_id, signed_at, pdf_url }
Response: 200 { provisioning_run_id }

Basecamp webhook (bi-directional sync) → Mission Control

POST https://mission-control.kaizenailab.com/api/sync/basecamp
Headers: X-Basecamp-Webhook-Token: <signing_secret>
Body: { kind: 'todo_created' | 'card_moved' | ..., recording: {...} }
Response: 200

4.3 Provisioning state machine

qualified
    ↓ (Don approves contract send)
contract_sent + intake_sent
    ↓ (PandaDoc webhook)
signed
    ↓ (provisioner picks up — does NOT wait for intake)
provisioning
    ↓ (all steps succeed)
provisioned
    ↓ (kickoff held)
active
    ↓ (engagement ends)
offboarding
    ↓ (90-day archive complete)
archived

Intake fields land async and trigger personalization passes. Failure states: provisioning_failed → Campfire #ops-alerts; contract_expired → re-send.

4.4 Key API calls

Basecamp — create per-client project

curl -X POST https://3.basecampapi.com/${ACCOUNT_ID}/projects.json \
  -H "Authorization: Bearer ${BASECAMP_TOKEN}" \
  -H "Content-Type: application/json" \
  -H "User-Agent: Kaizen Provisioner (don@kaizenailab.com)" \
  -d '{"name":"Kaizen × {Client Name}","description":"{summary}"}'

Basecamp — invite client as client-tier user

curl -X PUT https://3.basecampapi.com/${ACCOUNT_ID}/projects/${PROJECT_ID}/people/users.json \
  -H "Authorization: Bearer ${BASECAMP_TOKEN}" \
  -d '{"grant":[{"email_address":"{client_email}",
                 "name":"{client_name}",
                 "title":"Client",
                 "company_name":"{client_company}"}]}'

Campfire — install Kai into per-client instance

# Currently manual via Campfire admin UI (~30 sec):
# 1. Log in to {slug}.kaizenportal.com as admin
# 2. Bot section → Add bot → Name: "Kai",
#    Webhook URL: https://kai-{slug}.kaizenailab.com/webhook
# 3. Campfire generates per-room URLs for Kai to post unprompted
# 4. Save URLs into Supabase clients.kai_room_urls (JSON map)

Campfire — Kai posts to a room

curl -X POST "https://{slug}.kaizenportal.com/rooms/{room_id}/bot/{bot_token}/messages" \
  -H "Content-Type: text/plain" \
  --data "Hello — Kai here. What can I help with?"

Cloudflare Pages (website clients)

curl -X POST "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/pages/projects" \
  -H "Authorization: Bearer ${CF_TOKEN}" \
  -d '{"name":"{slug}-site","production_branch":"main"}'
# Staging at {slug}.pages.dev (native CF subdomain — no custom DNS)

Supabase Management (Kai)

curl -X POST https://api.supabase.com/v1/projects \
  -H "Authorization: Bearer ${SUPABASE_MGMT_KEY}" \
  -d '{"name":"kaizen-{slug}","region":"us-west-1","plan":"pro"}'

4.5 Agent ownership (Hermes runtime)

v1.1 correction: v1.0 named agents Cosmo, Juno, and Bonnie. Those were my fabrication. Only Percy is named in the actual Hermes architecture so far. Remaining lines use Percy + [agent TBD] until you name additional agents.
StepOwning agentAction
Intake parse + SOW draftPercyReads intake, drafts SOW
Contract sendPercyCalls PandaDoc on Don's approval
Provisioning orchestrationPercyFans out steps
Basecamp provisioningPercy + [TBD]Project, Card Table, invites
Campfire instance provisioningPercy + [TBD]Docker deploy + admin setup
GitHub / Cloudflare (website)Percy + [TBD]Repo + Pages provisioning
Supabase / Hermes (Kai)Percy + [TBD]Per-client infra spin-up
Welcome packetPercy + [TBD]Brand-aligned comms
Kickoff agendaPercyPulls intake data, generates agenda
Status digestPercyWeekly Basecamp → client Campfire digest
Client-facing chat in portalKai (per-client)Answers questions, files Basecamp cards

5. Build sequence

  1. Week 1 — Basecamp adoption. Migrate Kaizen ops Linear → Basecamp. Connect MC as bi-directional sync. Dogfood the canonical store.
  2. Week 2 — Custom intake form. intake.kaizenailab.com + Supabase clients + ops notifications.
  3. Week 3 — Contract automation. SOW auto-draft + PandaDoc + parallel contract/intake fire pattern.
  4. Week 4 — Provisioning state machine. Basecamp project + Cloudflare + welcome email.
  5. Week 5 — Internal Campfire migration. Stand up Kaizen Campfire, migrate Hermes agents, retire Slack.
  6. Week 6 — Per-client Campfire portal. Automate Docker deploy for {slug}.kaizenportal.com. Carson's build slots in here.
  7. Week 7 — Kai-specific provisioning. Per-client Hermes + Supabase + Kai bot install.
  8. Week 8 — Off-boarding automation.

6. Open decisions for Don (v1.1)

Resolved (no longer open)

Still open

  1. Top-tier white-label price point. What revenue tier unlocks Kai rename rights?
  2. Per-client Campfire hosting model. One VM per client (cleanest, ~$5-10/mo) vs container density on shared VM (cheaper, more ops). Recommend per-client VM.
  3. Internal Campfire migration timing. Day-1 cutover or 1-week parallel run? Recommend parallel.
  4. Basecamp account structure. Single Kaizen account with all clients as projects (recommended), or per-client accounts (overkill)?
  5. intake.kaizenailab.com build scope. Separate engagement, ~1 week. Confirm you want a standalone spec.

7. intake.kaizenailab.com build spec

Custom Tally/Typeform-style page, fully owned.

Tech stack

Pages

Key UX

Branding

Build estimate: 5-7 working days. Recommendation: Scope as separate deliverable. Launch the workflow on Tally first if needed, swap to custom in week 2.

8. Campfire feasibility for Hermes agents

Headline: Campfire supports 10+ Hermes agents. Deal-breaker check ✅ passed.

How Campfire bots work

No documented limit on bot count. 10+ agents = 10+ bot entries. Each agent runs as its own webhook endpoint inside the Hermes runtime.

Pros vs Slack

DimensionCampfireSlack
CostOne-time ~$300, self-hosted$X/user/month forever
Multi-botUnlimited, simple webhooksBot apps, more friction
Per-client isolationNative (single-tenant by design)Multi-tenant; Connect/guest
Data ownershipFully owned (your Docker, your DB)Salesforce cloud
Compliance postureHIPAA/SOC2/GDPR by box controlVendor certifications
ThreadingLight (rooms + messages)Heavy threads
SearchBuilt-in, basicStrong but rate-limited on lower tiers
Integrations marketplaceNone — custom webhooksMassive
Mobile appsPWA onlyFirst-class native
Voice/videoNoneHuddles, Clips

Cons

Recommendation: Yes, migrate. Slack subscription savings + per-client isolation outweigh polish gap. Plan a 1-week parallel run. PWA install as default mobile path.

9. Fizzy → Basecamp kanban migration

Why the swap is clean: 37signals owns both. Basecamp's Card Table primitive is the same metaphor as Fizzy's boards. Migration = data shape, not concept shift.

Mapping

Fizzy conceptBasecamp concept
AccountBasecamp account
BoardProject's Card Table (one per project)
ColumnCard Table column
CardCard (Basecamp primitive)
Tag priority:redBasecamp tag OR title prefix [🔴]
Tag size:*Basecamp tag OR title prefix
Tag context:*Project assignment (each context = own project)
Tag energy:*MC-side only (energy is an MC concept)
CommentsCard comments (native)
Card detail bodyCard content (markdown)

Steps

  1. Export every Fizzy card with tags
  2. Rewrite Mission Control's fizzy-data.tsbasecamp-data.ts using @37signals/basecamp SDK
  3. Use Basecamp tags for priority/size/context; fall back to title prefix if needed
  4. Bi-directional sync: Basecamp webhooks → MC cache; MC writes → Basecamp API
  5. MC fallback: read-only mode if Basecamp unreachable, queue writes
  6. Test on Kaizen's own ops first
  7. Cut over, deprecate Fizzy, archive fizzy.do account

Effort estimate: 1-2 weeks of Carson's time. Bonus: Basecamp brings To-do lists, Messages, Docs & Files, Schedules, Check-ins — all in the canonical store. MC can surface any of them over time.

10. Appendix

A. Frameworks referenced

B. Glossary (v1.1)

C. Campfire deployment math

Architecture:

Cost @ 20 clients (illustrative):

Savings: ~$300/mo at 20-client scale + full data ownership + native per-client isolation.

Deployment command

docker run \
  --publish 80:80 --publish 443:443 \
  --restart unless-stopped \
  --volume campfire-{slug}:/rails/storage \
  --env SECRET_KEY_BASE=$YOUR_SECRET_KEY_BASE \
  --env VAPID_PUBLIC_KEY=$YOUR_PUBLIC_KEY \
  --env VAPID_PRIVATE_KEY=$YOUR_PRIVATE_KEY \
  --env SSL_DOMAIN={slug}.kaizenportal.com \
  campfire

Wrap in a provisioning script Percy calls per new client. DNS for *.kaizenportal.com wildcards to a single rule.

Hermes agent → Campfire wiring

  1. Each Hermes agent exposes a webhook (e.g. https://hermes.kaizenailab.com/agents/percy/webhook)
  2. In each Campfire instance, admin adds a bot with that webhook URL
  3. Campfire returns per-room URLs the bot can POST to
  4. Save those URLs in Supabase, scoped per agent

Kai (per-client): Each client's Campfire registers Kai with webhook → https://kai-{slug}.kaizenailab.com/webhook, served by the client's dedicated Hermes workspace. Kai inherits client's seed docs, integrations, and isolation by construction.