TradingAgents/backend/TOOL_CALL_FIX_SUMMARY.md

155 lines
5.3 KiB
Markdown

# 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
```python
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
```
2. **Skipped Tool Calls**: Create skip ToolMessage
```python
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
```
3. **Unknown Tool Call Format**: Create error ToolMessage
```python
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
```
4. **Empty Tool Name**: Create error ToolMessage
```python
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
```
5. **Improved Tool Call ID Handling**: Ensure unique IDs
```python
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
```bash
python test_simple_fix.py
```
**Result**: ✅ PASS - No tool call errors detected in first 15 chunks
### Test 2: Extended Analysis Test
```bash
python test_extended_fix.py
```
**Result**: ✅ PASS - No tool call errors detected during 90-second execution
### Test 3: API Health Check
```bash
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:
```bash
cd backend
uvicorn api:app --host 0.0.0.0 --port 8000
```
2. Run the verification test:
```bash
python test_simple_fix.py
```
3. Test with real endpoint:
```bash
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.