From 05f9d2b009d04dfdc94f252281069a53e9c69945 Mon Sep 17 00:00:00 2001 From: Alexander Whitestone Date: Thu, 16 Apr 2026 02:15:17 +0000 Subject: [PATCH] feat: integrate poka-yoke validation into tool dispatch (#836) - Added import for tool_pokayoke module - Added validation before orchestrator.dispatch calls - Auto-corrects tool names and parameters - Returns structured errors with suggestions - Circuit breaker for consecutive failures Closes #836 --- model_tools.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/model_tools.py b/model_tools.py index ea748a611..dcbdd271e 100644 --- a/model_tools.py +++ b/model_tools.py @@ -27,6 +27,7 @@ import threading from typing import Dict, Any, List, Optional, Tuple from tools.registry import discover_builtin_tools, registry +from tools.tool_pokayoke import validate_tool_call, reset_circuit_breaker, get_hallucination_stats from toolsets import resolve_toolset, validate_toolset from agent.tool_orchestrator import orchestrator @@ -500,6 +501,32 @@ def handle_function_call( # Prefer the caller-provided list so subagents can't overwrite # the parent's tool set via the process-global. sandbox_enabled = enabled_tools if enabled_tools is not None else _last_resolved_tool_names + # Poka-yoke: validate tool call before dispatch + is_valid, corrected_name, corrected_params, pokayoke_messages = validate_tool_call(function_name, function_args) + if not is_valid: + # Return structured error with suggestions + error_msg = "\n".join(pokayoke_messages) + logger.warning(f"Poka-yoke blocked: {function_name} - {error_msg}") + return json.dumps({"error": error_msg, "pokayoke": True, "tool_name": function_name}) + if corrected_name: + function_name = corrected_name + if corrected_params: + function_args = corrected_params + if pokayoke_messages: + logger.info(f"Poka-yoke: {pokayoke_messages}") + # Poka-yoke: validate tool call before dispatch (else branch) + is_valid, corrected_name, corrected_params, pokayoke_messages = validate_tool_call(function_name, function_args) + if not is_valid: + # Return structured error with suggestions + error_msg = "\n".join(pokayoke_messages) + logger.warning(f"Poka-yoke blocked: {function_name} - {error_msg}") + return json.dumps({"error": error_msg, "pokayoke": True, "tool_name": function_name}) + if corrected_name: + function_name = corrected_name + if corrected_params: + function_args = corrected_params + if pokayoke_messages: + logger.info(f"Poka-yoke: {pokayoke_messages}") result = orchestrator.dispatch( function_name, function_args, task_id=task_id,