跳到主要内容

BeeAI Framework — 架构与原理

30 秒导读: BeeAI 是一个用 Python / TypeScript 写多 agent 系统的框架。它最有辨识度的东西不是「又一个 ReAct agent」,而是 RequirementAgent:你给 agent 配一组需求规则(比如「第 1 步必须先思考」「查完资料才允许回答」「调危险工具前先问我」),框架在每一次让模型说话之前把这些规则算成「这一步允许 / 禁止 / 强制 哪些工具」,再把工具列表喂给模型。结果是:同一个 agent,换个更笨的模型也不会乱来。

1. 这是什么(零基础也能懂)

一句话定义。 BeeAI Framework 是一套构建「会推理、会调工具、能互相协作」的 AI agent 的工具箱,Python 与 TypeScript 双实现。

它解决谁的什么问题。 假设你写了个能调工具的 agent,在 GPT-4 上表现很好;换到一个小的本地模型(比如 8B 的 Ollama 模型),它就开始乱来:该查资料时直接瞎编、该停时停不下来、把同一个工具反复调十遍。问题不在你的代码,在于不同模型的推理与工具调用能力差异巨大。BeeAI 的 RequirementAgent 用「规则」把这种差异抹平——能力不靠模型自觉,靠框架在每一步强制。

它能做什么(模块清单)。

模块干什么
RequirementAgent声明式、带规则约束的 agent(旗舰)
Backend / ChatModel用统一接口接任意 LLM 提供商(底层走 LiteLLM)
Tools内置工具(搜索 / 天气 / 代码执行 / MCP / OpenAPI)+ 自定义工具
Memory对话历史的几种策略(无约束 / 滑窗 / token 上限 / 摘要)
Emitter事件系统,agent 每一步都发事件,用于日志 / 观测
Workflow把多个步骤 / agent 编排成状态图
Serve把 agent 暴露成服务器(A2A / MCP 协议)

用起来什么样。 下面是 README 里的精简版——一个会「先思考、再查维基百科」的知识 agent:

# 示意,基于 README 的 Multi-Agent Example 精简
from beeai_framework.agents.requirement import RequirementAgent
from beeai_framework.agents.requirement.requirements.conditional import ConditionalRequirement
from beeai_framework.backend import ChatModel
from beeai_framework.tools.search.wikipedia import WikipediaTool
from beeai_framework.tools.think import ThinkTool

agent = RequirementAgent(
llm=ChatModel.from_name("ollama:granite4:micro"),
tools=[ThinkTool(), WikipediaTool()],
requirements=[
# 规则:第 1 步必须先调用 ThinkTool(强制思考再行动)
ConditionalRequirement(ThinkTool, force_at_step=1),
],
role="Knowledge Specialist",
instructions="Provide answers to general questions about the world.",
)

result = await agent.run("法国的首都是哪里?")
print(result.last_message.text)

关键在 requirements=[...] 那一行:force_at_step=1 不是写进 prompt 的「建议」,而是框架在第 1 步真的只把 ThinkTool 放进允许列表,模型没得选。

一句话直觉。 把普通 agent 想成「给模型一堆工具,然后求它别乱用」;把 RequirementAgent 想成「每一步都重新发一张通行证,上面写明这一步你只能走哪几扇门」。通行证由规则引擎根据当前状态当场签发。

2. 顶层全景(它大概怎么转)

RequirementAgent 一次 run 的控制流是一个循环:每转一圈,规则引擎先根据当前状态算出「本步允许的工具」,据此组装系统提示与 tool_choice,调模型,执行模型选的工具,把结果写回记忆,再转下一圈——直到模型调用了 final_answer 工具。

agent.run("问题")


┌─────────────────────────────────────────────┐
│ RequirementAgentRunner.run() ←── 主循环 │
│ │
│ 每一圈(一个 iteration): │
│ │
│ ① 规则引擎签发本步「请求」 │
│ RequirementsReasoner.create_request() │
│ → 谁 allowed / hidden / forced / 能否停 │
│ │ │
│ ▼ │
│ ② 组装系统提示 + tool_choice,调 LLM │
│ _run_llm() → ChatModel.run() │
│ │ │
│ ▼ │
│ ③ 模型回了 tool_call? │
│ ├─ final_answer → 写入 state.answer,停 │
│ ├─ 普通工具 → 执行,结果写回 memory │
│ └─ 检测「死循环」→ 加规则禁掉该工具重来 │
│ │ │
│ └────── 回到 ① ──────────────┘
└─────────────────────────────────────────────┘
│ state.answer 非空时退出

RequirementAgentOutput(output=[answer], state=...)

主要部件一句话职责:

部件干什么在哪个文件
RequirementAgent对外的门面:收集 llm / tools / requirements,造 runneragents/requirement/agent.py
RequirementAgentRunner主循环:逐 iteration 跑,管错误重试与死循环检测agents/requirement/_runner.py
RequirementsReasoner规则引擎:跑所有需求生成规则,聚合成「本步请求」agents/requirement/utils/_llm.py
Requirement / Rule需求(每步生成规则)与规则(对某工具的允许 / 强制 / 隐藏)agents/requirement/requirements/requirement.py
FinalAnswerTool一个特殊「工具」:模型调它即表示「我要交最终答案了」agents/requirement/utils/_tool.py
ChatModel统一 LLM 接口,处理 tool_choice 与跨模型降级backend/chat.py

主线走一遍(高层): 用户问题进来 → runner 进循环 → 规则引擎签发「本步只允许这些工具」→ 把允许的工具 + 各自「allowed/reason」渲染进系统提示,并设 tool_choice 调模型 → 模型选一个工具调 → 若是普通工具就执行、结果回灌记忆、继续循环;若是 final_answer 就把答案落进状态、退出循环 → 返回最终答案。

3. 阅读地图(按这个顺序读)

这个框架的「价值」高度集中在 RequirementAgent + 规则引擎上,所以我们从那里开始,再向下挖横切骨架,最后讲多 agent 组合。

  1. 01-requirement-agent.md — 先把 RequirementAgent 一次 run 的主线、运行器循环、系统提示怎么拼搞清楚。读完你能讲清「一次问答在框架里走了哪些步」。
  2. 02-rule-engine.md — 核心中的核心:Requirement 怎么每步产出 Rule,RequirementsReasoner 怎么把一堆规则按优先级聚合成「本步允许 / 强制 / 隐藏 哪些工具」。这是整个框架最值得带走的设计。
  3. 03-runtime-emitter-context.md — 横切层:Runnable / RunContext / Emitter 这套贯穿 agent、工具、工作流的执行 + 可观测骨架,以及中间件怎么挂上去。
  4. 04-multi-agent.md — 把多个 agent 拼起来的两条路:HandoffTool(把整个 agent 包成一个工具)与 Workflow(状态图编排)。
  5. 05-cleverness-boundaries-map.md — 巧妙之处、边界局限、与兄弟框架的横向对比,以及给 agent / 人用的代码地图跳转表。

注:本库同时有 python/typescript/ 两套实现。本组文档以 Python 实现为准(引用路径相对 python/ 根),两边设计同构,符号名基本一致。