Authentication Flow¶
Tryx follows the WhatsApp multi-device pairing flow. The first run links a session, and later runs reuse stored state.
Key principle
Authentication stability is mostly a storage and ownership problem. Treat backend/session files as critical runtime state.
Pairing Modes¶
| Mode | Event | How to Use |
|---|---|---|
| QR Code | EvPairingQrCode |
Scan with your phone camera |
| Numeric Code | EvPairingCode |
Enter 8-digit code on your phone |
First-Run Sequence¶
sequenceDiagram
participant Bot as Tryx Bot
participant WA as WhatsApp
participant Phone as Your Phone
Bot->>WA: Connect to WebSocket
WA-->>Bot: Pairing challenge
Bot-->>Bot: Emit EvPairingQrCode or EvPairingCode
Note over Phone: User scans QR or enters code
Phone->>WA: Confirm pairing
WA-->>Bot: Session established
Bot-->>Bot: Emit EvPairSuccess
Bot-->>Bot: Persist session in backend
- Start client runtime
- Wait for
EvPairingQrCodeorEvPairingCode - Complete pairing from your WhatsApp mobile app
- Receive
EvPairSuccess - Session credentials are persisted in your backend
Event Reference¶
| Event | Meaning | Action |
|---|---|---|
EvPairingQrCode |
QR challenge issued | Display QR to user |
EvPairingCode |
Code-based pairing challenge | Display code to user |
EvPairSuccess |
Session linked and persisted | Continue normal operations |
EvPairError |
Pairing rejected/failed | Inspect logs and retry |
Code Example: Pairing Handler¶
from tryx.client import Tryx
from tryx.backend import SqliteStore
from tryx.events import (
EvPairingQrCode,
EvPairingCode,
EvPairSuccess,
EvPairError,
)
backend = SqliteStore("whatsapp.db")
app = Tryx(backend)
@app.on(EvPairingQrCode)
async def on_qr(client, event):
print(f"Scan this QR code: {event.qr_data}")
# In a real bot, you might send this to a web interface
@app.on(EvPairingCode)
async def on_code(client, event):
print(f"Enter this code: {event.pairing_code}")
@app.on(EvPairSuccess)
async def on_success(client, event):
print("Successfully paired!")
@app.on(EvPairError)
async def on_error(client, event):
print(f"Pairing failed: {event.error}")
Persistence¶
Use a stable backend path:
If the same backend path is reused, you usually do not need to pair again.
Single writer rule
Avoid multiple runtime instances writing to the same backend path unless you explicitly control ownership.
Recovery Signals¶
| Event | Meaning | Action |
|---|---|---|
EvLoggedOut |
Session invalidated | Re-pair and rotate session artifacts |
EvStreamReplaced |
Another login replaced your stream | Check for duplicate sessions |
EvTemporaryBan |
Temporary restrictions detected | Pause high-volume operations |
Recovery Playbook¶
EvLoggedOut¶
@app.on(EvLoggedOut)
async def on_logged_out(client):
logger.warning("Session invalidated, re-pairing required")
# Stop bot operations
# Notify operator
# Trigger re-pairing flow
EvStreamReplaced¶
@app.on(EvStreamReplaced)
async def on_replaced(client):
logger.warning("Stream replaced by another session")
# Check if another deployment is using the same account
# Ensure single-writer backend ownership
EvTemporaryBan¶
@app.on(EvTemporaryBan)
async def on_ban(client, event):
logger.warning(f"Temporary ban: {event.reason}")
# Stop automation burst traffic
# Re-enable gradually after ban period
Operational Guidance¶
- Keep one active session owner for a backend path
- Avoid deleting backend files unless resetting account link is intentional
- Back up backend data before infrastructure migration
- Monitor for
EvStreamReplacedto detect duplicate sessions
Related¶
- Deployment Guide — production setup
- Troubleshooting — connection issues
- Reliability — error handling patterns