4. 多智能体通信:Agent间消息传递机制、共享黑板(Blackboard)模式与发布-订阅模式

多智能体系统,说白了就是一群AI Agent在一起干活。但问题来了——它们怎么交流?

我刚开始做多Agent系统时,天真地以为让每个Agent直接调用对方的API就行。结果呢?耦合度爆炸,改一个Agent,其他三个都得跟着改。后来我学乖了,开始认真研究Agent间的通信模式。

今天咱们就聊聊三种最核心的通信方式:直接消息传递黑板模式发布-订阅模式。这三种模式,我在实战中都用过,各有各的适用场景。

4.1 直接消息传递:最朴素的通信方式

直接消息传递,就是Agent A直接给Agent B发消息。像两个人面对面聊天。

这种方式实现简单,但问题也很明显——耦合太强。Agent A必须知道Agent B的存在,还得知道它的地址和接口。

核心特点:
  • 点对点通信,延迟低
  • 实现简单,适合少量Agent
  • 耦合度高,扩展性差

我在一个早期的交易系统中用过这种方式。当时只有两个Agent:一个负责行情分析,一个负责下单。直接通信没问题。但后来加了风控Agent、日志Agent、策略优化Agent……代码直接变成一团乱麻。

避坑指南:我曾经在一个项目里用直接消息传递连接了8个Agent,结果每次新增Agent都要修改现有代码。后来花了整整两天重构,才换成黑板模式。所以,Agent数量超过3个,就别用直接通信了。

4.2 共享黑板模式:中央集权式通信

黑板模式,说白了就是所有Agent都往一个公共区域写东西、读东西。这个公共区域就是「黑板」。

想象一下:一个教室里,老师在黑板上写题目,学生们各自解题,然后把答案写在黑板上。老师不用一个个去问,学生也不用互相传纸条。

在交易系统里,黑板就是一个共享的数据结构。每个Agent都可以往里面写数据,也可以读取其他Agent写的数据。

class Blackboard:
    def __init__(self):
        self._data = {}
        self._lock = threading.Lock()
    
    def write(self, key, value, agent_id):
        with self._lock:
            self._data[key] = {
                'value': value,
                'writer': agent_id,
                'timestamp': time.time()
            }
    
    def read(self, key):
        with self._lock:
            return self._data.get(key)
    
    def subscribe(self, key, callback):
        # 注册回调,当key更新时通知
        pass

这个模式的好处很明显:

  • 解耦:Agent之间不需要知道彼此的存在
  • 灵活:随时可以加新Agent,只要它知道黑板地址
  • 可追溯:所有数据都有写入者和时间戳

但缺点也有:黑板容易成为性能瓶颈。所有Agent都往一个地方读写,并发量大了就卡。

我的经验:在实盘交易中,黑板模式特别适合做「状态共享」。比如,行情Agent把最新价格写到黑板,策略Agent读取后生成信号,风控Agent再读取信号做校验。每个Agent各司其职,互不干扰。

4.3 发布-订阅模式:去中心化的消息总线

发布-订阅模式,就是Agent把消息发到一个「主题」上,其他Agent订阅这个主题就能收到消息。发布者和订阅者完全解耦。

你想想看,这就像微信公众号。我写文章发出去,谁订阅了谁就能看到。我不知道谁在看,读者也不知道我什么时候写。但消息就是能准确送达。

在交易系统里,我常用Redis的Pub/Sub或者RabbitMQ来实现这个模式。

import redis

class PubSubAgent:
    def __init__(self, agent_id, redis_host='localhost'):
        self.agent_id = agent_id
        self.redis = redis.StrictRedis(host=redis_host)
        self.pubsub = self.redis.pubsub()
    
    def publish(self, channel, message):
        """发布消息到指定频道"""
        self.redis.publish(channel, json.dumps({
            'agent_id': self.agent_id,
            'message': message,
            'timestamp': time.time()
        }))
    
    def subscribe(self, channel, callback):
        """订阅频道,注册回调"""
        self.pubsub.subscribe(**{channel: callback})
        self.pubsub.run_in_thread(sleep_time=0.001)

发布-订阅模式的好处:

  • 完全解耦:发布者和订阅者互不知道对方
  • 可扩展:加Agent只需要订阅新主题
  • 异步:发布者不用等订阅者处理完

但要注意,消息可能会丢失。如果订阅者挂了,消息就没了。所以关键消息需要做持久化。

我曾经踩过的坑:有一次,我把订单确认消息用Pub/Sub发送,结果网络抖动导致消息丢失,订单状态不一致。后来我改用「确认机制」——订阅者收到消息后必须回复ACK,否则发布者重发。

4.4 三种模式对比

特性 直接消息传递 黑板模式 发布-订阅模式
耦合度
扩展性 极好
延迟
可靠性 中(需ACK)
适用场景 少量Agent 状态共享 事件通知

4.5 实战中的选择策略

我个人习惯这样选:

  • Agent少于3个:直接消息传递,简单粗暴
  • 需要共享状态:黑板模式,比如行情数据、账户余额
  • 事件通知:发布-订阅模式,比如订单成交、风控告警
  • 混合使用:实际项目中,我经常黑板+Pub/Sub一起用

举个例子,我最近做的多Agent交易系统:

  • 行情Agent把K线数据写到黑板
  • 策略Agent从黑板读K线,生成交易信号
  • 信号通过Pub/Sub发给执行Agent
  • 执行Agent下单后,把结果写回黑板
  • 风控Agent订阅「风控告警」主题,同时从黑板读账户状态

这样,每个Agent只关心自己该做的事,互不干扰。改一个Agent,其他Agent完全不受影响。

核心原则:通信模式的选择,取决于你的系统规模和需求。没有银弹,只有最适合的。

4.6 知识体系总览

下面这张图,把三种通信模式的核心逻辑画出来了。你看一眼就能明白它们之间的区别。

多智能体通信模式总览 直接消息传递 Agent A Agent B 消息 回复 点对点,高耦合 共享黑板模式 黑板 共享数据 Agent 1 Agent 2 Agent 3 读写共享,解耦 发布-订阅模式 消息总线 主题通道 发布者 订阅者 异步,完全解耦 实战选择建议 🔹 直接消息:Agent ≤ 3,追求低延迟 🔹 黑板模式:需要共享状态,如行情、账户 🔹 发布-订阅:事件通知,如成交、告警 🔹 混合使用:黑板 + Pub/Sub 是最常见的实战组合 注:实际项目中,80%的场景用黑板+Pub/Sub就能解决

嗯,这张图基本把三种模式的核心区别讲清楚了。你仔细看看,尤其是箭头方向——直接通信是双向的,黑板是多个Agent指向中心,Pub/Sub则是通过总线中转。

一个小技巧:如果你不确定选哪种模式,先画个图。把Agent画成圆圈,把通信画成箭头。如果箭头交叉太多,就该考虑黑板或Pub/Sub了。

好了,关于多智能体通信,今天就聊到这儿。这三种模式,你可以在自己的系统里试试。先从简单的开始,慢慢你就会发现,通信模式选对了,整个系统的复杂度能降低一大半。


公众号:蓝海资料掘金营,微信deep3321