跳到主要内容
AI教程

使用 Unreal Agent 构建异步、持久化的 AI 代理工作流

本教程将介绍 Unreal Agent 的异步优先架构、仓库布局、核心组件和事件流。你将了解输入如何成为持久化的会话历史记录,工具调用如何转换为异步操作,如何进行设置和使用,以及如何在不违反其序列化和事件循环不变量的前提下扩展该框架。

使用 Unreal Agent 构建异步持久化 AI 代理工作流

什么是 Unreal Agent?

Unreal Agent 是 Unreal Labs 提供的一个异步优先代理框架。它提供可组合的基础设施,用于接收输入、维护会话历史、准备模型上下文、协调 LLM 轮次、转换工具调用,以及调度持久化的异步操作。

该项目将同步协调与异步执行分离。工具转换器会验证模型生成的请求,并生成可序列化的操作描述,而不会执行 I/O。随后,操作管理器会在协调器的事件循环之外执行已提交的操作。

仓库结构

该仓库分为三个主要区域:

  • harness/:可复用的代理框架库。
  • cmd/:使用该库构建的可执行文件。
  • benchmarks/:用于评估项目的基准测试运行器。

将框架集成到其他应用程序时,请从 harness/ 开始。查看 cmd/ 了解具体的可执行入口点;需要检查或测量运行时行为时,使用 benchmarks/。

核心概念

输入与收件箱

输入是一个由调用方提供全局唯一标识符的事件。如果该事件再次传递,其标识符必须保持不变。

会话收件箱使用这些标识符,对外部输入、控制输入和崩溃输入进行内存中的去重。这种幂等性仅限于会话范围且是易失性的,因此调用方仍应始终提供稳定的 ID。

{
  "id": "globally-unique-and-stable-id",
  "type": "external-input",
  "payload": "Example request"
}

这种形式是概念性的,并非 Unreal Agent 文档记录的 API 类型。关键要求是输入 ID 必须稳定且全局唯一。

会话

会话是一个仅追加、持久化的历史记录。会话可以恢复和分叉,使应用程序能够继续现有工作,或从之前的历史记录创建分支,而无需重写原始序列。

会话存储负责维护规范历史记录和操作状态。它还会将工具调用的转换状态与该转换生成的操作原子地记录下来。

LLM 轮次

LLM 轮次是围绕一次逻辑模型请求、由协调器管理的序列。协调器会持久化已接受的输入、准备轮次、解析工具转换器、记录产生的工作,并调度已提交的操作。

工具、转换器与操作

工具由一个架构和一个转换器组成。当模型生成工具调用时,转换器会对其进行验证,并将其转换为一个或多个操作。

工具转换器会在协调器的事件循环上同步运行。它不得执行 I/O 或挂起事件循环。

转换结果称为工具调用状态。其中包含验证错误,或已提交操作的引用。该状态与这些操作的执行状态相互独立。

操作是对异步工作的可序列化、版本化描述。转换器负责描述工作;操作管理器负责执行工作。

关键组件

  • 会话收件箱:提供易失的、会话范围内的输入幂等性。
  • 协调器:持久化已接受的输入,管理 LLM 轮次,解析工具转换器,并调度已提交的操作。
  • 会话存储:持久化规范会话历史记录和操作状态,支持恢复与分叉,并将工具调用状态与操作原子地记录下来。
  • 上下文构建器:在内存中组装模型输入,并报告被省略、截断或压缩的内容。它不执行 I/O,也不依赖持久化。
  • LLM 适配器:将准备好的输入发送给模型提供商,并返回标准化的已完成响应。它负责身份验证、取消操作和提供商错误。
  • 工具注册表:负责 Bash、ViewImage 和 skill-use 工具的定义与转换器,同时向宿主暴露所选工具集合。
  • 工具转换器:验证调用,生成状态与操作,并为模型格式化已记录的状态和准备好的操作输出。
  • 操作管理器:为持久化操作提供 actor 运行时。其本地实现可以替换。

安装与设置

README 未指定包管理器、特定语言的安装命令或稳定的公共 API。因此,设置应从本地检出仓库及其构建元数据开始,而不是假定存在某个包命令。

  1. 克隆或下载 Unreal Agent 仓库。
  2. 打开仓库根目录,并检查其构建文件和依赖文件,了解受支持的工具链。
  3. 使用仓库配置的工具构建或安装 harness/ 下的库。
  4. 查看 cmd/ 中组合使用框架组件的可执行示例。
  5. 仅在核心项目成功构建后使用 benchmarks/。
cd <unreal-agent-repository>

# 检查库、可执行文件和基准测试目录。
ls harness
ls cmd
ls benchmarks

宿主应用还需要为所选提供商配置 LLM 适配器。身份验证、取消行为和提供商特定的错误处理应由该适配器负责。

基本用法:跟踪一次代理请求

由于 README 未公开具体的构造函数或方法名称,理解用法最稳妥的方式是按照文档所述的组件流程进行跟踪。

  1. 创建或恢复会话。会话存储提供持久化历史记录和恢复支持。
  2. 使用稳定 ID 提交输入。重新传递同一逻辑事件时,应重复使用相同的 ID。
  3. 通过会话收件箱去重。在活动会话中,收件箱会根据实现行为拒绝或忽略重复输入。
  4. 持久化已接受的输入。协调器会将其记录到规范的追加式会话历史记录中。
  5. 构建模型上下文。上下文构建器会组装内存中的模型输入,并报告其省略、截断或压缩的任何内容。
  6. 运行 LLM 轮次。LLM 适配器将准备好的输入发送给提供方,并返回规范化的已完成响应。
  7. 解析工具调用。协调器通过注册表查找每个获准使用的工具。
  8. 同步转换。选定的转换器会验证调用,并生成验证错误或可序列化的操作。
  9. 原子提交。会话存储会将工具调用状态和操作一起记录。
  10. 异步分发。操作管理器执行已提交的操作,并独立于转换状态跟踪其执行状态。
  11. 为模型格式化结果。转换器将记录的调用状态与准备好的操作输出结合起来,生成面向模型的结果。

工具调用生命周期示例

带稳定 ID 的输入
  -> 收件箱去重
  -> 持久化会话事件
  -> 上下文构建
  -> 规范化 LLM 响应
  -> 工具注册表查找
  -> 同步验证与转换
  -> 原子提交状态和操作
  -> 异步执行操作
  -> 格式化面向模型的结果

如果验证失败,转换器会记录验证错误,而不会生成操作。如果验证成功,状态会引用已提交的操作,而操作管理器则独立跟踪这些操作是否处于待处理、运行中、已完成状态,或处于其实现定义的其他状态。

选择工具

工具注册表负责管理 Bash、ViewImage 和技能使用的定义与转换器。主机决定要公开其中哪些工具。

仅公开特定部署所需的功能。README 未定义授权或沙箱策略,因此这些问题应由主机环境和操作执行层处理。

扩展 Harness

Unreal Agent 的组件旨在实现可组合。只要保留文档中规定的职责和不变量,就可以用其他实现替换由接口支持的组件。

实现工具转换器

自定义转换器应遵循以下顺序:

  1. 根据工具的架构验证模型生成的参数。
  2. 请求无效时返回验证错误。
  3. 请求有效时,创建一个或多个可序列化、带版本的操作描述。
  4. 返回引用已提交操作的状态。
  5. 提供格式化逻辑,将记录的状态和准备好的操作输出转换为面向模型的结果。

保持转换过程确定且快速。不要在转换器中发出网络请求、访问文件、等待子进程,或执行其他 I/O。

替换操作管理器

本地操作管理器可以替换。一个有文档记录的扩展是代理管理器:它会序列化操作,并将其发送给运行在远程沙箱进程中的另一个本地操作管理器。

这种设计使协调器和转换器专注于验证与持久化意图,同时允许在隔离环境中执行操作。

实现存储

替代会话存储必须保留可序列化性、版本控制、恢复行为,以及工具调用状态与生成操作之间的原子关系。

项目致力于维持会话的向后兼容性。如果不支持某个会话版本,恢复该会话必须以明确错误失败,而不能悄然误读数据。

高级提示

  • 在调用方边界生成输入 ID。 将该 ID 与产生它的事件一同存储,以便重试和重新投递时保留相同的身份。
  • 不要将收件箱去重与持久化历史混为一谈。 收件箱是不稳定且仅限会话范围的,而会话存储会持久化规范事件。
  • 保持转换器纯粹且同步。 将请求转换为操作,而不是直接执行工作。
  • 为每种操作格式设置版本。 操作的生命周期可能超过创建它们的进程,或跨越进程和沙箱边界。
  • 保留原子提交。 如果只记录成功的工具调用状态而没有记录其操作,进程崩溃后可能会导致会话状态不一致。
  • 独立跟踪转换和执行。 有效的调用可能生成已提交但尚未完成的操作。
  • 使用上下文构建器元数据。 监控哪些内容被省略、截断或压缩,以便诊断模型行为。
  • 集中处理提供商相关问题。 将凭据、取消操作和提供商错误保留在 LLM 适配器内部。
  • 为实验创建会话分支。 分支可以探索不同的后续流程,同时保留源会话仅追加的历史记录。
  • 使用代理操作管理器实现隔离。 序列化后的操作可以转发到远程沙箱内的运行时,而无需将同步转换移入其中。

重要不变量

扩展应保留以下保证:

  • 会话存储项保持可序列化。
  • 存储格式保持版本化。
  • 不支持的会话版本会产生明确的恢复错误。
  • 操作保持可序列化并具有版本信息。
  • 上下文构建不执行 I/O,也不接受持久化依赖。
  • 工具转换不执行 I/O,也绝不会挂起协调器的事件循环。

结论

Unreal Agent 为需要持久化会话、输入去重、协调 LLM 轮次、经过验证的工具调用以及持久化异步工作的代理提供了模块化基础。其核心设计原则是在同步转换与异步执行之间建立清晰边界。请从现有可执行程序入手,遵循文档记录的事件流,并在替换或扩展组件时保留序列化、版本控制和原子性。