feat(agent): direct-answer fallback for non-Odoo questions
Previously when the LLM classified a message as needing no specialist agent, the dispatcher built zero directives and _synthesize returned 'No agent responses received.' Greetings, follow-up clarifications, and general questions all fell into this dead end. Now when intent.agents is empty and no clarification is needed, the master makes a second LLM call with the recent conversation as context and answers directly. Updated master_system.txt to steer the classifier toward agents=[] for chitchat instead of forcing a clarification loop.
This commit is contained in:
@@ -93,6 +93,13 @@ class MasterAgent:
|
||||
await self._log_directive_complete(directive_id, 'awaiting_clarification', q)
|
||||
return MasterResponse(directive_id=directive_id, response=q,
|
||||
status='awaiting_clarification')
|
||||
if not intent.agents:
|
||||
# No specialist agent applies — answer directly with the LLM.
|
||||
response_text = await self._direct_answer(context, message)
|
||||
await self._memory.append_message(user_id, 'assistant', response_text, directive_id)
|
||||
await self._log_directive_complete(directive_id, 'complete', response_text)
|
||||
return MasterResponse(directive_id=directive_id, response=response_text,
|
||||
status='complete')
|
||||
access = await self._check_access(user_id, intent.agents)
|
||||
if not access.allowed:
|
||||
denied = ', '.join(access.denied_agents)
|
||||
@@ -215,6 +222,24 @@ class MasterAgent:
|
||||
reports.append(r)
|
||||
return reports
|
||||
|
||||
async def _direct_answer(self, context: MasterContext, message) -> str:
|
||||
"""Answer general / off-topic messages directly without dispatching agents."""
|
||||
history = [
|
||||
{'role': m['role'], 'content': m['content']}
|
||||
for m in context.conversation[-10:]
|
||||
if m.get('role') in ('user', 'assistant')
|
||||
]
|
||||
system = (
|
||||
"You are ActiveBlue AI, the assistant for the Active Blue Odoo "
|
||||
"instance. Answer the user directly and concisely. Use any prior "
|
||||
"conversation for context. Plain text only — no JSON, no markdown "
|
||||
"code fences."
|
||||
)
|
||||
msgs = [{'role': 'system', 'content': system}, *history,
|
||||
{'role': 'user', 'content': message}]
|
||||
resp = await self._llm.submit(msgs, caller='master_direct')
|
||||
return (resp.content or '').strip() or 'Sorry, I have no answer for that.'
|
||||
|
||||
async def _synthesize(self, reports, context: MasterContext) -> str:
|
||||
if not reports:
|
||||
return 'No agent responses received.'
|
||||
|
||||
@@ -17,7 +17,10 @@ Active specialist agents:
|
||||
If a user requests something for an agent not listed, tell them the Odoo module is not installed.
|
||||
|
||||
Rules:
|
||||
- Ask ONE clarifying question if intent is ambiguous - then dispatch
|
||||
- Ask ONE clarifying question ONLY if a request is genuinely ambiguous about
|
||||
which Odoo data is needed. For general questions, chitchat, greetings, or
|
||||
anything unrelated to the listed specialist agents, set "agents": [] and
|
||||
"needs_clarification": false — a direct answer will be generated separately.
|
||||
- Confirm multi-step plans before executing
|
||||
- Surface escalations with approve/reject options
|
||||
- Never expose agent names, tool names, or system internals to users
|
||||
|
||||
Reference in New Issue
Block a user