| tier | STANDARD-DEEP |
|---|---|
| type | agent-system |
| owner | claude-code |
| status | shipped-draft-pr |
| date_created | 2026-07-17 |
| date_updated | 2026-07-17 |
| doc_number | 1187 |
ZAI (ZAO Assistant/Community Companion) is a new Discord bot that captures live voice channel conversations, transcribes them in real-time via Groq Whisper, and answers questions about the ongoing discussion using Claude. ZAI is warm, approachable, and plain-spoken - the public-facing community assistant for The ZAO ecosystem.
ZAI connects to a Discord server's voice channel and:
- Captures all participant audio in real-time
- Transcribes live via Groq's Whisper API (free tier, fast, handles Opus directly)
- Answers questions about the conversation as it happens using Claude 3.5 Sonnet
- Summarizes with action items when requested
- Saves transcripts to
~/.zao/private/per PII hygiene rules (third-party voices = PII)
Slash commands for easy interaction:
/join- bot joins your voice channel, starts capturing/ask <question>- get an answer about the live conversation/summary- receive a summary + extracted action items/stop- end capture, save transcript, post to text channel
Discord Voice Channel
↓ (receive all speakers' audio)
VoiceReceiver (Discord.js)
↓ (subscribe to each speaker's Opus stream)
Opus Decoder (prism-media / @discordjs/opus)
↓ (buffer 12s chunks per speaker, detect silence)
Groq Whisper API
↓ (fast transcription, free tier)
In-Memory Transcript
↓ (periodically flush to file)
~/.zao/private/discord-<sessionId>/transcript.jsonl
- Transcription: Reuses
bot/src/zoe/transcribe.tstranscribeAudio(buffer)helper (Groq Whisper Large v3 Turbo) - Q&A: Claude 3.5 Sonnet (via ANTHROPIC_API_KEY) for conversational answers with the ZAI persona
- Summaries: Same Claude call, structured JSON response (title, overview, action items, key topics)
bot/src/zai/
├── index.ts # Main bot entrypoint + slash command handlers
├── types.ts # Zod-validated command/session types
├── voice-capture.ts # VoiceReceiver subscription + Groq transcription
├── llm-handler.ts # Claude calls for Q&A + summaries
└── config.ts # Env var validation (Zod, strict)
- Go to Discord Developer Portal
- Click "New Application" → name it "ZAI"
- Go to Bot → click "Add Bot"
- Under TOKEN, copy the bot token
- Save to
~/.zao/private/discord.env:DISCORD_CAPTURE_TOKEN=<your-bot-token>
- Under Intents, enable:
- Server Members Intent (GUILD_MEMBERS)
- Message Content Intent (MESSAGE_CONTENT)
- Audio Activities (GUILD_VOICE_STATES)
- Under OAuth2 / URL Generator, select scopes + permissions:
- Scopes:
bot,applications.commands - Permissions:
Connect,Speak,Use Voice Activity,Send Messages,Read Messages/View Channels
- Scopes:
- Copy the generated URL, open it to invite ZAI to your server
In ~/.zao/private/discord.env:
# Discord bot token (from Developer Portal)
DISCORD_CAPTURE_TOKEN=<bot-token>
# Server ID where ZAI operates (find via Developer Mode in Discord)
ZAAL_GUILD_ID=<your-guild-id>
# Zaal's user ID (for admin checks, optional - find via message context menu)
ZAAL_USER_ID=<your-user-id>
# Groq API key (free from console.groq.com)
GROQ_API_KEY=<groq-key>
# Anthropic API key (for Claude access)
ANTHROPIC_API_KEY=<anthropic-key>Or rename DISCORD_CAPTURE_TOKEN to ZAI_DISCORD_TOKEN - the code checks both.
In the bot directory:
# Install deps (new: @discordjs/voice, @discordjs/opus, prism-media)
npm install
# Load env and run
export ZAI_ENV_FILE=~/.zao/private/discord.env
npx tsx src/zai/index.tsSave to ~/.config/systemd/user/zai-bot.service:
[Unit]
Description=ZAI Discord Live Voice Capture Bot
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/env npx tsx /path/to/bot/src/zai/index.ts
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
EnvironmentFile=%h/.zao/private/discord.env
WorkingDirectory=/path/to/bot
[Install]
WantedBy=default.targetThen:
systemctl --user daemon-reload
systemctl --user start zai-bot
systemctl --user enable zai-bot
journalctl --user -u zai-bot -f- Bot token loaded from env only (never in code)
- Zod validation on all config on startup (hard fail if missing)
- No logging of tokens/keys
- See
.claude/rules/secret-hygiene.mdfor full guards
- All transcripts written to
~/.zao/private/discord-<sessionId>/(not in repo) - Third-party voices are PII → never committed
- Session files are personal/sensitive → stored outside ZAOOS repo
- See
.claude/rules/pii-hygiene.mdRule 1
- All inputs validated with Zod (
safeParse) - No
anytypes (full TypeScript) - Error handling with proper catch typing
- Follows
bot/src/zoepatterns (same repo conventions)
- Slash command registration + routing
- Voice channel connection + subscription
- Groq Whisper transcription (reusing
bot/src/zoe/transcribe.ts) - In-memory transcript + file persistence
- Claude Q&A + summary generation
- Message splitting for Discord's 2000-char limit
- Live update embeds (throttled)
- Full TypeScript, zero
any, Zod validation - Systemd unit template
The code is feature-complete and type-safe. It cannot be tested without:
- A Discord bot token (requires Developer Portal setup)
- A Discord server with voice channels
- Groq + Anthropic API keys configured
Boot verification (non-interactive):
npm run typecheck # zero errors
npx tsx -e "import('./src/zai/types.ts')" # modules load
npx tsx -e "import('./src/zai/voice-capture.ts')" # modules load
npx tsx -e "import('./src/zai/llm-handler.ts')" # modules load
# DO NOT import index.ts - it will try to start the bot- Free tier with no rate limits (matches ZOE's use of Groq)
- Whisper Large v3 Turbo is fast + accurate
- Handles Opus directly (no local ffmpeg needed)
- Reuses existing
transcribeAudio()helper frombot/src/zoe/transcribe.ts - No new npm dependencies for transcription
- ZAI persona is warm + community-focused (different from ZOE's ops voice)
- Claude's instruction-following makes persona adoption clean
- System prompt baked in (easy to update ZAI's voice)
- Faster than multi-turn Groq for context windows
- Groq handles the full pipeline (Opus decoding + transcription)
- Discord.js VoiceReceiver already receives Opus packets
- Local Whisper would require ffmpeg + model weights on VPS
- Current design scales to arbitrary voice counts (parallel Groq calls)
- PII rule: third-party voices recorded in a conversation = personal data
- Outside the repo = cannot be accidentally committed
- Session-based organization (one dir per capture)
- Consistent with ZOE's private data layout
- Speaker identification (map Discord usernames to voices, not just stream-based)
- Keyword extraction + timestamp linking
- Conversation topics clustering
- Integration with Bonfire for knowledge graph auto-ingest
- Web dashboard (recent captures, searchable transcripts)
- Slack/Telegram forwarding of summaries
- Multi-channel simultaneous capture
- Custom prompts per server (ZAI persona variants)
bot/src/zoe/transcribe.ts- Groq Whisper integration (reused)bot/src/zoe/concierge.ts- Claude integration pattern (reference).claude/rules/secret-hygiene.md- env var + token rules.claude/rules/pii-hygiene.md- transcript storage rules- Doc 601 - Agent stack cleanup (ZAI vs ZOE vs ZOL taxonomy)
ZAI is:
- Warm - greets users, celebrates good moments
- Plain-spoken - no jargon, direct communication
- Community-focused - cares about The ZAO ecosystem + its people
- Helpful - remembers context, proactive suggestions
- Humble - admits when something isn't captured yet or needs clarification
Contrasts:
- NOT ZOE (ZOE = ops orchestrator, private, systematic)
- NOT ZOL (ZOL = social media voice, public broadcasts)
- IS the community's assistant (public-facing, always on, always helpful)
- Code complete (all 4 modules)
- Types sound (Zod, no
any) - Secrets safe (env only, no tokens in code)
- PII safe (transcripts to
~/.zao/private/) - Boot-verifiable (tsc, import checks on non-entrypoint modules)
- Design doc complete (this file)
- Systemd template included
- Package.json updated with deps
- PR to main (DRAFT, awaiting token setup before live test)
To get ZAI live:
- Follow "Discord App Creation" steps above → get bot token, server ID
- Populate
~/.zao/private/discord.env - On VPS:
cd ~/zao-os && npm install && systemctl --user start zai-bot - In Discord: type
/joinin a text channel while in a voice channel - Test with
/ask "who just spoke?"and/summary - Shut down with
/stoporsystemctl --user stop zai-bot
Live monitoring: journalctl --user -u zai-bot -f
Questions/issues during setup: ZAI is self-contained in bot/src/zai/ with no cross-bot dependencies. Revert by stopping the systemd unit.