TradingAgents/backend/TOOL_CALL_FIX_SUMMARY.md

5.3 KiB

Tool Call Fix Summary

Problem Description

The TradingAgents system was experiencing a critical error during execution:

Error code: 400 - {'error': {'message': "An assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'. The following tool_call_ids did not have response messages: call_Ai2XeBuqwYn44GC5ogLZxzsG", 'type': 'invalid_request_error', 'param': 'messages', 'code': None}}

Root Cause Analysis

The error occurred in the Market Analyst when it made multiple tool calls, but one of them failed:

  1. Market Analyst made 8 tool calls including get_stockstats_indicators_report_online with macd_signal indicator
  2. Tool execution failed because macd_signal is not supported (only macds is available)
  3. No ToolMessage created for the failed tool call
  4. OpenAI API rejected the conversation because tool call call_Ai2XeBuqwYn44GC5ogLZxzsG had no response

From the logs:

ERROR:tradingagents.graph.setup:❌ market tools: Error executing get_stockstats_indicators_report_online: Indicator macd_signal is not supported. Please choose from: ['close_50_sma', 'close_200_sma', 'close_10_ema', 'macd', 'macds', 'macdh', 'rsi', 'boll', 'boll_ub', 'boll_lb', 'atr', 'vwma', 'mfi']

Solution Implemented

Modified backend/tradingagents/graph/setup.py in the _wrap_tool_node_for_channel method to ensure every tool call gets a ToolMessage response, even when errors occur.

Changes Made

  1. Failed Tool Execution: Create error ToolMessage
except Exception as e:
    logger.error(f"❌ {analyst_type} tools: Error executing {tool_name}: {str(e)}")
    # Create an error ToolMessage to maintain conversation flow
    error_message = ToolMessage(
        content=f"Error executing {tool_name}: {str(e)}",
        tool_call_id=tool_call_id
    )
    updated_messages.append(error_message)
    logger.info(f"🔧 {analyst_type} tools: ✅ Added error ToolMessage for {tool_name}")
    tools_executed += 1
  1. Skipped Tool Calls: Create skip ToolMessage
if not can_call:
    logger.warning(f"🔧 {analyst_type} tools: SKIPPING - {reason}")
    # Create a skip ToolMessage to maintain conversation flow
    skip_message = ToolMessage(
        content=f"Tool call skipped: {reason}",
        tool_call_id=tool_call_id
    )
    updated_messages.append(skip_message)
    logger.info(f"🔧 {analyst_type} tools: ✅ Added skip ToolMessage for {tool_name}")
    tools_executed += 1
    continue
  1. Unknown Tool Call Format: Create error ToolMessage
else:
    logger.error(f"❌ {analyst_type} tools: Unknown tool call format")
    # Create an error ToolMessage even for unknown format
    unknown_tool_call_id = f'unknown_format_{i}'
    error_message = ToolMessage(
        content=f"Error: Unknown tool call format at index {i}",
        tool_call_id=unknown_tool_call_id
    )
    updated_messages.append(error_message)
    logger.info(f"🔧 {analyst_type} tools: ✅ Added error ToolMessage for unknown format")
    tools_executed += 1
    continue
  1. Empty Tool Name: Create error ToolMessage
if not tool_name:
    logger.error(f"❌ {analyst_type} tools: Empty tool name")
    # Create an error ToolMessage for empty tool name
    error_message = ToolMessage(
        content=f"Error: Empty tool name at index {i}",
        tool_call_id=tool_call_id
    )
    updated_messages.append(error_message)
    logger.info(f"🔧 {analyst_type} tools: ✅ Added error ToolMessage for empty tool name")
    tools_executed += 1
    continue
  1. Improved Tool Call ID Handling: Ensure unique IDs
tool_call_id = tool_call.get('id', f'unknown_{i}')  # For dict format
tool_call_id = tool_call.id if hasattr(tool_call, 'id') else f'unknown_{i}'  # For object format

Testing Results

Test 1: Simple Fix Verification

python test_simple_fix.py

Result: PASS - No tool call errors detected in first 15 chunks

Test 2: Extended Analysis Test

python test_extended_fix.py

Result: PASS - No tool call errors detected during 90-second execution

Test 3: API Health Check

curl http://localhost:8000/health

Result: {"status":"healthy"}

Impact

  • Fixed: Critical OpenAI API error that was breaking the analysis flow
  • Improved: Error handling and logging for tool execution
  • Enhanced: Robustness of the conversation flow with OpenAI API
  • Maintained: All existing functionality while adding error resilience

Verification Commands

To verify the fix is working:

  1. Start the API server:
cd backend
uvicorn api:app --host 0.0.0.0 --port 8000
  1. Run the verification test:
python test_simple_fix.py
  1. Test with real endpoint:
curl -X GET "http://localhost:8000/analyze/stream?ticker=AAPL"

The system should now run without the tool call error and handle failed tool executions gracefully.

Files Modified

  • backend/tradingagents/graph/setup.py - Main fix implementation
  • backend/test_simple_fix.py - Simple verification test (created)
  • backend/test_extended_fix.py - Extended verification test (created)
  • backend/test_tool_call_fix.py - Comprehensive test script (created)

Status

🎉 RESOLVED - Tool call error fix successfully implemented and tested.