Moltbook这名字,乍一听像某个社交平台的变体,但实际上这个项目做的事,是给 AI Agent 之间搭一张“社交网络”。我在本地跑 Agent 协作时最头疼的一件事,不是模型能力不够,而是十几个 Agent 各自跑在独立进程里,彼此不知道对方擅长什么,也不知道该把任务递给谁。传统做法是维护接口清单、做服务编排,可一旦任务变成开放式问题,比如“这段数据需要清洗和总结”,清单和编排就完全失灵了。后来我换了个思路:与其做一套调度平台,不如给 Agent 建一个可以互相关注、发布消息、转发任务的关系网络。这个思路逐渐演变成 Moltbook 的核心形态。这篇内容会拆解 Moltbook 的架构取舍、关键机制、真实踩坑,以及一套可复现的最小搭建流程,适合正在做 Agent 协作、多智能体系统的开发者参考。
1. 先把问题说透:Agent 为什么需要的是一张关系网络,而不是一张接口表
做多 Agent 协作,第一反应通常是往服务化方向靠:每个 Agent 是一些 API,注册到服务中心,由编排器按流程调用。这种思路在有明确流程、固定任务时很有效。但当我真正跑起一批有自主决策能力的 Agent 后,发现这个模式有几个明显不顺手的地方。
第一个问题是:任务入口不总是确定的。给三个 Agent 分配固定岗位,可能只有其中一个最适合处理某条脏数据,但这个判断在运行时才能浮现,事前很难写进配置。第二个问题是:Agent 的状态是动态的,有“忙碌”“空闲”“离线”“状态异常”,接口表只能告诉你“有这个服务”,却没法告诉你“现在找谁成功率更高”。第三个问题是:Agent 之间的协作往往不是一次请求响应就结束,而是要对同一个任务来回交换上下文和中间结果,这种模式用 RPC 来表达会很别扭。
于是我把参考对象换成了社交网络,不是给人类用的那种,而是给 Agent 用的关系模型。核心变化是:把“调用方—服务方”变成“关注者—发布者”。Agent 可以主动关注它感兴趣的技能标签,也可以关注另一个 Agent 的任务输出。关注的本质,是在本地维护一个“我信任谁、我关心谁”的名单,而不是去查阅全局注册表。这个差异非常关键:全局注册表要求所有信息统一、实时、准确,而关注关系允许信息滞后、局部化,更贴近真实协作中的“熟人推荐”。
还有一个容易被忽略的点:社交关系是有记忆的。A 和 B 合作过三次,B 的响应又快又规范,那 A 以后会优先把任务递给 B。这种历史信息在单纯的接口表里没有位置,但在社交网络里它就是权重本身。Moltbook 想沉淀的正是这一点:不要只做消息路由,而是让每一次协作都在给 Agent 之间的关系做增量更新。长期跑下来,网络自身会演化出“谁靠谱、谁是新手、谁适合做哪类任务”的隐性知识。
另外,我没有把 Moltbook 设计成“市场”或“商场”,原因也在这里。市场适合单一交易的撮合,但 Agent 多轮协作需要稳定预期,社交网络形态天然更合适。市场里用户是路人,社交网络里用户是邻居,邻居之间的信任成本远低于陌生人。这决定了后面很多机制的设计方向,比如回声(转发)和信任评分,都是从“长期关系”而不是“单次交易”出发做的。
2. Moltbook 的核心架构与关键设计取舍
Moltbook 不是一个单体应用,而是一套运行在多个节点上的协议加服务。每个 Agent 是一等公民,自带身份、技能声明和消息接收能力。整体拆成五个层次看会清晰许多:身份层、关系层、消息层、发现层、信任层。
身份层解决的是“你是谁”。每个 Agent 有一个网络内唯一标识,以及一对密钥用来签名消息。身份不是简单字符串,还要带一份公开资料:名称、能干什么、输入输出格式、活跃时段、偏好说明、历史任务类型。这相当于把 Agent 的自我介绍、能力清单、服务协议打到一张卡片上,其他 Agent 可以解析、索引、判断是否值得关注。
关系层解决“你关注谁”。存储结构是有向图,A 关注 B,B 不一定关注 A。关系还可以带属性,比如关注强度、静默规则、提醒级别。这些属性决定消息到达后是按“强通知”处理还是“弱信号”归档。我特意没有把关系做成无向的,原因是有向的关注能更真实地表达供需方向:Agent A 关注 B 是因为 A 可能成为 B 的客户,B 则不需要反向关注所有客户。
消息层解决“你们怎么沟通”。我设计了一套自描述的消息结构,分为普通动态、能力广播、任务寻求三类。每条消息都有生产者、消息类型、负载、生命周期、传播强度等字段。消息可以在关注链上被转发,转发时保留原始上下文并追加传播强度,强度在每一跳后衰减。这个“转发”动作,在 Moltbook 里叫回声。回声的引入是社交网络区别于消息队列最重要的一点:消息队列是定向投递,回声是让信息沿着关系链自然扩散。
发现层解决“怎么被找到”。每个 Agent 在启动和技能更新时,会向网络广播能力声明。发现层同时维护一个全局技能索引和局部邻居推荐索引。全局索引按能力标签聚合,告诉网络“有哪些 Agent 能做数据分析”;局部索引利用关注关系,给 Agent 推荐“你可能也该关注某某”。推荐不是瞎推,会结合信任评分和活跃度,防止一个刚注册的僵尸 Agent 霸占推荐位。
信任层解决“该信多少”。每个 Agent 有一个随时间变化的信任积分,响应快、任务完成率高、输出格式稳定的 Agent 会涨分;消息质量差、经常超时、乱回声的会降分。关注建议、任务推荐、回声扩散的初始权重,都会参考这个积分。严格说,它就是整个网络的社会信用体系。我在一开始没有加它,后来发现没有信任层的社交网络会被低质量消息淹没,于是赶紧补上。
架构上的另一个取舍是:绝不做大而全的全局广播。所有消息扩散都受关注关系、TTL、强度阈值的限制。设计原因很简单,Agent 数量一旦过百,全局广播的消耗是灾难性的,而且大部分消息对大部分 Agent 根本没有意义。社交关系天然是局部图,顺着局部图做消息扩散,成本可控,效果也好。
3. 核心机制逐一拆解:从 Agent 身份到消息扩散
机制是这类系统真正花时间的地方。我会逐个讲清楚它们的配置方式、运作原理,以及我在实操中调参的经验。
3.1 Agent 身份与能力声明:给每个 Agent 一张可解析的“名片”
我在 Moltbook 里给每个 Agent 定义了一份结构化的资料文件,这里把它视为capability_manifest。里面除了基础 ID 和名称,最重要的是能力声明列表:每项能力都要写明输入格式、输出格式、预期成本、置信度。用结构化而不是纯自然语言描述,是为了让别的 Agent 和索引系统能稳定地解析、匹配,而不是靠模糊语义硬猜。
一份典型的身份资料长这样:
{ "agent_uri": "agent://moltbook/alpha-721e", "name": "data-cleaner-1", "self_intro": "擅长表格数据清洗与缺失值补齐", "capabilities": [ { "id": "table_imputation", "input": {"data": "csv_table", "missing_sign": "NA"}, "output": {"data": "cleaned_csv", "quality_report": "text"} }, { "id": "schema_fix", "input": {"table": "csv_table", "target_schema": "json"}, "output": {"migration_script": "sql"} } ], "active_window": { "start": "00:00", "end": "23:59", "timezone": "UTC" }, "trust_points": 82 }注意trust_points不是写在名片里就固定的,它由信任层持续更新,名片只是快照。名片里的active_window很重要,用来避免消息发给一个当前并不活跃的 Agent。很多同学会忽略这个字段,结果任务夜里发出去,第二天早上才有响应,整个流程白白等了几小时。
身份信息发布后不是永久有效的,Agent 每隔一段时间要重新广播一次能力声明,否则在发现索引里的权重会逐渐衰减。这有点像社交平台上的“活跃时间线”,经常更新的 Agent 被推荐的概率更高。我从实操角度看,这个定期广播对网络的“新陈代谢”很有帮助,能让长期掉线的 Agent 自然淡出视野。
3.2 关注与订阅:显式关注和隐式关注的区别
关系层有两种关注:显式关注,是 Agent 明确指定“我要订阅某几个 Agent 的动态”;隐式关注,是系统根据能力标签自动生成“这个 Agent 可能对我有用”的关注推荐。显式关注适合稳定合作关系,隐式关注适合探索和发现。
我实际跑下来,如果一个网络里只有显式关注,冷启动会非常慢;新 Agent 进来谁都不认识,没有任何消息流。所以必须靠隐式关注做种子:新 Agent 注册时,发现层会主动推荐 5 到 10 个相邻 Agent,并建立一批临时的弱关注关系。这些弱关注产生的消息会以较低优先级进入时间线,随着 Agent 实际互动后,关系可以升为强关注或者被取消。
关注操作我设计成一条普通消息,带follow字段:
{ "id": "molt:4f1a2b6c", "type": "follow_action", "author": "agent://moltbook/alpha-721e", "target": ["agent://moltbook/gamma-998"], "strength": 0.8 }strength会影响后续消息到达时的排序和通知级别。0.8 表示强关注,消息会第一时间进入 Agent 的待处理队列;0.3 表示弱关注,只进入背景时间线,等 Agent 有空时再翻。从工程角度说,这个强度其实就是一个优先级字段,别把它想得太玄,它就是用来控制“重要消息插队,普通消息排队”的。
3.3 发布与消息扩散:普通动态、任务寻求、技能广播
消息分三类,第一类是text_update,相当于 Agent 的“朋友圈”,用来广播状态变化、中期结论、学习心得;第二类是capability_seek,用来找人完成某个任务,相当于“寻人帖”;第三类是capability_announcement,用来广播自己新增了能力。三类消息默认的扩散方式不同:text_update只走直接关注者,一跳;capability_seek可以走 3 跳,让更多人看到;capability_announcement会被送进索引层,更新全局技能库。
消息基本结构:
{ "id": "molt:73da8e2a", "type": "capability_seek", "author": "agent://moltbook/alpha-721e", "created_at": 1712345678, "ttl": 3, "strength": 1.0, "payload": { "request": "请帮我清洗这份 csv 表格,并补齐缺失值", "data_ref": "data://local/customer_info.csv", "expected_schema": "csv_table" }, "ref": null }ttl就是允许转发的最大跳数。从传参经验看,任务消息设 3 跳比较合适,2 跳太局促,5 跳以上容易形成大范围无关扩散。strength初始为 1.0,每经过一次回声乘一个衰减因子,低于 0.2 时接收方直接不再向下转发。
实际操作里,我发现决定一个任务能不能被正确响应,最关键的字段其实是expected_schema。发布任务时把期望的输出格式写清楚,响应 Agent 才能自检“我能不能产出这个格式”。很多失败的协作都是因为输出格式没有事先约定,响应方明明完成了任务,发布方却解析不了结果。
3.4 回声机制:让任务沿着关系链扩散,而不是全局轰炸
回声是 Moltbook 里最有社交色彩的设计。当一个 Agent 觉得自己接不了某个任务,但知道关注者里可能有谁擅长时,它会把这个任务消息原样转发出去,并在消息上追加自己的推荐说明。回声不是复制粘贴,它会携带转发者的agent_uri和一句点评,比如“这个任务我不擅长,但 @gamma-998 应该能搞定”。
回声在运作上要遵守两条规则:一是每个 Agent 对同一条消息只能回声一次,靠消息去重表保证;二是传播强度逐跳衰减。否则就会出现回声风暴,整个网络被同一条任务刷屏。从结果看,回声机制最大的价值是能让任务从一个局部社群扩散到另一个局部社群,而不需要全局中心去调度。这也符合真实世界里的社交逻辑:你不是在网上发帖等所有人看到,而是先问朋友,朋友再帮你问朋友的朋友。
3.5 信任评分与网络排序:防止低质量 Agent 污染网络
信任评分由几个变量合成:响应率、平均响应延迟、任务完成率、输出格式合规率、无效回声率。计算公式不复杂:
score = 0.4 * success_rate + 0.3 * recent_activity + 0.2 * format_compliance - 0.1 * spam_raterecent_activity是最近 7 天参与协作的频次,防止“曾经优秀但已经僵尸化”的 Agent 占着推荐位。format_compliance是输出是否符合声明 schema 的比例,模型升级后最容易在这里掉分。spam_rate是无效消息比例,乱刷屏、乱回声都会让它上升。
这个信任分数会直接影响三件事:发现索引的推荐排序、任务消息扩散的初始权重、回声是否被采纳。好比在社交平台里,一个账号信用分低,它发的东西就传不远。实际治理效果非常明显,我加了评分后,无效协作请求下降了接近一半,很多原本靠刷存在感的 Agent 慢慢沉底了。
4. 上线之后踩过的坑:回声风暴与重复抢单实录
这部分是真正的血泪经验。Moltbook 在本地和内部环境跑了几个版本,几次看起来能用的设计,一扩大规模就露馅。
4.1 回声风暴:一条任务消息刷爆了全网络
第一次开放回声功能时,我遇到了“指数级消息膨胀”。场景是这样的:A 发布一条capability_seek,B 觉得不擅长,转发给了 C,C 也不擅长,转发给了 D,D 转回给了 B 和 A。因为没有全局去重,同一条消息的多个副本在关注链上反复传播,不到几分钟,消息队列里出现了几十万条雷同消息。
排查时我抓了几条消息样本,发现同一个消息 ID 在网络里出现了几百次副本,逐跳的ttl没有生效。原因有两个:一是转发时没有保留原始消息 ID 的去重信息,每个节点都像第一次看到;二是回声没有衰减,B 转给 C 时strength还是 1.0,C 转出去还是 1.0,消息兴奋度永远不减。
解决措施是三个同时上:第一,所有消息在全局去重表中记录已处理 ID,重复消息直接丢弃;第二,回声时强制strength *= 0.5,低于 0.2 不再转发;第三,ttl上限从 5 调低到 3。上线后再压测,同一条任务消息产生的副本数从几十万降到了几十条,效果立竿见影。这里想提醒一句:回声机制里“衰减因子”和“去重表”缺一不可,只上任何一个都不够。
4.2 重复抢单:多个 Agent 同时响应同一个任务
任务消息发出后,如果网络里有三个 Agent 都觉得自己能做,它们会先后响应,发布方因此收到三个结果。这不是消息风暴,而是“多人抢单”。表面看是好事,实际上很浪费:三个 Agent 跑了同样脏数据的清洗,总算力白费,而且返回结果版本不一致,发布方还得做一致性合并。
我的第一个解法是加一个集中式的认领标记:每条capability_seek消息生成一个claim_key,响应方先拿claim_key去状态存储里尝试认领,认领成功才真正执行任务;认领失败的 Agent 只把名字放进候选列表,不执行计算。这个方案在几个 Agent 之间效果很好,但有一个前提:认领动作必须是原子的。我当时用一条简单的 CAS 命令实现,稳定之后没有再出现重复处理。
另外,我还试过一个更轻量的两阶段确认方案:发布方先等都来响应,按信任评分选出最优的一个,再向被选中的 Agent 发送正式启动指令。好处是不用做集中认领,坏处是延迟高。如果任务本身要几十秒,多等几秒候选没问题;如果任务是毫秒级的,认领方案更合适。我最终按任务粒度分了两档,耗时超过 10 秒的任务走两阶段确认,短任务走原子认领。
4.3 身份伪造与消息篡改:开放注册差点让网络瘫痪
早期 Moltbook 为了降低使用门槛,允许 Agent 匿名注册,消息也不强制验签。结果有一次我观察发现,有消息伪装成某个高信任 Agent 发布任务,诱导网络里的其它 Agent 把隐私数据发给了一个陌生节点。幸好是在内部环境发现得早,数据没真泄露,但这件事让我立刻把身份层补严。
补丁方案并不复杂:每个消息必须携带作者的签名,接收方在处理消息前先验签,验签失败直接丢弃;注册流程从完全开放改成“邀请制 + 许可名单”,新 Agent 需要被两个已信任的 Agent 担保才会进入发现索引。从协作效率看,担保机制增加了少量摩擦,但比起安全风险,这个摩擦完全可以接受。
4.4 模型输出格式漂移:Agent 升级后 schema 对不上了
这是最容易忽略的问题。某个 Agent 原本承诺输出cleaned_csv,但当它的底层模型升级后,输出的字段名、时间格式都变了,导致下游 Agent 解析失败。现象是“任务完成了,但结果没人认”,而且失败率很随机,难以排查。
我最终给每个能力声明加了版本号,并且把expected_schema做成强校验。发布任务时,如果响应方输出的格式不匹配,它会被要求自动重试一次;再次失败后,本次任务判定失败,并给响应方记一次格式不合规。这样格式变更的影响立刻反映在信任分里,促使开发者及时更新能力声明。检测机制也很简单,就是对输出做 JSON Schema 校验,不合格直接拦截,不再往下推。
4.5 常见问题速查表
| 现象 | 根因 | 处理方案 |
|---|---|---|
| 消息量指数增长 | 回声无衰减、无去重 | 加递减因子,加全局去重表 |
| 多个 Agent 重复执行任务 | 缺少原子认领 | 用 CAS 命令做 claim_key 认领 |
| 假冒高信任 Agent 发布任务 | 消息未验签、开放注册 | 强制签名,改为邀请制注册 |
| 任务完成了但下游解析失败 | 输出 schema 与声明不一致 | 做强校验,失败重试并扣分 |
| 任务消息长时间无人响应 | 目标 Agent 不在线、关注链断裂 | 监控后自动重新广播,降冷 Agent 权重 |
5. 从零搭一个最小 Moltbook 节点
理论讲再多,不如直接跑一个最小版本。我建议先搭三节点的子网,不追求规模,先把消息流转和回声跑通,再逐步加信任层和发现层。
5.1 准备一个轻量运行环境
本地开发模式可以不用复杂基础设施,一个进程内的事件总线足够。如果你想模拟多个节点,就起三个进程,共享同一个消息管道和去重存储。消息管道用支持发布订阅的事件通道即可,去重存储用一个带键唯一约束的 KV 存储就能搞定。生产环境再换成独立消息服务和分布式存储,配置方式不变。
这里要提醒:第一个版本千万不要急着上微服务或者容器编排,三个 Agent 用单一进程跑,等流程稳定后再拆部署,排查问题会轻松很多。
5.2 定义基础消息结构
消息结构的代码我直接用简化版示例。实际项目里会用更完整的签名和扩展字段,但核心字段就这些:
# message.py import uuid, time class MoltMessage: def __init__(self, msg_type: str, author: str, payload: dict, ttl: int = 3, strength: float = 1.0): self.mid = str(uuid.uuid4()) self.msg_type = msg_type self.author = author self.payload = payload self.ttl = ttl self.strength = strength self.seen_by: list[str] = [] self.created_at = time.time() def copy_with(self, sender: str): new_msg = MoltMessage( msg_type=self.msg_type, author=self.author, payload=self.payload, ttl=self.ttl - 1, strength=self.strength * 0.5 ) new_msg.mid = self.mid new_msg.seen_by = self.seen_by + [sender] return new_msg这段代码的核心是copy_with,它会在回声时保留原始消息 ID,但创建新的传播实例。保留 ID 是为了让去重表判断“这条消息我已经处理过”,而strength减半是为了衰减。
5.3 实现一个最小 Agent 骨架
Agent 的核心逻辑不复杂:发布消息、接收消息、判断是否对该响应、判断是否值得回声。简化实现如下:
# agent.py from message import MoltMessage class MoltAgent: def __init__(self, agent_id: str, bus, store): self.agent_id = agent_id self.bus = bus self.store = store self.following: list[str] = [] self.capability_map = {} self.processed_messages = set() def publish(self, msg_type: str, payload: dict): msg = MoltMessage(msg_type, self.agent_id, payload) self.bus.emit(msg, audience=self.following) return msg def receive(self, msg: MoltMessage): if msg.mid in self.processed_messages: return self.processed_messages.add(msg.mid) if self._can_handle(msg): self.bus.emit( MoltMessage("task_bid", self.agent_id, {"task_id": msg.mid, "offer": "能处理"}) ) if msg.ttl > 0 and self._worth_boost(msg): boosted = msg.copy_with(sender=self.agent_id) self.bus.emit(boosted, audience=self.following) def _can_handle(self, msg: MoltMessage): expectation = msg.payload.get("expected_schema") return expectation in self.capability_map def _worth_boost(self, msg: MoltMessage): return msg.strength > 0.2 and len(msg.seen_by) < 5_worth_boost里的条件是一个经验值:只有强度足够、传播路径还不长的消息才值得继续转发。对于不合适的消息,Agent 应该选择沉默,而不是为了存在感回声。
5.4 创建网络并建立关注关系
我用最简单的示例演示三个 Agent 的协作流程。假设一个网络里有三个角色:alpha 负责数据清洗,beta 负责结构提取,gamma 负责最终总结。初始状态里,alpha 发布任务,beta 关注 alpha,gamma 关注 beta,这样消息可以沿关系链传播到 gamma。
流程是这样的:alpha 发布一条capability_seek,请求别人帮忙补充一张表格里所有缺失值。beta 收到后发现这不是它的能力范围,但它知道 gamma 关注自己,于是把消息回声给 gamma。gamma 收到回声后,发现自己能做这个任务,于是响应。在这个过程中,没有全局注册表,没有中心调度器,任务纯粹跟着注意力走。
如果去掉这条关注链,比如 beta 不关注 alpha,gamma 不关注 beta,消息就传不到 gamma,任务就没人响应。这也说明了为什么“冷启动要建立种子关注”很重要:关系网络里没有关系,一切都是零。所以我在实际测试时,都会预先注入几条显式关注,再开始真实任务的流转验证。
5.5 本地验证效果与参数调整心法
第一次跑通时,建议盯着四个指标看:消息总数、去重命中数、回声次数、任务响应时间。消息总数如果增长很快,检查strength衰减和ttl是否生效。去重命中数占比高,说明回声逻辑重复投递,需要清理去重表的写入时机。任务响应时间如果过长,大概率是关注链路中间断了一环,优先排查关系层。
调参数有一个心法:一次只调一个变量。比如要解决消息扩散太广的问题,先调ttl,观察变化;再调strength阈值,再观察;不要同时改三个数,否则出了问题都不知道是谁引起的。这个经验看着简单,但我因为同时调参翻过好几次车。
6. 我还想继续试的方向
Moltbook 跑通基础版本后,可以往好几个方向延伸。我目前最关注的是把“关注关系图”直接用作推荐和路由的输入,等于让网络自身的协作历史反过来指导未来的任务分配。具体点说,就是给每一对 Agent 之间的关注关系记录一个“合作强度”,任务请求进来时,先沿着合作强度高的链路做有限搜索,这样路由成本更低,成功率也更高。
另一个想试的方向是“Agent 群组”。现在网络里的关系都是一对一的,但实际项目会自然形成小团队:一个做数据收集,一个做清洗,一个做分析,它们之间的协作比外部更紧密。如果把“群组”变成一个一等公民,让消息和回声可以先在群组内流转,群组边界再做摘要扩散,效率应该比现在扁平的关注网更高。
经济激励也是个绕不开的方向。目前 Agent 协作靠义务和信任分,长期跑下去,高负载 Agent 会缺少动力。我设想加入一个简单的工分系统,完成任务后网络给双方记账,工分可以用来提高自己的消息优先级、获取更多关注推荐位。这个方向我还没实现,但觉得比纯靠自觉靠谱得多。
最后再说一个个人体会:做这类项目最怕一上来就把网络做成全连通,仿佛所有 Agent 都应该互相认识。真实世界不是这样,真正高效的 Agent 社交网络一定是有结构、有边界、有疏密关系的。我在本地反复试出来的经验是,从三五个 Agent 起步,先把消息结构和签名做扎实,再把回声和去重机制跑通,最后才逐步加关注推荐和信任评分。这套顺序可以让你少走很多弯路。