From 828f89abbe5d1f86d7f52f7080ed97fe1c99ede8 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 22 May 2026 15:49:30 +0000 Subject: [PATCH] Skip malformed-args validation when auto-heal is on The F3 pre-dispatch validator flagged any non-object tool-call ``arguments`` as malformed, even when the caller had set ``auto_heal_tool_calls=True``. The dispatcher downstream already heals bare-string arguments (for example a raw web_search query) into a valid ``{"query": ...}`` shape, so rejecting them up front made the validation loop fight the heal and effectively disabled the auto-heal feature for that family of models. Gate the malformed-args branch on ``auto_heal_tool_calls`` being off so dispatch keeps its existing healing semantics. The unknown-tool branch still fires in either mode because no amount of healing can invent a tool that is not registered. Existing tests in tests/test_validation_retry_loop.py already pin both paths (``test_malformed_args_bypassed_when_heal_on`` and ``test_malformed_args_caught_when_heal_off``); both pass with this change. --- studio/backend/core/inference/llama_cpp.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/studio/backend/core/inference/llama_cpp.py b/studio/backend/core/inference/llama_cpp.py index da25d91678..de7fe49180 100644 --- a/studio/backend/core/inference/llama_cpp.py +++ b/studio/backend/core/inference/llama_cpp.py @@ -5020,6 +5020,15 @@ class LlamaCppBackend: # tool-result tied to the hallucinated call id and # re-enter the model. Skips when the budget is spent so # the existing error path still runs. + # + # ``malformed_args`` (non-object arguments) only fires + # when auto-heal is OFF. With auto_heal_tool_calls=True + # the dispatch path downstream coerces bare-string + # arguments (e.g. a raw web_search query) into a valid + # `{"query": ...}` shape, and rejecting those calls + # here would defeat the heal. The unknown-tool branch + # still runs in either mode because no amount of + # healing can invent a tool that isn't registered. _validation_problem = None if ( tool_calls @@ -5032,6 +5041,10 @@ class LlamaCppBackend: if _vname not in _allowed_tool_names: _validation_problem = ("unknown_tool", _vtc, _vname) break + if auto_heal_tool_calls: + # Dispatch will heal non-object arguments; do + # not pre-empt it by rejecting them here. + continue _vraw = _vfn.get("arguments", "") if isinstance(_vraw, str): try: