From 1eef3d04065ae4d7c9a59d46a39645a4e9ddda1c Mon Sep 17 00:00:00 2001 From: Kujtim Hoxha Date: Tue, 28 Oct 2025 14:40:19 +0100 Subject: [PATCH] fix: run tools in order (#48) * fix: run tools in order * fix(lint): remove not needed append --- agent.go | 194 ++++++++++++++++++++++++------------------------------- 1 file changed, 83 insertions(+), 111 deletions(-) diff --git a/agent.go b/agent.go index 19d64cd8c6a3a558e3788916f279bf27037bdcf1..214cb388918fa15115716ccf58d96fffce36cf41 100644 --- a/agent.go +++ b/agent.go @@ -8,7 +8,6 @@ import ( "fmt" "maps" "slices" - "sync" ) // StepResult represents the result of a single step in an agent execution. @@ -619,127 +618,100 @@ func (a *agent) executeTools(ctx context.Context, allTools []AgentTool, toolCall toolMap[tool.Info().Name] = tool } - // Execute all tool calls in parallel - results := make([]ToolResultContent, len(toolCalls)) - executeErrors := make([]error, len(toolCalls)) - - var wg sync.WaitGroup - - for i, toolCall := range toolCalls { - wg.Add(1) - go func(index int, call ToolCallContent) { - defer wg.Done() - - // Skip invalid tool calls - create error result - if call.Invalid { - results[index] = ToolResultContent{ - ToolCallID: call.ToolCallID, - ToolName: call.ToolName, - Result: ToolResultOutputContentError{ - Error: call.ValidationError, - }, - ProviderExecuted: false, - } - if toolResultCallback != nil { - err := toolResultCallback(results[index]) - if err != nil { - executeErrors[index] = err - } - } - - return + // Execute all tool calls sequentially in order + results := make([]ToolResultContent, 0, len(toolCalls)) + + for _, toolCall := range toolCalls { + // Skip invalid tool calls - create error result + if toolCall.Invalid { + result := ToolResultContent{ + ToolCallID: toolCall.ToolCallID, + ToolName: toolCall.ToolName, + Result: ToolResultOutputContentError{ + Error: toolCall.ValidationError, + }, + ProviderExecuted: false, } - - tool, exists := toolMap[call.ToolName] - if !exists { - results[index] = ToolResultContent{ - ToolCallID: call.ToolCallID, - ToolName: call.ToolName, - Result: ToolResultOutputContentError{ - Error: errors.New("Error: Tool not found: " + call.ToolName), - }, - ProviderExecuted: false, + results = append(results, result) + if toolResultCallback != nil { + if err := toolResultCallback(result); err != nil { + return nil, err } - - if toolResultCallback != nil { - err := toolResultCallback(results[index]) - if err != nil { - executeErrors[index] = err - } - } - return } + continue + } - // Execute the tool - result, err := tool.Run(ctx, ToolCall{ - ID: call.ToolCallID, - Name: call.ToolName, - Input: call.Input, - }) - if err != nil { - results[index] = ToolResultContent{ - ToolCallID: call.ToolCallID, - ToolName: call.ToolName, - Result: ToolResultOutputContentError{ - Error: err, - }, - ClientMetadata: result.Metadata, - ProviderExecuted: false, - } - if toolResultCallback != nil { - cbErr := toolResultCallback(results[index]) - if cbErr != nil { - executeErrors[index] = cbErr - } - } - executeErrors[index] = err - return + tool, exists := toolMap[toolCall.ToolName] + if !exists { + result := ToolResultContent{ + ToolCallID: toolCall.ToolCallID, + ToolName: toolCall.ToolName, + Result: ToolResultOutputContentError{ + Error: errors.New("Error: Tool not found: " + toolCall.ToolName), + }, + ProviderExecuted: false, } - - if result.IsError { - results[index] = ToolResultContent{ - ToolCallID: call.ToolCallID, - ToolName: call.ToolName, - Result: ToolResultOutputContentError{ - Error: errors.New(result.Content), - }, - ClientMetadata: result.Metadata, - ProviderExecuted: false, - } - - if toolResultCallback != nil { - err := toolResultCallback(results[index]) - if err != nil { - executeErrors[index] = err - } - } - } else { - results[index] = ToolResultContent{ - ToolCallID: call.ToolCallID, - ToolName: toolCall.ToolName, - Result: ToolResultOutputContentText{ - Text: result.Content, - }, - ClientMetadata: result.Metadata, - ProviderExecuted: false, - } - if toolResultCallback != nil { - err := toolResultCallback(results[index]) - if err != nil { - executeErrors[index] = err - } + results = append(results, result) + if toolResultCallback != nil { + if err := toolResultCallback(result); err != nil { + return nil, err } } - }(i, toolCall) - } - - // Wait for all tool executions to complete - wg.Wait() + continue + } - for _, err := range executeErrors { + // Execute the tool + toolResult, err := tool.Run(ctx, ToolCall{ + ID: toolCall.ToolCallID, + Name: toolCall.ToolName, + Input: toolCall.Input, + }) if err != nil { + result := ToolResultContent{ + ToolCallID: toolCall.ToolCallID, + ToolName: toolCall.ToolName, + Result: ToolResultOutputContentError{ + Error: err, + }, + ClientMetadata: toolResult.Metadata, + ProviderExecuted: false, + } + if toolResultCallback != nil { + if cbErr := toolResultCallback(result); cbErr != nil { + return nil, cbErr + } + } return nil, err } + + var result ToolResultContent + if toolResult.IsError { + result = ToolResultContent{ + ToolCallID: toolCall.ToolCallID, + ToolName: toolCall.ToolName, + Result: ToolResultOutputContentError{ + Error: errors.New(toolResult.Content), + }, + ClientMetadata: toolResult.Metadata, + ProviderExecuted: false, + } + } else { + result = ToolResultContent{ + ToolCallID: toolCall.ToolCallID, + ToolName: toolCall.ToolName, + Result: ToolResultOutputContentText{ + Text: toolResult.Content, + }, + ClientMetadata: toolResult.Metadata, + ProviderExecuted: false, + } + } + results = append(results, result) + if toolResultCallback != nil { + if err := toolResultCallback(result); err != nil { + return nil, err + } + } } return results, nil