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:

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