fix: prevent master agent asking for clarification when receipts are uploaded

When a zip/image arrives via /upload, the LLM was classifying the
message as needs_clarification=True (because the chat body was just a
filename like "download (8).zip", not an instruction), and the early
return on line 91 fired before the receipts safety guard on line 106,
so the guard never executed.

master_agent: move the receipts safety guard to BEFORE the
needs_clarification early-return.  If extra_context contains receipts,
unconditionally set needs_clarification=False and ensure expenses_agent
is in the agents list — the LLM cannot veto an upload with a question.

upload router: normalize empty or filename-only messages (e.g. when the
user drops a file in Discuss chat with no text) to
"Create an expense report from these uploaded receipts." so the LLM
intent classification also has a sensible string to work with.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Carlos Garcia
2026-05-20 22:13:46 -04:00
parent 68b7b3f0f3
commit cc025695ac
2 changed files with 24 additions and 5 deletions

View File

@@ -88,6 +88,17 @@ class MasterAgent:
await self._memory.append_message(user_id, 'user', message, directive_id)
context = await self._build_context(user_id, message)
intent = await self._classify_intent(context, message)
# Safety guard: when receipts arrive via the upload flow, always
# route to expenses_agent — regardless of what the LLM decided.
# MUST run BEFORE the needs_clarification early-return; otherwise an
# LLM that asks "please provide more context" blocks a valid upload.
if (extra_context or {}).get('receipts'):
intent.needs_clarification = False
intent.clarification_question = None
if 'expenses_agent' not in intent.agents:
intent.agents.append('expenses_agent')
if intent.needs_clarification:
q = intent.clarification_question or 'Could you provide more details?'
await self._memory.append_message(user_id, 'assistant', q, directive_id)
@@ -101,11 +112,6 @@ class MasterAgent:
await self._log_directive_complete(directive_id, 'complete', response_text)
return MasterResponse(directive_id=directive_id, response=response_text,
status='complete')
# When receipts are present (upload flow), always dispatch expenses_agent
# even if the user's message is a one-word reply like "skip duplicates".
if (extra_context or {}).get('receipts') and 'expenses_agent' not in intent.agents:
intent.agents.append('expenses_agent')
intent.needs_clarification = False
access = await self._check_access(user_id, intent.agents)
if not access.allowed:
denied = ', '.join(access.denied_agents)