QQQ
Quick Query Quorum is a minimal, in-memory multi-user chat with an OpenAI-compatible AI facilitator. It provides one self-contained Rust binary and a browser interface with no database or frontend build step.
Sessions, credentials, history, and generated audio exist only in process
memory and disappear on restart. Participant tokens remain in browser
sessionStorage; they are sent as bearer credentials and never appear in URLs
or session views.
The first interaction is a private AI conversation, not a group session. QQQ creates a joinable session only after the user explicitly requests a group conversation and provides a concrete group purpose. Display names and language are optional.
Install
Install the latest release from crates.io:
Create the configuration and start QQQ:
# Set OPENAI_API_KEY and CHAT_MODEL for text mode.
Open http://127.0.0.1:8787 and press the orb.
To run directly from a checkout, use cargo run --release. Exported variables
override values loaded from .env.
Docker
Release images are published for linux/amd64 and linux/arm64:
Pin a version tag such as 0.1.2 in production. QQQ must bind to 0.0.0.0
inside a container for the published port to be reachable.
Configuration
| Variable | Default | Purpose |
|---|---|---|
QQQ_BIND |
127.0.0.1:8787 |
Listener address |
OPENAI_BASE_URL |
https://openrouter.ai/api/v1 |
OpenAI-compatible API base URL |
OPENAI_API_KEY |
required | Server-only provider credential |
CHAT_MODEL |
required | Chat-completion model |
STT_MODEL |
unset | Speech-to-text model; set with both TTS variables to enable voice mode |
TTS_MODEL |
unset | Text-to-speech model; set with STT model and TTS voice to enable voice mode |
TTS_VOICE |
unset | Text-to-speech voice; set with both model variables to enable voice mode |
TTS_FORMAT |
mp3 |
Speech response format |
OPENAI_HTTP_REFERER |
unset | Optional provider attribution header |
OPENAI_APP_TITLE |
unset | Optional provider attribution header |
MAX_SESSIONS |
100 |
Maximum active in-memory sessions |
MAX_PARTICIPANTS_PER_SESSION |
8 |
Maximum participants per session |
SESSION_TTL_SECONDS |
14400 |
Idle session lifetime |
MAX_HISTORY_MESSAGES |
512 |
Append-only history limit |
MAX_AUDIO_BYTES |
10000000 |
Multipart audio upload limit |
INPUT_BATCH_MS |
350 |
Model input batching interval |
DELIVERY_TIMEOUT_SECONDS |
45 |
Delivery progress timeout |
DEFAULT_LANGUAGE |
en |
Onboarding and STT fallback language |
PRIVATE_CONVERSATION_PROMPT |
built-in private-assistant prompt | Private onboarding system prompt; must preserve explicit group intent and concrete-purpose requirements |
GROUP_SESSION_PROTOCOL_PROMPT |
built-in delivery protocol | Appended to the model-generated, use-case-specific group prompt after promotion |
The selected provider and base URL must support chat completions. Voice mode also requires speech generation and transcription.
API Model
Public routes are GET / and GET /health. POST /api/sessions initially
creates a private provisional conversation; it becomes joinable and
URL-addressable only after explicit promotion through bootstrap. Joining uses
POST /api/sessions/:id/join. All other session routes require bearer authentication, including the WebSocket hello at
/api/sessions/:id/ws.
History begins with one stable system message and is append-only. User messages
preserve arrival order, and each assistant send_messages tool call remains
paired with its tool result. Each session runs one model call at a time.
Deliveries play in FIFO order. Each dispatch independently may update the displayed next-speaker hint when it completes; participant input remains open to every connected participant.
Development
Run the same checks as CI:
Offline tests exercise in-process Axum routes, authorization, multipart and raw audio validation, delivery transitions, and WebSocket semantics.
Live Provider Tests
Ignored live tests use real provider requests and spend credits. Put credentials
and model names in the ignored .env.test, then source it without printing its
contents:
The paid suite validates private-to-group promotion, a generic three-participant
dispatch scenario, forced tool calls, and a real TTS-to-STT round trip. A manually
dispatched Live provider E2E GitHub workflow runs the same checks with secrets
from the protected openrouter-e2e environment.
HTTPS And Limits
Mobile microphone access requires trusted HTTPS. Terminate TLS at a same-origin reverse proxy; QQQ intentionally does not implement TLS:
location / {
proxy_pass http://127.0.0.1:8787;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
QQQ intentionally provides one process with no persistence, accounts, recovery, audio broadcast, database, or history truncation. A session closes when it reaches its history limit.
License
QQQ is available under the MIT License.