Planner: respuesta directa para saludos y preguntas simples

El planner ahora puede devolver direct_response en vez de un plan
cuando el mensaje no requiere herramientas (saludos, preguntas
generales, conversación casual).

- planner.py: prompt actualizado con formato direct_response
- engine.py: si planner devuelve string, emitir como texto y
  completar sin ejecutar steps

"hola" → "¡Hola! ¿En qué puedo ayudarte hoy?" (0 steps, 0 tools)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jordan Diaz
2026-04-03 20:48:28 +00:00
parent df7dfbc280
commit 56c8a9c066
2 changed files with 74 additions and 17 deletions

View File

@@ -118,8 +118,54 @@ class OrchestratorEngine:
planner_usage: dict[str, int] = {"input_tokens": 0, "output_tokens": 0}
try:
planner = self._create_agent(AgentRole.PLANNER)
plan_steps, planner_usage = await planner.plan(session)
task.plan = plan_steps
plan_result, planner_usage = await planner.plan(session)
# Direct response — no plan needed (saludo, pregunta simple)
if isinstance(plan_result, str):
logger.info("Planner returned direct response for task %s", task.task_id)
task.status = TaskStatus.COMPLETED
session.complete_task()
# Emit as text streaming for the frontend
await self.sse.emit(
EventType.AGENT_DELTA,
{"agent": "planner", "delta": plan_result, "step": 0},
session_id=session.session_id,
)
cost_usd = (
(planner_usage.get("input_tokens", 0) / 1_000_000) * settings.cost_per_1m_input
+ (planner_usage.get("output_tokens", 0) / 1_000_000) * settings.cost_per_1m_output
)
await self.sse.emit(
EventType.EXECUTION_COMPLETED,
{
"session_id": session.session_id,
"task_id": task.task_id,
"steps_completed": 0,
"steps_failed": [],
"status": "completed",
"usage": planner_usage,
"total_cost_usd": round(cost_usd, 6),
},
session_id=session.session_id,
)
return {
"session_id": session.session_id,
"task_id": task.task_id,
"content": plan_result,
"steps_completed": 0,
"steps_failed": [],
"artifacts_count": 0,
"review": "",
"status": "completed",
"usage": planner_usage,
"total_cost_usd": round(cost_usd, 6),
}
task.plan = plan_result
task.status = TaskStatus.EXECUTING
except Exception as e:
logger.error("Planning failed: %s", e)
@@ -134,7 +180,7 @@ class OrchestratorEngine:
logger.info(
"Plan created with %d steps for task %s",
len(plan_steps),
len(plan_result),
task.task_id,
)