feat: force the planning agent to ask questions
This commit is contained in:
@@ -734,8 +734,6 @@ Write a brief intro (1-2 sentences), then call the tool:
|
||||
])
|
||||
|
||||
Examples (single question):
|
||||
- ask_user("What do you need?",
|
||||
["Build a new agent", "Run the loaded worker", "Help with code"])
|
||||
- ask_user("Ready to proceed?",
|
||||
["Yes, go ahead", "Let me change something"])
|
||||
|
||||
|
||||
@@ -90,6 +90,28 @@ async def create_queen(
|
||||
phase_state = QueenPhaseState(phase=initial_phase, event_bus=session.event_bus)
|
||||
session.phase_state = phase_state
|
||||
|
||||
# ---- Track ask rounds during planning ----------------------------
|
||||
# Increment planning_ask_rounds each time the queen requests user
|
||||
# input (ask_user or ask_user_multiple) while in the planning phase.
|
||||
async def _track_planning_asks(event: AgentEvent) -> None:
|
||||
if phase_state.phase != "planning":
|
||||
return
|
||||
# Only count explicit ask_user / ask_user_multiple calls, not
|
||||
# auto-block (text-only turns emit CLIENT_INPUT_REQUESTED with
|
||||
# an empty prompt and no options/questions).
|
||||
data = event.data or {}
|
||||
has_prompt = bool(data.get("prompt"))
|
||||
has_questions = bool(data.get("questions"))
|
||||
has_options = bool(data.get("options"))
|
||||
if has_prompt or has_questions or has_options:
|
||||
phase_state.planning_ask_rounds += 1
|
||||
|
||||
session.event_bus.subscribe(
|
||||
[EventType.CLIENT_INPUT_REQUESTED],
|
||||
_track_planning_asks,
|
||||
filter_stream="queen",
|
||||
)
|
||||
|
||||
# ---- Lifecycle tools (always registered) --------------------------
|
||||
register_queen_lifecycle_tools(
|
||||
queen_registry,
|
||||
@@ -149,7 +171,8 @@ async def create_queen(
|
||||
worker_identity = (
|
||||
"\n\n# Worker Profile\n"
|
||||
"No worker agent loaded. You are operating independently.\n"
|
||||
"Handle all tasks directly using your coding tools."
|
||||
"Design or build the agent to solve the user's problem "
|
||||
"according to your current phase."
|
||||
)
|
||||
|
||||
_planning_body = (
|
||||
|
||||
@@ -765,7 +765,8 @@ class SessionManager:
|
||||
|
||||
await node.inject_event(
|
||||
"[SYSTEM] Worker unloaded. You are now operating independently. "
|
||||
"Handle all tasks directly using your coding tools."
|
||||
"Design or build the agent to solve the user's problem "
|
||||
"according to your current phase."
|
||||
)
|
||||
|
||||
async def revive_queen(self, session: Session, initial_prompt: str | None = None) -> None:
|
||||
|
||||
@@ -95,6 +95,10 @@ class QueenPhaseState:
|
||||
# Built during decision-node dissolution at confirm_and_build().
|
||||
flowchart_map: dict[str, list[str]] | None = None
|
||||
|
||||
# Counter for ask_user / ask_user_multiple rounds during planning phase.
|
||||
# Incremented via event bus subscription in queen_orchestrator.
|
||||
planning_ask_rounds: int = 0
|
||||
|
||||
# Agent path — set after scaffolding so the frontend can query credentials
|
||||
agent_path: str | None = None
|
||||
|
||||
@@ -1251,6 +1255,34 @@ def register_queen_lifecycle_tools(
|
||||
with a unique color. The queen can override auto-detection by setting
|
||||
flowchart_type explicitly on a node.
|
||||
"""
|
||||
# ── Gate: require at least 2 rounds of user questions ─────────
|
||||
if (
|
||||
phase_state is not None
|
||||
and phase_state.phase == "planning"
|
||||
and phase_state.planning_ask_rounds < 2
|
||||
):
|
||||
return json.dumps({
|
||||
"error": (
|
||||
"You haven't asked enough questions yet. You have only "
|
||||
f"asked {phase_state.planning_ask_rounds} round(s) of "
|
||||
"questions — at least 2 are required before saving a "
|
||||
"draft. Think deeper and ask more practical questions "
|
||||
"to fully understand the user's requirements before "
|
||||
"designing the agent graph."
|
||||
)
|
||||
})
|
||||
|
||||
# ── Gate: require at least 5 nodes for a meaningful graph ─────
|
||||
if len(nodes) < 5:
|
||||
return json.dumps({
|
||||
"error": (
|
||||
f"Draft only has {len(nodes)} node(s) — at least 5 are "
|
||||
"required for a meaningful agent graph. Think deeper and "
|
||||
"ask more practical questions to fully understand the "
|
||||
"user's requirements, then design a more thorough graph."
|
||||
)
|
||||
})
|
||||
|
||||
# Loose validation: each node needs at minimum an id
|
||||
validated_nodes = []
|
||||
for i, n in enumerate(nodes):
|
||||
|
||||
@@ -13,7 +13,8 @@ from framework.agents.queen.nodes import (
|
||||
_DEFAULT_WORKER_IDENTITY = (
|
||||
"\n\n# Worker Profile\n"
|
||||
"No worker agent loaded. You are operating independently.\n"
|
||||
"Handle all tasks directly using your coding tools."
|
||||
"Design or build the agent to solve the user's problem "
|
||||
"according to your current phase."
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user