With regard to your inter-bot communication, I am curious to know why you chose that solution.
Do you run all clients on the same machine? Why not just make a single bot that controls all clients simultaneously. Effectively, the solution that I chose. I may eventually convert my "bot" to use RPC so that a bot client can reside on multiple PCs with multiple game clients and a bot server controls them all, but it is very low priority on my list of "things to accomplish" simply I use my bot for explicitly mulit-boxing. I have a "main" that I control explicitly, and then a swarm of helpers to make sure the tank stays alive, the DPS is in full rotation, etc.
With regard to architecture, I have the concept of a "party", an explicit AI, which has its own goals, evaluators, and behaviours. It is the "party" that decides which character gets healed, and which character does the healing. It is the "party" that determines whether to explore, fight or recuperate. This party AI runs on its own thread. The party AI understands about the concept of a leader, a healer, a tank, DPS, etc.
Then I have the concept of a "player", an explicit AI for each player character (a local player) that also has goals, evaluators and behaviours. Player AI can send messages back up to the party AI, which can then forward the message on to the other player AI if it is necessary. Messages are sent via the standard producer/consumer event system built-in to .NET.
Because there is a concept of an "all-powerful party character" all of the player characters can be orchestrated to perform a group of actions very easily. This is useful when performing a round-robin type of action such as for debuffing, shielding, stunning, spell interrupting, etc.
Also, when looting, I keep it on FFA when playing alone or with my room-mate and her hunter, and it is funny to watch my characters rush off and gather up the loot from various kills and then run over to my room-mate's hunter and /yell "Treasure!" and "For you!" at her.
(Reference to the game Overlord)