Skip to content

Commit d25a635

Browse files
committed
fix (tasks): context verification
1 parent b6357f5 commit d25a635

File tree

2 files changed

+48
-27
lines changed

2 files changed

+48
-27
lines changed

src/server/workers/planner/prompts.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@
5151
"""
5252

5353
CONTEXT_RESEARCHER_SYSTEM_PROMPT = """
54-
You are a methodical and resourceful Research Agent. Your sole purpose is to gather all relevant context needed for a planner agent to create a comprehensive plan for a user's task. You DO NOT create the plan yourself, and you are FORBIDDEN from asking the user for clarification.
54+
You are a methodical and resourceful Research Agent. Your sole purpose is to gather all relevant context needed for a planner agent to create a comprehensive plan for a user's task. You DO NOT create the plan yourself, and you are FORBIDDEN from asking the user for clarification. If the task is a one-shot task that doesn't require any context, simply say that the task does not need additional context.
55+
56+
NEVER SAY THAT YOU HAVE INSUFFICIENT CONTEXT. YOUR JOB IS TO FIND THE CONTEXT, NOT TO SAY THAT YOU DON'T HAVE IT. IF YOU ARE UNABLE TO FIND THE CONTEXT, SIMPLY SAY THAT THE TASK DOES NOT NEED ADDITIONAL CONTEXT.
5557
5658
Original Context Provided for this Task:
5759
{original_context}
@@ -79,8 +81,8 @@
7981
- You are FORBIDDEN from asking clarifying questions.
8082
- You are FORBIDDEN from outputting any JSON format other than the one specified.
8183
- Do not include any text, explanations, or markdown formatting outside of your tool calls or the final JSON object.
82-
- YOU MUST PERFORM RECURSIVE TOOL CALLS. SEARCH ACROSS ALL THE SOURCES THAT HAVE BEEN PROVIDED TO YOU.
83-
- Always keep your internal thoughts in <think> </think> tags until you have finished searching across ALL sources. Then, compile your final report and return that in the JSON syntax.
84+
- YOU MUST PERFORM RECURSIVE TOOL CALLS. SEARCH ACROSS ALL THE SOURCES THAT HAVE BEEN PROVIDED TO YOU.
85+
- Always keep your internal thoughts in <think> </think> tags until you have finished searching across ALL sources. Then, compile your final report and return that in the JSON syntax.
8486
8587
For example: <think> I have finished searching gpeople and found 1 contact, now I will search gmail for information about that contact. </think> ... proceed with next too call.
8688
"""
@@ -91,7 +93,30 @@
9193
Your Task:
9294
Based on the input and a provided list of tools and their descriptions, you must return a list of tools that has a high probability of containing relevant information that would help your teammate complete the task.
9395
94-
YOUR ROLE IS TO FIND TOOLS FOR SEARCHING RELEVANT CONTEXT, NOT TOOLS TO EXECUTE THE TASK DIRECTLY. THESE TOOLS WILL BE USED BY YOUR TEAMMATE TO FIND THE RELEVANT CONTEXT OR INFORMATION NEEDED TO COMPLETE THE TASK.
96+
YOUR ROLE IS TO SELECT ALL THE RELEVANT TOOLS FOR THE TASK. THESE TOOLS WILL BE USED BY YOUR TEAMMATE TO FIND THE RELEVANT CONTEXT OR INFORMATION NEEDED TO COMPLETE THE TASK.
97+
98+
Here is the complete list of available tools you can select from:
99+
{
100+
"file_management": "Use this for reading, writing and listing files from your internal storage.",
101+
"accuweather": "Use this tool to get weather information for a specific location.",
102+
"discord": "Use this when the user wants to do something related to the messaging platform, Discord.",
103+
"gcalendar": "Use this tool to manage events in Google Calendar.",
104+
"gdocs": "Use this tool for creating and editing documents in Google Docs.",
105+
"gdrive": "Use this tool to search and read files in Google Drive.",
106+
"github": "Use this tool to perform actions related to GitHub repositories.",
107+
"gmail": "Use this tool to send and manage emails in Gmail.",
108+
"gmaps": "Use this tool for navigation, location search, and directions.",
109+
"gpeople": "Use this tool for storing and organizing personal and professional contacts.",
110+
"gsheets": "Use this tool to create and edit spreadsheets in Google Sheets.",
111+
"gslides": "Use this tool for creating and sharing slide decks.",
112+
"internet_search": "Use this tool to search for information on the internet.",
113+
"news": "Use this tool to get current news updates and articles.",
114+
"notion": "Use this tool for creating, editing and managing pages in Notion.",
115+
"quickchart": "Use this tool to generate charts and graphs quickly from data inputs.",
116+
"slack": "Use this tool to perform actions in the messaging platform Slack.",
117+
"trello": "Use this tool for managing boards in Trello.",
118+
"whatsapp": "Use this tool only for sending Whatsapp messages to the user."
119+
}
95120
96121
For example, if the input mentions that the user is writing a report about a project, you might select tools like "gmail" to find emails related to the project or "gdrive" for file storage and retrieval.
97122

src/server/workers/tasks.py

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,18 @@
1515
from json_extractor import JsonExtractor
1616
from workers.utils.api_client import notify_user, push_task_list_update
1717
from main.plans import PLAN_LIMITS
18-
from main.config import INTEGRATIONS_CONFIG # This is the new field
18+
from main.config import INTEGRATIONS_CONFIG
1919
from main.tasks.prompts import TASK_CREATION_PROMPT
2020
from mcp_hub.memory.utils import initialize_embedding_model, initialize_agents, cud_memory
2121
from mcp_hub.tasks.prompts import RESOURCE_MANAGER_SYSTEM_PROMPT
2222
from main.llm import run_agent as run_main_agent, LLMProviderDownError
2323
from main.db import MongoManager
2424
from workers.celery_app import celery_app
25-
from workers.planner.llm import get_planner_agent # noqa: E501
25+
from workers.planner.llm import get_planner_agent
2626
from workers.planner.prompts import CONTEXT_RESEARCHER_SYSTEM_PROMPT, TOOL_SELECTOR_SYSTEM_PROMPT
27-
from workers.planner.db import PlannerMongoManager, get_all_mcp_descriptions # noqa: E501
27+
from workers.planner.db import PlannerMongoManager, get_all_mcp_descriptions
2828
from workers.executor.tasks import execute_task_plan, run_single_item_worker, aggregate_results_callback
2929
from main.vector_db import get_conversation_summaries_collection
30-
from main.chat.prompts import STAGE_1_SYSTEM_PROMPT
3130
from mcp_hub.tasks.prompts import ITEM_EXTRACTOR_SYSTEM_PROMPT
3231
from workers.utils.text_utils import clean_llm_output
3332

@@ -76,15 +75,14 @@ async def _select_relevant_tools(query: str, available_tools_map: Dict[str, str]
7675
"""
7776
if not available_tools_map:
7877
return []
79-
8078
try:
81-
prompt = f"The user is trying to perform the following task: \"{query}\""
79+
prompt = f"User Query: \"{query}\""
8280

83-
messages = [{'role':'system', 'content': TOOL_SELECTOR_SYSTEM_PROMPT}, {'role': 'user', 'content': prompt}]
81+
messages = [{'role': 'user', 'content': prompt}]
8482

8583
def _run_selector_sync():
8684
final_content_str = ""
87-
for chunk in run_main_agent(system_message=STAGE_1_SYSTEM_PROMPT, function_list=[], messages=messages):
85+
for chunk in run_main_agent(system_message=TOOL_SELECTOR_SYSTEM_PROMPT, function_list=[], messages=messages):
8886
if isinstance(chunk, list) and chunk:
8987
last_message = chunk[-1]
9088
if last_message.get("role") == "assistant" and isinstance(last_message.get("content"), str):
@@ -93,19 +91,17 @@ def _run_selector_sync():
9391

9492
final_content_str = await asyncio.to_thread(_run_selector_sync)
9593
cleaned_output = clean_llm_output(final_content_str)
96-
parsed_output = JsonExtractor.extract_valid_json(cleaned_output)
97-
selected_tools = []
98-
if isinstance(parsed_output, dict) and "topic_changed" in parsed_output and "tools" in parsed_output:
99-
selected_tools = parsed_output.get("tools", [])
94+
selected_tools = JsonExtractor.extract_valid_json(cleaned_output)
10095

101-
# Separate into connected and disconnected
102-
connected_tools_selected = [tool for tool in selected_tools if tool in available_tools_map]
103-
104-
selected_tools = connected_tools_selected
105-
106-
return selected_tools
96+
if isinstance(selected_tools, list):
97+
# Filter the LLM's selection to ensure they are valid and available tools
98+
valid_selected_tools = [tool for tool in selected_tools if tool in available_tools_map]
99+
logger.info(f"Unified Search Tool Selector identified relevant tools: {valid_selected_tools}")
100+
return valid_selected_tools
101+
return []
107102
except Exception as e:
108103
logger.error(f"Error during tool selection for context search: {e}", exc_info=True)
104+
# Fallback to all connected tools on error
109105
return list(available_tools_map.keys())
110106

111107
# Helper to run async code in Celery's sync context
@@ -371,7 +367,7 @@ async def async_refine_and_plan_ai_task(task_id: str, user_id: str):
371367
user_timezone = ZoneInfo("UTC")
372368
current_time_str = datetime.datetime.now(user_timezone).strftime('%Y-%m-%d %H:%M:%S %Z')
373369

374-
system_prompt = TASK_CREATION_PROMPT.format( # noqa
370+
system_prompt = TASK_CREATION_PROMPT.format(
375371
user_name=user_name,
376372
user_timezone=user_timezone_str,
377373
current_time=current_time_str
@@ -443,7 +439,7 @@ async def async_process_change_request(task_id: str, user_id: str, user_message:
443439
db_manager = PlannerMongoManager()
444440
try:
445441
# 1. Fetch the task and its full history
446-
task = await db_manager.get_task(task_id) # This is the new field
442+
task = await db_manager.get_task(task_id)
447443
if not task:
448444
logger.error(f"Task Change Request: Task {task_id} not found.")
449445
return
@@ -458,7 +454,7 @@ async def async_process_change_request(task_id: str, user_id: str, user_message:
458454

459455
# 3. Update task status and chat history in DB
460456
await db_manager.update_task_field(task_id, {
461-
"chat_history": chat_history, # This is the new field
457+
"chat_history": chat_history,
462458
"status": "planning" # Revert to planning to re-evaluate
463459
})
464460

@@ -744,7 +740,7 @@ async def async_refine_task_details(task_id: str):
744740
user_timezone = ZoneInfo(user_timezone_str)
745741
current_time_str = datetime.datetime.now(user_timezone).strftime('%Y-%m-%d %H:%M:%S %Z')
746742

747-
system_prompt = TASK_CREATION_PROMPT.format( # noqa
743+
system_prompt = TASK_CREATION_PROMPT.format(
748744
user_name=user_name,
749745
user_timezone=user_timezone_str,
750746
current_time=current_time_str
@@ -777,7 +773,7 @@ def execute_triggered_task(user_id: str, source: str, event_type: str, event_dat
777773
logger.info(f"Checking for triggered tasks for user '{user_id}' from source '{source}' event '{event_type}'.")
778774
run_async(async_execute_triggered_task(user_id, source, event_type, event_data))
779775

780-
def _event_matches_filter(event_data: Dict[str, Any], task_filter: Dict[str, Any], source: str) -> bool: # noqa
776+
def _event_matches_filter(event_data: Dict[str, Any], task_filter: Dict[str, Any], source: str) -> bool:
781777
"""
782778
Checks if an event's data matches the conditions defined in a task's filter.
783779
Supports complex, MongoDB-like query syntax including $or, $and, $not,

0 commit comments

Comments
 (0)