🏢 每日匀源研读 #003 — MetaGPT圓 AI 组成䞀家蜯件公叞

5 阅读7分钟

项目信息

  • 项目名: MetaGPT (FoundationAgents/MetaGPT)
  • GitHub: github.com/geekan/Meta

  • Star: 67,502 ⭐
  • License: MIT
  • 语蚀: Python

䞺什么看这䞪项目

最近圚研究倚 Agent 系统的讟计发现 MetaGPT 的 Slogan 特别有意思——"Enable GPT to work in a software company"让 GPT 像真实蜯件公叞䞀样协䜜

栞心理念 "Code = SOP(Team)" 也埈有启发性把真实蜯件公叞的标准䜜䞚皋序SOP固化䞋来应甚到 LLM Agent 团队䞭。


栞心理念Code = SOP(Team)

现实蜯件公叞                    MetaGPT
─────────────────────────────────────────
老板䞀句话需求    →       甚户蟓入
产品经理            →       ProductManager
架构垈              →       Architect  
工皋垈              →       Engineer
测试工皋垈          →       QaEngineer
SOP 流皋            →       SOP 驱劚

MetaGPT 把敎䞪蜯件匀发流皋做了䞀䞪抜象蟓入是䞀句话需求蟓出是完敎的代码、规范文档、测试甚䟋等。而内郚运䜜则暡拟了䞀家蜯件公叞的 SOP。


敎䜓架构

┌──────────────────────────────────────────────────────┐
│                      Team (公叞)                      │
│                                                       │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐   │
│  │  产品经理    │  │   架构垈    │  │   工皋垈    │   │
│  │ ProductMgr  │  │ Architect  │  │  Engineer   │   │
│  │  Alice      │  │  Brian     │  │  Cathy      │   │
│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘   │
│         │                 │                 │         │
│         └────────────────┮┮─────────────────┘         │
│                          â–Œ                            │
│              ┌───────────────────────┐               │
│              │     Environment       │               │
│              │  ─────────────────── │               │
│              │  • 消息总线广播   │               │
│              │  • 角色泚册衚         │               │
│              │  • 历史记圕           │               │
│              └───────────────────────┘               │
│                          │                            │
│              ┌───────────┮───────────┐                │
│              │     CostManager       │                │
│              │  预算控制 & 计莹      │                │
│              └───────────────────────┘               │
└──────────────────────────────────────────────────────┘

栞心文件结构

文件䜜甚
software_company.py公叞入口hire() 招聘角色、invest() 讟眮预算、run() 运行
team.pyTeam 类管理倚䞪 Role 和共享的 Environment
environment/base_env.py环境类承蜜角色、消息广播、匂步执行
roles/role.pyRole 基类栞心的 think/act/observe 埪环
roles/product_manager.py产品经理写 PRD、竞品分析
roles/architect.py架构垈系统讟计
roles/engineer.py工皋垈写代码
actions/各种可执行的劚䜜
utils/cost_manager.py预算控制和莹甚计算

Think / Act / Observe 埪环诊解

这是 MetaGPT 最栞心的运行机制每䞪 Role 郜是按照这䞪埪环运䜜的

┌─────────────────────────────────────────┐
│            Role 运行埪环                 │
│                                         │
│    ┌─────── observe ────────┐           │
│    │                        │           │
│    │   1. 从消息猓冲区        │           │
│    │      读取新消息         │           │
│    │                        │           │
│    │   2. 根据 watch 过滀    │           │
│    │      只保留关心的消息    │           │
│    │                        │           │
│    │   3. 存入自身记忆       │           │
│    └───┬───────────────────┘           │
│        │ 有新消息                         │
│        â–Œ                                 │
│    ┌─────── think ─────────┐             │
│    │                       │             │
│    │   1. 根据 react_mode  │             │
│    │      决定䞋䞀步状态     │             │
│    │                       │             │
│    │   2. 选择芁执行的       │             │
│    │      Action            │             │
│    │                       │             │
│    │   3. 讟眮 state        │             │
│    └───┬───────────────────┘             │
│        │ 确定芁执行                         │
│        â–Œ                                 │
│    ┌─────── act ──────────┐              │
│    │                       │              │
│    │   1. 调甚 Action.run() │              │
│    │      执行具䜓劚䜜       │              │
│    │                       │              │
│    │   2. 生成回倍消息       │              │
│    │                       │              │
│    │   3. 发垃到环境         │              │
│    │   4. 存入记忆           │              │
│    └───┬───────────────────┘              │
│        │                                   │
│        └──────────┐                        │
│                   │                        │
│         埪环盎到 state=-1                   │
└─────────────────────────────────────────┘

1. Observe — 观察感知环境

async def _observe(self) -> int:
    """从消息猓冲区读取新消息并过滀"""
    # 1. 从消息猓冲区 pop 所有消息
    news = self.rc.msg_buffer.pop_all()
    
    # 2. 根据 watch 列衚过滀
    # watch 记圕了这䞪 Role 关心哪些 Action 产生的消息
    self.rc.news = [
        n for n in news 
        if (n.cause_by in self.rc.watch or self.name in n.send_to) 
        and n not in old_messages
    ]
    
    # 3. 存入自身记忆
    self.rc.memory.add_batch(self.rc.news)
    
    return len(self.rc.news)  # 返回新消息数量

关键抂念 watch每䞪 Role 有䞀䞪 watch 集合里面是芁监听的消息类型。比劂产品经理䌚监听 UserRequirement甚户需求和 PrepareDocuments准倇文档这䞀䞪 Action 产生的消息。

2. Think — 思考决定行劚

async def _think(self) -> bool:
    """决定䞋䞀步执行哪䞪 Action"""
    
    # 情况1: 只有䞀䞪 Action盎接执行
    if len(self.actions) == 1:
        self._set_state(0)
        return True
    
    # 情况2: BY_ORDER 暡匏按顺序执行
    if self.rc.react_mode == RoleReactMode.BY_ORDER:
        self._set_state(self.rc.state + 1)
        return self.rc.state < len(self.actions)
    
    # 情况3: REACT 暡匏甚 LLM 决定
    prompt = self._get_prefix()  # 获取角色讟定
    prompt += STATE_TEMPLATE.format(
        history=self.rc.history,      # 历史记忆
        states="\n".join(self.states), # 可选状态列衚
        previous_state=self.rc.state, # 䞊䞀䞪状态
    )
    
    # LLM 返回䞋䞀䞪状态猖号
    next_state = await self.llm.aask(prompt)
    next_state = extract_state_value_from_output(next_state)
    
    # -1 衚瀺结束
    if next_state == -1:
        logger.info("结束劚䜜")
    
    self._set_state(next_state)
    return True

侉种 react_mode

暡匏行䞺适甚场景
REACTLLM 劚态决定䞋䞀步灵掻、需芁掚理的任务
BY_ORDER按 actions 列衚顺序执行固定流皋、SOP 驱劚的任务
PLAN_AND_ACT先计划再按计划执行倍杂任务、需芁规划

3. Act — 行劚执行劚䜜

async def _act(self) -> Message:
    """执行圓前 state 对应的 Action"""
    # 1. 记圕日志
    logger.info(f"{self._setting}: to do {self.rc.todo}")
    
    # 2. 调甚 Action.run() 执行
    response = await self.rc.todo.run(self.rc.history)
    
    # 3. 封装成 AIMessage
    msg = AIMessage(
        content=response.content,
        cause_by=self.rc.todo,  # 标记由哪䞪 Action 产生
        sent_from=self,         # 标记发送者
    )
    
    # 4. 存入记忆
    self.rc.memory.add(msg)
    
    return msg

角色闎通信机制

MetaGPT 的角色闎通信采甚发垃-订阅暡匏栞心是消息路由

消息发垃流皋

Role A                              Environment                           Role B
  │                                       │                                  │
  │  publish_message(msg)                 │                                  │
  │  ────────────────────────────────────►│                                  │
  │                                       │                                  │
  │                     ┌─────────────────────────────────────────┐          │
  │                     │ 遍历所有角色的地址衚 (member_addrs)     │          │
  │                     │ 检查 msg.send_to 是吊匹配               │          │
  │                     └─────────────────────────────────────────┘          │
  │                                       │                                  │
  │                                       │ put_message(msg)                 │
  │                                       │─────────────────────────────────►│
  │                                       │                                  │

具䜓代码

# Role 发垃消息
def publish_message(self, msg):
    # 劂果没有指定环境消息无法发送
    if not self.rc.env:
        return
    
    # 劂果指定了环境委托给环境发垃
    self.rc.env.publish_message(msg)

# Environment 广播消息
def publish_message(self, message: Message, peekable: bool = True):
    for role, addrs in self.member_addrs.items():
        # 检查消息的 send_to 是吊包含这䞪角色
        if is_send_to(message, addrs):
            role.put_message(message)  # 攟入角色的私有消息猓冲区

消息的结构

class Message(BaseModel):
    content: str           # 消息内容
    send_to: set[str]      # 发送给谁角色名或 "all"
    cause_by: str          # 由哪䞪 Action 产生
    sent_from: str         # 发送者是谁

通信瀺䟋

假讟产品经理Alice写完了 PRD芁告诉架构垈Brian

Alice: 
  msg = Message(
    content="PRD 已完成包含枞戏需求文档",
    send_to={"Brian"},  # 指定发送给架构垈
    cause_by="WritePRD",
    sent_from="Alice"
  )
  self.publish_message(msg)

Brian (圚䞋䞀次埪环䞭):
  news = self._observe()  # 发现有新消息来自 Alice
  self._think()           # 决定芁倄理这䞪消息
  self._act()             # 匀始写架构讟计

预算控制机制

MetaGPT 甹 CostManager 来控制成本防止 LLM 调甚倱控。

工䜜流皋

甚户调甚                         
  │
  │ invest(3.0)  讟眮预算 $3
  ▌
Team.invest()
  │
  │ cost_manager.max_budget = 3.0
  ▌
┌──────────────────┐
│   CostManager    │
│  max_budget=$3   │
│  total_cost=$0   │
└────────┬─────────┘
         │
         │ 每次 LLM 调甚
         ▌
┌──────────────────┐
│  LLM API 返回     │
│  usage 信息       │
└────────┬─────────┘
         │
         ▌
┌──────────────────┐
│ cost_manager.    │
│ update_cost()     │
│                  │
│ total_cost +=    │
│ 新增莹甚          │
└────────┬─────────┘
         │
         ▌
┌──────────────────┐
│ Team._check_     │
│ balance()         │
│                  │
│ if total_cost >= │
│ max_budget:       │
│ raise NoMoneyException │
└──────────────────┘

莹甚计算代码

class CostManager(BaseModel):
max_budget: float = 10.0 # 最倧预算
total_cost: float = 0 # 圓前环计莹甚

def update_cost(self, prompt_tokens, completion_tokens, model):
"""每次 LLM 调甚后曎新莹甚"""
# 从预定义的 TOKEN_COSTS 衚查莹率
cost = (
prompt_tokens * self.token_costs[model]["prompt"] 
+ completion_tokens * self.token_costs[model]["completion"]
) / 1000 # 陀以 1000 是因䞺莹率是 per 1K tokens

self.total_cost += cost
logger.info(f"Total: ${self.total_cost:.3f} / Max: ${self.max_budget:.3f}")

预算检查

class Team:
def _check_balance(self):
"""每次运行埪环前检查"""
if self.cost_manager.total_cost >= self.cost_manager.max_budget:
raise NoMoneyException(...)

async def run(self, n_round=3, idea=""):
while n_round > 0:
if self.env.is_idle:
break
n_round -= 1
self._check_balance() # ← 每次埪环检查预算
await self.env.run()

Role 状态机诊解

每䞪 Role 有 states 列衚和 state 属性衚瀺圓前圚执行流皋䞭的哪䞪阶段。

状态的定义

class Role:
    states: list[str] = []  # 可选状态列衚
    rc.state: int = -1     # 圓前状态玢匕-1 衚瀺空闲/结束

讟眮 Action 时䌚自劚生成状态

def set_actions(self, actions: list[Action]):
    for action in actions:
        self.actions.append(action)
        self.states.append(f"{len(self.actions) - 1}. {action}")
    # 䟋劂states = ["0. WritePRD", "1. WriteSpec", "2. Review"]

状态的䜜甚

1. 远螪进床 — 知道执行到哪䞀步了

2. 决定䞋䞀步 — 根据圓前状态选择䞋䞀䞪 Action

# 状态蜬换瀺䟋
State 0: WritePRD (写需求文档)
    ↓ 产品经理完成
State 1: DesignAPI (讟计 API)
    ↓ 架构垈完成
State 2: WriteCode (写代码)
    ↓ 工皋垈完成
State -1: 结束

3. 恢倍执行 — 劂果䞭闎出错可以从某䞪状态恢倍

# 恢倍时从之前的状态继续
if self.recovered and self.rc.state >= 0:
    self._set_state(self.rc.state)  # 从恢倍的状态继续

䞍同 react_mode 的状态行䞺

react_mode状态行䞺
REACTLLM 根据 history 和圓前 state 劚态决定䞋䞀䞪 state
BY_ORDER每次 act 后 state +1按顺序执行
PLAN_AND_ACT先甚 Planner 生成计划计划䞭的每䞪 task 对应䞀䞪 state

最新劚态和项目的关系

MetaGPT 团队圚 2025 幎发垃了䞍少新䞜西

1. MGX — AI Agent 匀发团队产品

æ—¶é—Ž: 2025 幎 2 月正匏发垃
铟接: mgx.dev/

MGX 是基于 MetaGPT 框架的商䞚化产品定䜍䞺"䞖界銖䞪 AI Agent 匀发团队"。甚户蟓入䞀䞪想法MGX 䌚自劚组建䞀䞪虚拟 AI 公叞来完成敎䞪项目。

2. AFlow — ICLR 2025 Oral 论文

æ—¶é—Ž: 2025 幎 1 月ICLR 2025 OralTop 1.8%
论文: openreview.net/forum?id=z5


AFlow 是䞀䞪自劚化生成 Agent 工䜜流的框架。可以理解䞺 MetaGPT 的䞋䞀代技术——䞍只是甚 SOP 驱劚 Agent而是自劚生成最合适的 SOP。

3. SPO 和 AOT 论文

æ—¶é—Ž: 2025 幎 2 月
代码: 已圚 examples 目圕

SPO 和 AOT 是䞀篇关于 Agent 䌘化和掚理的新论文进䞀步完善了 MetaGPT 的理论基础。


总结

MetaGPT 展瀺了䞀种埈有意思的倚 Agent 协䜜范匏把真实公叞的 SOP 流皋迁移到 AI Agent 团队䞭。

栞心讟计暡匏

暡匏诎明
Think-Act-Observe 埪环Agent 的基本运䜜机制
发垃-订阅消息解耊的匂步通信
状态机驱劚通过 state 控制流皋
预算保技防止 LLM 莹甚倱控
角色分工䞍同角色有䞍同目标、纊束、Action

架构亮点

  1. Environment 䜜䞺消息总线 — 所有角色通过环境广播消息
  2. Role 私有消息猓冲区 — msg_buffer 实现匂步消息接收
  3. 倚层记忆 — memory长期、working_memory工䜜、msg_buffer猓冲
  4. 可插拔的 react_mode — 支持倚种思考-行劚策略

坹倚 Agent 匀发的启瀺

劂果想匀发类䌌"AI 公叞"的倚 Agent 系统MetaGPT 的讟计倌埗参考

  • 甹 SOP 固化流皋比完党劚态协䜜曎可控
  • 消息路由和状态远螪是协䜜的关键
  • 䞀定芁有预算控制防止倱控

项目铟接: github.com/geekan/Meta


参考铟接:

系列埀期:

  • #002: mem0 — 记忆增区的 AI Agent
  • #001: browser-use — 让 AI Agent 操䜜浏览噚

「Code = SOP(Team)」— MetaGPT 让 LLM Agent 协䜜有了䞀种新的可胜性。