S275 — Vitto WhatsApp Smartness Analysis
Documentation for Sessions
Vitto WhatsApp Intelligence — 7 Bugs Identified
Analysis of the WhatsApp conversation between Paco and Vitto. All root causes traced to code.
Bugs (priority order)
1. Duplicate messages (Critical)
Every response appears twice in WhatsApp.
Root cause: channel-processing.service.ts — executeUnifiedAgentLoop() calls composeAndRenderRichMessage() (which sends via WhatsApp adapter, returns alreadySent: true), then unconditionally calls routeTaskResponse() which sends the same text again. No alreadySent guard on the routeTaskResponse() call, even though one exists for quick reply buttons.
Fix: Guard routeTaskResponse() with if (!richOutput?.rendered?.alreadySent).
2. Raw LLM error leaked to user (High)
User received: [ERROR: All LLM providers failed — tool_use ids without tool_result blocks...]
Root cause: agent-loop.service.ts has a graceful fallback (lines 412-417) but only for the execute phase. Errors in PLAN/ANALYZE/VERIFY phases bypass the guard and leak via smart-router.service.ts (line 246). Also routeTaskResponse() sanitizes [ERROR:...] blocks (line ~577) but the raw error text doesn't always match the sanitization regex.
Fix: Wrap the entire agent pipeline output with an error sanitizer before sending to any channel. Make the sanitization regex in routeTaskResponse() more robust.
3. False inactivity detection (High)
"4 days since we last worked together" sent 5 hours after user chatted.
Root cause: proactive-reach.service.ts (line ~143) uses VittoMemoryService.recall("recent activity for user X") — a semantic search, not a time-based query. Returns the most semantically similar memory, which may be days old. Actual conversation timestamps are not checked.
Fix: Replace semantic recall() with a direct timestamp query (last conversation message or last task execution).
4. Wrong timezone (High)
Vitto said "Son las 5am" when it was 11:52 PM for the user.
Root cause: channel-prompt-builder.service.ts (lines 58-59) uses new Date().getHours() — server clock. The user's timezone exists in dossier.identity.timezone but is never used when building the prompt context.
Fix: Read dossier.identity.timezone, convert server time to user's local time.
5. Duplicate daily digests (Medium)
Same digest sent at 3:00 AM and 8:00 AM.
Root cause: Only one @Cron('0 8 * * *') in daily-digest.service.ts. The 3 AM send comes from something external (scheduler, manual API call to POST /proactive/digest/send). Zero deduplication logic — no check if digest was already sent today, no timestamp tracking per user.
Fix: Add date-based deduplication (skip if already sent today per user). Investigate external 3 AM trigger.
6. Filler/thinking messages (Medium)
"Got it!", "One sec, looking into it...", "Here's what I found." sent as separate WhatsApp messages.
Root cause: VittoExpressionService ACK_POOLS and PROGRESS_POOLS (code-driven, not LLM). Budget-capped at 2 max. But combined with the duplicate bug (#1), users see 3+ pre-response messages.
Agreed design direction:
- WhatsApp: 1 contextual ack max, only for >3s responses. Zero progress messages. Typing indicator is enough.
- Web chat: Rich real-time streaming via SSE (already in place), NOT separate messages. Enhance SSE events for reasoning/tool visibility.
7. "Here's what I found" after error (Low)
Progress message fires regardless of LLM success.
Root cause: WhatsAppProgressEmitter sends messages independently of LLM outcome. When the LLM fails (#2), the progress message still fires, creating a confusing sequence.
Fix: Resolved by fixing #2 (error handling) and #6 (reducing filler messages).
Key files
| File | Role |
|---|---|
APIs/backend-vitto-api/src/app/engine/channel-processing.service.ts |
Main pipeline: ACK, agent loop, response routing |
APIs/backend-vitto-api/src/app/engine/agent-loop.service.ts |
LLM calls, tool execution, error handling |
APIs/backend-vitto-api/src/app/engine/context-assembly/channel-prompt-builder.service.ts |
System prompt: time, personality, memories |
APIs/backend-vitto-api/src/app/engine/vitto-expression.service.ts |
ACK_POOLS, PROGRESS_POOLS, reactions |
APIs/backend-vitto-api/src/app/engine/whatsapp-progress-emitter.ts |
Budget-aware progress messages |
APIs/backend-vitto-api/src/app/proactive/daily-digest.service.ts |
Digest cron + delivery |
APIs/backend-vitto-api/src/app/proactive/proactive-reach.service.ts |
Inactivity detection + check-in |
APIs/backend-vitto-api/src/app/engine/adapters/whatsapp-channel.adapter.ts |
Rich message rendering |
Status
- Awaiting cowork agent's document with Twilio template registration details and any additional findings
- Will resume with full design spec + implementation plan after cowork input