Witt, Massey and MJ Melendez had two hits each for the Royals (47-101), who have won three in a row.
Kansas City starter Zack Greinke pitched two scoreless innings before departing. The former American League Cy Young winner and six-time All Star allowed three hits, struck out one and walked one, but remains winless in his past 20 games (17 starts).
Angel Zerpa (2-3) allowed one run and two hits in four innings of relief to record the win. He fanned five and walked one.
Taylor Clarke yielded a run in the ninth but still earned his first save of the season.
Astros starter Cristian Javier (9-4) allowed three runs (two earned) and five hits in five innings. He struck out six and walked one.
Jose Abreu homered and singled and Jeremy Pena also had two hits for the Astros, who have lost three of four.
Houston (83-65) was unable to take advantage of a loss earlier in the day by the Texas Rangers (82-65) and remains a half-game ahead of the second-place Rangers in the AL West. The Seattle Mariners (81-65) were one game behind the Astros entering their late game against the Los Angeles Dodgers.
Melendez singled with one out in the third, took second on a passed ball and moved to third on an infield single up the middle by Witt. Salvador Perez then lined out to left, and Melendez scored on the sacrifice fly for a 1-0 lead.
Velazquez lifted a 1-2 pitch over the fence in center with one out in the fourth to extend the lead to 2-0. It was his 13th long ball of the year.
With two outs in the fifth, Witt lined a solo home run to left, his 29th of the season, making it 3-0.
Pena opened the sixth with an opposite-field single to right. Yordan Alvarez then slapped a double just inside the left field line, scoring Pena from first to make it 3-1, but Kansas City avoided further damage.
Massey got the run back in the eighth when he homered for the third consecutive game, his 14th of the year.
Abreu hit his 15th homer of the season to lead off the ninth and make it 4-2, but Clarke struck out the next three batters.
—Field Level Media