BoxLang AI 深度解析:多智能体编排与协作系统构建
BoxLang AI 深度解析 — 第 3 部分(共 7 部分):多智能体编排 — 构建高效 AI 团队 🌲
目录
- 🌲 智能体树 (The Agent Tree)
- 🤖 将子智能体作为工具
- 🏢 AiAgent 现已完全无状态
- 🧠 基于内存的每调用身份路由
- 🏗️ 智能体运行生命周期
- 🌊 多智能体团队的流式传输
- 🔄 挂起与恢复
- 🔍 自省 (Introspection)
- 🚀 完整的多智能体示例
- 后续展望
[LOADING...]
BoxLang AI 3.0 系列 · 第 3 部分(共 7 部分)
单个智能体很有用,但一组智能体协同工作则更加强大。
大多数多智能体框架的问题在于编排层是“外挂”式的——你需要手动管理智能体引用,手动在它们之间传递输出,并时刻担心是否引入了循环依赖。它们缺乏层级概念,没有循环检测,也无法回答“谁是负责人”或“我在树中的深度是多少”这类问题。
BoxLang AI 3.0 改变了这一点。AiAgent 现在可以跟踪其在完整层级树中的位置,子智能体会被自动挂载为工具——协调者无需知道如何进行委派,只需知道它有权委派即可。
🌲 智能体树
每个 AiAgent 都拥有一个 parentAgent 属性和一套完整的层级辅助方法。这种关系是双向的:addSubAgent() 在一次调用中即可将子智能体注册为可调用的工具,并设置父级引用。
源码中完整的层级 API 如下:
内置循环检测
设置会导致循环的父级会立即抛出异常——绝不会出现静默的无限循环:
🤖 将子智能体作为工具
addSubAgent() 的魔力在于,每个子智能体都会自动封装为一个父级可以调用的工具——无需手动配置,无需自定义回调代码。
当调用 addSubAgent() 时,父级的 AiModel 会获得一个名为 delegate_to_researcher、delegate_to_writer 等的新工具。大模型(LLM)在其上下文中看到这些工具后,会决定何时调用它们——其方式与调用任何其他工具完全相同。
协调者不需要特殊的逻辑,它只是拥有了更多的工具。
🏢 AiAgent 现已完全无状态
这是 3.0 版本中最重要的架构变更之一:AiAgent 不再将 userId 或 conversationId 作为实例状态保存,而是按调用进行解析。
这意味着一个智能体实例可以安全地为多个并发用户提供服务——没有竞态条件,没有跨用户污染,也不需要为每个用户创建智能体工厂。
🧠 基于内存的每调用身份路由
所有内存类型都遵循相同的模式——add()、getAll()、clear() 和 trim() 都接受可选的 userId 和 conversationId 参数:
当智能体在内部调用 loadMemoryMessages() 时,它会将解析后的 userId 和 conversationId 传递给所有关联的内存。内存自然实现了租户隔离,无需任何额外的配置。
🏗️ 智能体运行生命周期
了解 run() 内部发生了什么,对于调试或构建中间件(第 4 部分将深入讨论)非常有用。以下是执行顺序:
- 解析
threadId/userId/conversationId(按调用解析,非实例状态)。 - 构建用户消息结构。
- 构建系统消息(描述 + 指令 + 技能 + 工具 + MCP 服务器)。
- 加载该
userId/conversationId的内存消息。 - 组装:
[system, ...memory, userMessage]。 - 触发
beforeAgentRun中间件(前向传递)。 - 触发
BoxAnnounce事件"beforeAIAgentRun"(全局事件)。 - 通过
AiModel.run()执行 — 处理工具调用、重试、流式传输。 - 如果挂起(HITL):检查点存储并返回。
- 将助理响应存储在所有内存中(以
userId/conversationId为作用域)。 - 触发
afterAgentRun中间件(反向传递)。 - 触发
BoxAnnounce事件"afterAIAgentRun"(全局事件)。 - 返回响应。
系统消息也会被缓存和指纹化——如果描述、指令和技能池自上次调用以来没有改变,则使用缓存版本,而不是重新构建。这对于同一智能体处理大量请求的高吞吐量场景至关重要。
🌊 多智能体团队的流式传输
流式传输在多智能体设置中工作方式相同——每个智能体都可以独立进行流式传输:
当协调者决定委派给研究员时,该子调用在工具调用内部同步发生——流式传输的协调者会收到研究员的结果作为工具响应,然后继续流式传输。
🔄 挂起与恢复
当 HumanInTheLoopMiddleware(第 4 部分涵盖)挂起智能体时,状态需要被保留。checkpointer 属性负责处理此过程:
resume() 的实现会从保存的检查点重新运行,将人类的决定注入中间件上下文:
🔍 自省
getConfig() 方法让你能够全面了解智能体的状态——对于调试、监控仪表板和日志记录非常有用:
🚀 完整的多智能体示例
这是一个实用的编排案例:一个协调者将研究任务委派给专业研究员,将写作任务委派给专业写作者,两者都拥有各自的技能和工具。
驱动协调者的大模型看到了两个工具:delegate_to_researcher 和 delegate_to_writer。它决定首先调用研究员,获得详细摘要,然后将该摘要和原始请求发送给写作者,最后将写作者的输出合成为最终响应。你无需编写任何此类逻辑——大模型通过工具描述自行推导出了执行方案。
后续展望
在第 4 部分中,我们将探讨中间件系统——包括六个内置中间件类、钩子生命周期如何工作、如何编写自己的中间件,以及使 AI 智能体在 CI 中可测试的 FlightRecorderMiddleware。