I feel like these are some good points, and are definitely worth addressing.
Spam seems to be pretty widely regarded as irrelevant, unsolicited messages sent to large numbers of people. If a whisper is sent in response to a command, I feel it’s almost by definition guaranteed to be relevant, solicited, and sent to relatively few people. If the whisper clearly communicates why it was sent the only way to view it as spam would be to not read it, and if we’re allowed to categorize things as spam without reading them, then I feel like all bets are off. Now, is it possible that whispering users with bots could be spam? Of course, but you could just as easily post a message of random text to the public twitch chat every second and that would still clearly also be spam. I feel like whether or not a message counts as spam has less to do with the medium of that message and more to do with the value brought by the contents of that message.
As for your other point, I think I agree that splitting the request and response of a command across mediums is a little counterintuitive. The question becomes, “Are the benefits worth the cost.” I think they can be. I think a large part of that as I’ve said relies on explaining that the bot will sometimes send whispers in response to commands, so that people can get on board with that idea quickly. Another part of that I think just comes from having non-negligible benefits. The primary one of course is just removing unwanted and unnecessary messages from the channel’s twitch chat. I feel like maintaining a good signal to noise ratio in that chat is one thing that’s helped keep users paying attention to it. If it becomes mostly bot spam, it becomes harder to parse, with less return for doing so, and so fewer people are likely to read the messages that show up there. Another big point (and really the reason for posting this question) is that for some functionality, privacy is a fundamental feature of the message. On some nights the caster that I built the bot for plays quiplash, and having a bot with a !join command allows us to set up a priority queue where we can cycle in viewers in a fair and transparent way. This only works because the bot can whisper players automatically. They can get confirmation of joining the queue, the can ask the bot about their spot in the queue, they can leave the queue, and when it comes time to play with the caster, they can get the credentials they need to join automatically without the caster having to do anything. If the caster had to do that whispering himself it becomes difficult to maintain an entertaining vibe to the stream. If the bot puts the credentials in chat then obviously everyone can join and it doesn’t work. If every time someone joined, left and asked for their spot we put those responses in chat, it would quickly pollute chat with information that very few people care about, again making it difficult to parse, and taking the chat farther away from what we want it to be; a place for humans to interact with other humans.