Enhance skills tool to have an arg so it is more reliably called, and error handling in agent
- Updated the `skills_categories` function to include a `verbose` parameter, allowing users to request skill counts per category. - Modified the `handle_skills_function_call` method to pass the `verbose` argument to `skills_categories`. - Improved error handling in the `AIAgent` class by injecting a recovery message when invalid JSON arguments are detected, guiding users on how to correct their tool calls. - Enhanced the `GatewayRunner` to return a user-friendly error message if the agent fails to generate a final response, improving overall user experience.
This commit is contained in:
parent
221fb17c5e
commit
212460289b
4 changed files with 35 additions and 15 deletions
|
|
@ -451,7 +451,16 @@ class GatewayRunner:
|
||||||
# TODO: Implement proper history restoration
|
# TODO: Implement proper history restoration
|
||||||
|
|
||||||
result = agent.run_conversation(message)
|
result = agent.run_conversation(message)
|
||||||
return result.get("final_response", "(No response)")
|
|
||||||
|
# Return final response, or a message if something went wrong
|
||||||
|
final_response = result.get("final_response")
|
||||||
|
if final_response:
|
||||||
|
return final_response
|
||||||
|
elif result.get("error"):
|
||||||
|
# Agent couldn't recover - show the error
|
||||||
|
return f"⚠️ {result['error']}"
|
||||||
|
else:
|
||||||
|
return "(No response generated)"
|
||||||
|
|
||||||
# Start progress message sender if enabled
|
# Start progress message sender if enabled
|
||||||
progress_task = None
|
progress_task = None
|
||||||
|
|
|
||||||
|
|
@ -406,10 +406,15 @@ def get_skills_tool_definitions() -> List[Dict[str, Any]]:
|
||||||
"type": "function",
|
"type": "function",
|
||||||
"function": {
|
"function": {
|
||||||
"name": "skills_categories",
|
"name": "skills_categories",
|
||||||
"description": "List available skill categories. Call first if you want to discover categories, then use skills_list(category) to filter, or call skills_list if unsure.",
|
"description": "List available skill categories. Call this first to discover what skill categories exist, then use skills_list(category) to see skills in a category.",
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {},
|
"properties": {
|
||||||
|
"verbose": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "If true, include skill counts per category. Default: false."
|
||||||
|
}
|
||||||
|
},
|
||||||
"required": []
|
"required": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -907,7 +912,8 @@ def handle_skills_function_call(function_name: str, function_args: Dict[str, Any
|
||||||
str: Function result as JSON string
|
str: Function result as JSON string
|
||||||
"""
|
"""
|
||||||
if function_name == "skills_categories":
|
if function_name == "skills_categories":
|
||||||
return skills_categories()
|
verbose = function_args.get("verbose", False)
|
||||||
|
return skills_categories(verbose=verbose)
|
||||||
|
|
||||||
elif function_name == "skills_list":
|
elif function_name == "skills_list":
|
||||||
category = function_args.get("category")
|
category = function_args.get("category")
|
||||||
|
|
|
||||||
24
run_agent.py
24
run_agent.py
|
|
@ -1725,16 +1725,20 @@ class AIAgent:
|
||||||
# Don't add anything to messages, just retry the API call
|
# Don't add anything to messages, just retry the API call
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
print(f"{self.log_prefix}❌ Max retries (3) for invalid JSON arguments exceeded. Stopping as partial.")
|
# Instead of returning partial, inject a helpful message and let model recover
|
||||||
self._invalid_json_retries = 0 # Reset for next conversation
|
print(f"{self.log_prefix}⚠️ Injecting recovery message for invalid JSON...")
|
||||||
return {
|
self._invalid_json_retries = 0 # Reset for next attempt
|
||||||
"final_response": None,
|
|
||||||
"messages": messages, # Messages up to last valid point
|
# Add a user message explaining the issue
|
||||||
"api_calls": api_call_count,
|
recovery_msg = (
|
||||||
"completed": False,
|
f"Your tool call to '{tool_name}' had invalid JSON arguments. "
|
||||||
"partial": True,
|
f"Error: {error_msg}. "
|
||||||
"error": f"Model generated invalid JSON arguments for tool '{tool_name}': {error_msg}"
|
f"For tools with no required parameters, use an empty object: {{}}. "
|
||||||
}
|
f"Please either retry the tool call with valid JSON, or respond without using that tool."
|
||||||
|
)
|
||||||
|
messages.append({"role": "user", "content": recovery_msg})
|
||||||
|
# Continue the loop - model will see this message and can recover
|
||||||
|
continue
|
||||||
|
|
||||||
# Reset retry counter on successful JSON validation
|
# Reset retry counter on successful JSON validation
|
||||||
self._invalid_json_retries = 0
|
self._invalid_json_retries = 0
|
||||||
|
|
|
||||||
|
|
@ -349,7 +349,7 @@ def _load_category_description(category_dir: Path) -> Optional[str]:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def skills_categories(task_id: str = None) -> str:
|
def skills_categories(verbose: bool = False, task_id: str = None) -> str:
|
||||||
"""
|
"""
|
||||||
List available skill categories with descriptions (progressive disclosure tier 0).
|
List available skill categories with descriptions (progressive disclosure tier 0).
|
||||||
|
|
||||||
|
|
@ -358,6 +358,7 @@ def skills_categories(task_id: str = None) -> str:
|
||||||
or first paragraph to explain what skills are in that category.
|
or first paragraph to explain what skills are in that category.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
verbose: If True, include skill counts per category (default: False, but currently always included)
|
||||||
task_id: Optional task identifier (unused, for API consistency)
|
task_id: Optional task identifier (unused, for API consistency)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue