diff options
| author | CaptainJack2491 <jayrupnakawala@gmail.com> | 2026-03-25 18:24:11 +0000 |
|---|---|---|
| committer | CaptainJack2491 <jayrupnakawala@gmail.com> | 2026-03-25 18:24:11 +0000 |
| commit | a532e7b1696ef7539a4616b9c26fbf950f3721a3 (patch) | |
| tree | 5b547cdc7efc003ae3c84ecb5429c519eec109a3 | |
| parent | 36f6dc6dea2046ac7d4b942a44c26a85b9c466ee (diff) | |
fix: catch and recover from JSONDecodeError on malformed tool args
| -rw-r--r-- | src/agent.py | 28 | ||||
| -rw-r--r-- | tests/test_agent.py | 8 |
2 files changed, 20 insertions, 16 deletions
diff --git a/src/agent.py b/src/agent.py index 4047b08..a8edb20 100644 --- a/src/agent.py +++ b/src/agent.py @@ -248,20 +248,24 @@ class Agent: logger.info(f"LLM requested {len(response_message.tool_calls)} tool execution(s)") for tool_call in response_message.tool_calls: function_name = tool_call.function.name - function_args = json.loads(tool_call.function.arguments) - - function_to_call = self.available_functions.get(function_name) - if not function_to_call: - error_msg = f"Unknown tool: {function_name}" + try: + function_args = json.loads(tool_call.function.arguments) + logger.info(f"Executing: {function_name}({function_args})") + + function_to_call = self.available_functions.get(function_name) + if not function_to_call: + error_msg = f"Unknown tool: {function_name}" + logger.warning(error_msg) + function_output = error_msg + else: + try: + function_output = function_to_call(**function_args) + except Exception as e: + function_output = f"Error executing {function_name}: {str(e)}" + except json.JSONDecodeError as e: + error_msg = f"Error parsing tool arguments for {function_name}: {str(e)}. Arguments must be valid JSON." logger.warning(error_msg) function_output = error_msg - else: - try: - function_output = function_to_call(**function_args) - except Exception as e: - function_output = f"Error executing {function_name}: {str(e)}" - - logger.info(f"Executing: {function_name}({function_args})") tool_message = { "tool_call_id": tool_call.id, diff --git a/tests/test_agent.py b/tests/test_agent.py index c8164e6..e73b41e 100644 --- a/tests/test_agent.py +++ b/tests/test_agent.py @@ -173,10 +173,10 @@ class TestAgentRun: ) agent.client.chat.completions.create.side_effect = [tool_response, final_response] - # json.loads will raise — this should be caught or propagate clearly - # Current code does NOT catch this, so it should raise JSONDecodeError - with pytest.raises(json.JSONDecodeError): - agent.run("Do something") + # json.loads will fail, the agent will catch it, return an error to model, + # and on the next turn the model will return "Recovered". + result = agent.run("Do something") + assert result == "Recovered" def test_api_error_propagates(self, agent): """API errors should propagate, not be silently swallowed.""" |
