@@ -263,3 +263,82 @@ async def test_multiple_flow_control_calls_all_filtered(self):
263263 ]
264264 assert len (tool_call_blocks ) == 1
265265 assert tool_call_blocks [0 ]["name" ] == "regular_tool"
266+
267+ @pytest .mark .asyncio
268+ async def test_end_execution_and_raise_error_keeps_only_raise_error (self ):
269+ """When only end_execution and raise_error are called, keep only raise_error."""
270+ mock_response = AIMessage (
271+ content_blocks = [
272+ create_tool_call (
273+ name = END_EXECUTION_TOOL .name ,
274+ args = {"result" : "done" },
275+ id = "call_1" ,
276+ ),
277+ create_tool_call (
278+ name = RAISE_ERROR_TOOL .name ,
279+ args = {"message" : "conflict" },
280+ id = "call_2" ,
281+ ),
282+ ],
283+ tool_calls = [
284+ {
285+ "name" : END_EXECUTION_TOOL .name ,
286+ "args" : {"result" : "done" },
287+ "id" : "call_1" ,
288+ },
289+ {
290+ "name" : RAISE_ERROR_TOOL .name ,
291+ "args" : {"message" : "conflict" },
292+ "id" : "call_2" ,
293+ },
294+ ],
295+ )
296+ self .mock_model .ainvoke = AsyncMock (return_value = mock_response )
297+
298+ llm_node = create_llm_node (self .mock_model , [self .regular_tool ])
299+
300+ result = await llm_node (self .test_state )
301+
302+ response_message = result ["messages" ][0 ]
303+ assert len (response_message .tool_calls ) == 1
304+ assert response_message .tool_calls [0 ]["name" ] == RAISE_ERROR_TOOL .name
305+
306+ @pytest .mark .asyncio
307+ async def test_multiple_raise_error_calls_keeps_only_first (self ):
308+ """When raise_error is called multiple times, keep only the first."""
309+ mock_response = AIMessage (
310+ content_blocks = [
311+ create_tool_call (
312+ name = RAISE_ERROR_TOOL .name ,
313+ args = {"message" : "first error" },
314+ id = "call_1" ,
315+ ),
316+ create_tool_call (
317+ name = RAISE_ERROR_TOOL .name ,
318+ args = {"message" : "second error" },
319+ id = "call_2" ,
320+ ),
321+ ],
322+ tool_calls = [
323+ {
324+ "name" : RAISE_ERROR_TOOL .name ,
325+ "args" : {"message" : "first error" },
326+ "id" : "call_1" ,
327+ },
328+ {
329+ "name" : RAISE_ERROR_TOOL .name ,
330+ "args" : {"message" : "second error" },
331+ "id" : "call_2" ,
332+ },
333+ ],
334+ )
335+ self .mock_model .ainvoke = AsyncMock (return_value = mock_response )
336+
337+ llm_node = create_llm_node (self .mock_model , [self .regular_tool ])
338+
339+ result = await llm_node (self .test_state )
340+
341+ response_message = result ["messages" ][0 ]
342+ assert len (response_message .tool_calls ) == 1
343+ assert response_message .tool_calls [0 ]["name" ] == RAISE_ERROR_TOOL .name
344+ assert response_message .tool_calls [0 ]["args" ]["message" ] == "first error"
0 commit comments