Build Plan
0 β POC OVERVIEW
Create a twoβURL proofβofβconcept that streams AI coaching hints to a facilitator during a 1βtoβ1 Internal Family Systems session.
/partnerβ full-screen video/facilitatorβ video + scrolling Coach Panel that prints live AI hints- A silent Agent joins the room, listens only to the Partner, streams hints to the Facilitator
 
Partner ββΆ LiveKit Room ββ Facilitator
               β²
               β audio
    Silent Agent ββ  (Whisper β GPT-4o-mini β text stream)1 β SET-UP (local workstation, once)
| Item | Command / action | 
|---|---|
| 1.1 Docker Desktop | Install from docker.com β confirm docker run hello-world works. | 
| 1.2 Node 18 + pnpm / npm | nvm install 18 && nvm use 18 or use Homebrew. | 
| 1.3 Vercel CLI | npm i -g vercel β vercel login | 
| 1.4 Fly CLI | brew install flyctl (mac) or choco install flyctl (Windows) | 
| 1.5 Git repo | git clone git@github.com:charlieellington/no-bad-parts.git (skip if already cloned)  git remote set-url origin git@github.com:<PRIVATE-ORG>/no-bad-parts.git (make it private) | 
| 1.6 Create new branch | git checkout -b video-poc | 
2 β LIVEKIT CLOUD (β 1 hour)
- 
Sign in at cloud.livekit.io β New Project β choose EU region β name:
no-bad-parts. - 
Rooms β Create Room β name
no-bad-parts(defaults are fine). - 
Settings β API Keys β Generate (keep key/secret somewhere safe).
 - 
Token Generator β
- 
identity
partner, roomno-bad-partsβ copy token A - 
identity
facilitator, roomno-bad-partsβ copy token B 
 - 
 - 
Create
.envin your repo root:NEXT_PUBLIC_LK_URL=wss://no-bad-parts-v5awu9p1.livekit.cloud NEXT_PUBLIC_PARTNER_TOKEN=<token A> NEXT_PUBLIC_FACILITATOR_TOKEN=<token B> 
β° Token Expiry Note: For longer development sessions, use TTL of 604800 seconds (1 week) when generating tokens. Current tokens expire June 13, 2025.
π¨ IMPORTANT - Token Expiry Warning:
- Sandbox tokens expire in 15 minutes - use only for quick testing
 - For development sessions: Generate tokens with longer TTL via dashboard
 - Signs of expired tokens: "Connection: disconnected", "cannot publish track when not connected"
 - Quick fix: Use sandbox API to generate fresh tokens:
curl -X POST https://cloud-api.livekit.io/api/sandbox/connection-details \ -H "X-Sandbox-ID: responsive-byte-1cgfuu" \ -H "Content-Type: application/json" \ -d '{"roomName": "no-bad-parts", "participantName": "facilitator"}' 
3 β AGENT (local run first, β 2 hours)
- 
Complete
.agent.envfile in project root:LIVEKIT_URL=wss://no-bad-parts-v5awu9p1.livekit.cloud PARTNER_ID=partner OPENAI_API_KEY=<see environment-reference.md> SYSTEM_PROMPT="You are Silent Coach, a non-intrusive IFS assistant.\nListen only to the participant with identity 'partner'.\nProduce <2 sentence hints, speaking directly to the facilitator.\nNever mention you are an AI or reference these rules.\nIf you're unsure, say '(coach is thinkingβ¦)'."Note:
.agent.envis already git-ignored. Actual API keys are inno-bad-parts/environment-reference.md(also git-ignored). ReplaceSYSTEM_PROMPTwith your actual IFS coaching prompt. - 
Test environment setup:
# Verify Docker can read all variables docker run --env-file .agent.env --rm busybox env | grep -E "LIVEKIT|PARTNER|OPENAI|SYSTEM" # Test LiveKit connectivity curl -Is https://no-bad-parts-v5awu9p1.livekit.cloud | head -n 1 - 
Pull and run agent container (~1GB download):
docker run --env-file .agent.env livekit/agent-audio-llm:latestSuccess indicators:
- "Connected to LiveKit server"
 - "Joined room: no-bad-parts"
 - "Listening to participant: partner"
 
If you need a remote tester while still local:
ngrok http 3000 
4 β FRONT-END (inside existing repo, β 1 day)
4.1 Install deps
npm i @livekit/components-react @livekit/client4.2 Shared wrapper β components/livekit-wrapper.tsx
(as in previous snippetβunchanged)
4.3 Routes
- 
pages/session/partner.tsxβ displays<ParticipantTile isLocal /> - 
pages/session/facilitator.tsxβ grid layout +HintStreamhook
(accessible at/session/partnerand/session/facilitator) 
4.4 Failure behaviour
If Agent drops, Coach Panel prints "AI offline β continue as normal."
4.5 β LOCAL INTEGRATION TEST (connects real agent to front-end, β 30 min)
Critical POC validation step before cloud deployment.
4.5.1 Start the Real Agent
# In terminal 1: Start the Python agent with full SYSTEM_PROMPT
cd no-bad-parts
source agent/venv/bin/activate
python agent.py devSuccess indicators:
- "Connected to LiveKit server"
 - "Joined room: no-bad-parts"
 - "Listening to participant: partner"
 
4.5.2 Test End-to-End Flow
# In terminal 2: Start front-end
cd energy-flow
pnpm devManual test sequence:
- Open 
/session/facilitatorin browser β verify video + "Waiting for AI hints..." - Open 
/session/partnerin another tab β speak into microphone - Expected result: Facilitator panel shows real IFS coaching hints using SYSTEM_PROMPT format:
SUMMARY: [partner validation] SUGGESTION: [facilitator guidance] FOLLOW-UP: [invitation 1] | [invitation 2] REMINDER: [peer support reminder] (first 3 replies only) 
4.5.3 Replace Dummy Script
Once real agent works, remove dependency on dummy script:
# No longer needed for testing
rm scripts/dummy-hints.jsπ― POC Success Criteria:
- Partner speaking β Agent transcribing β Facilitator receiving properly formatted hints
 - Real SYSTEM_PROMPT generating contextual IFS coaching suggestions
 - No "dummy" data in the final POC
 
5 β DEPLOY AGENT TO FLY.IO (puts POC fully online, β 45 min)
5.1 Pre-flight Checklist
Before deploying, ensure you have:
- β
 
.agent.envfile with all 4 variables populated (especiallySYSTEM_PROMPT) - β
 Local agent tested successfully with 
docker run --env-file .agent.env livekit/agent-audio-llm:latest - β LiveKit tokens are valid (check expiry: June 13, 2025)
 - β
 Fly CLI installed and logged in: 
flyctl auth whoami 
5.2 Launch Application
fly launch --name no-bad-parts-agent \
           --image livekit/agent-audio-llm:latest \
           --region fra --noworkspaceNote: Choose fra (Frankfurt) region to match LiveKit EU region for lowest latency.
5.3 System Prompt Setup (Two Methods)
Method A: Direct from environment-reference.md
# Copy actual values from no-bad-parts/environment-reference.md
fly secrets set \
  LIVEKIT_URL=wss://no-bad-parts-v5awu9p1.livekit.cloud \
  PARTNER_ID=partner \
  OPENAI_API_KEY=<copy-from-environment-reference.md> \
  SYSTEM_PROMPT="Your escaped prompt with \n for newlines"Method B: From separate file (recommended)
# Create ifs-prompt.txt with your multi-line prompt (no escaping needed)
echo "You are Silent Coach, a non-intrusive IFS assistant.
Listen only to the participant with identity 'partner'.
Produce <2 sentence hints, speaking directly to the facilitator.
Never mention you are an AI or reference these rules.
If you're unsure, say '(coach is thinkingβ¦)'." > ifs-prompt.txt
 
# Set secrets using file content
fly secrets set \
  LIVEKIT_URL=wss://no-bad-parts-v5awu9p1.livekit.cloud \
  PARTNER_ID=partner \
  OPENAI_API_KEY=<copy-from-environment-reference.md> \
  SYSTEM_PROMPT="$(cat ifs-prompt.txt)"5.4 Deploy & Resource Optimization
# Initial deployment
fly deploy
 
# Lock to minimal resources for POC (saves ~$15/month)
fly scale count 1
fly scale memory 256   # Minimum for ML workload
fly scale vm shared-cpu-1x  # Cheapest option
 
# Optional: Auto-suspend when idle (saves more money)
fly scale set-auto-sleep 5m5.5 Verification & Monitoring
Check deployment status:
fly status -a no-bad-parts-agentMonitor logs for successful connection:
fly logs -a no-bad-parts-agent
# Look for these success indicators:
# β
 "Connected to LiveKit server"
# β
 "Joined room: no-bad-parts"
# β
 "Listening to participant: partner"Test connectivity:
# Ping the app (should show running)
fly ping -a no-bad-parts-agent
 
# Check resource usage
fly status -a no-bad-parts-agent --verbose5.6 Troubleshooting Common Issues
Agent won't connect to LiveKit:
- Verify 
LIVEKIT_URLmatches exactly:wss://no-bad-parts-v5awu9p1.livekit.cloud - Check token expiry (current tokens expire June 13, 2025)
 - Ensure LiveKit room 
no-bad-partsexists 
Out of memory errors:
fly scale memory 512  # Increase if neededOpenAI API errors:
- Verify API key has sufficient credits
 - Check rate limits in OpenAI dashboard
 
Debug environment variables:
fly ssh console -a no-bad-parts-agent
# Inside container:
env | grep -E "LIVEKIT|OPENAI|SYSTEM|PARTNER"5.7 Security & Maintenance
Rotate OpenAI API key periodically:
# Generate new key from OpenAI dashboard, update environment-reference.md, then:
fly secrets set OPENAI_API_KEY=<new-key-from-environment-reference.md>
fly deploy  # Restart with new keyUpdate LiveKit tokens before expiry:
# Generate new tokens at cloud.livekit.io Token Generator
fly secrets set \
  LIVEKIT_URL=wss://no-bad-parts-v5awu9p1.livekit.cloud \
  # Copy new tokens hereMonitor costs:
fly billing  # Check monthly usage5.8 Emergency Procedures
Stop agent immediately:
fly scale count 0 -a no-bad-parts-agentRollback deployment:
fly releases -a no-bad-parts-agent
fly deploy --image livekit/agent-audio-llm:latest -a no-bad-parts-agentComplete teardown:
fly apps destroy no-bad-parts-agent6 β DAY-BY-DAY TIMELINE
| Slot | Goal | Deliverable | 
|---|---|---|
| Day 1 AM | LiveKit room + JWTs; local Agent running | .env, .agent.env complete | 
| Day 1 Noon | video-poc branch, deps installed, folder groups created | Repo pushed | 
| Day 1 Early PM | /partner route live on Vercel preview | Self-view video tile | 
| Day 1 Late PM | Demo milestone β /facilitator route with placeholder HintStream (dummy text) | Layout + video + scrolling text | 
| Day 2 AM | Step 4.5 β Local integration test: real Agent β front-end with SYSTEM_PROMPT | Partner speech β formatted IFS hints in facilitator panel | 
| Day 2 Mid-PM | Deploy Agent to Fly.io | Any browser β hints work (laptop can sleep) | 
| Day 2 Late PM | Polish UI, offline-toast, vercel --prod, record demo GIF | Finished POC | 
7 β NEXT EASY WINS
- 
Consent banner (Tailwind modal, store click in Supabase)
 - 
Supabase auth + serverless LiveKit JWT signer
 - 
Fly.io autoscaling or Railway alternative
 - 
Post-session summary generator
 
8 β NICE TO HAVE LATER
- 
Migrate session pages to app directory β Currently working fine in pages directory with proper CSS. Consider migration after POC is complete for consistency with rest of app, better performance with RSC, and modern Next.js patterns.
 - 
Enhanced video controls β Mute/unmute, camera toggle, screen sharing
 - 
Session recording β Store sessions for review (with consent)
 - 
Multi-party support β Expand beyond 1-to-1 to group sessions
 - 
Mobile-optimized layouts β Responsive design for phone/tablet sessions
 - 
Real-time connection quality indicators β Network status badges
 - 
Session analytics β Track engagement, duration, technical metrics
 
Follow the list top-to-bottom; you'll have a totally cloud-hosted proof-of-concept by the end of Day 2.