
什么是 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。因此,设置应从本地检出仓库及其构建元数据开始,而不是假定存在某个包命令。
- 克隆或下载 Unreal Agent 仓库。
- 打开仓库根目录,并检查其构建文件和依赖文件,了解受支持的工具链。
- 使用仓库配置的工具构建或安装
harness/下的库。 - 查看
cmd/中组合使用框架组件的可执行示例。 - 仅在核心项目成功构建后使用
benchmarks/。
cd <unreal-agent-repository>
# 检查库、可执行文件和基准测试目录。
ls harness
ls cmd
ls benchmarks宿主应用还需要为所选提供商配置 LLM 适配器。身份验证、取消行为和提供商特定的错误处理应由该适配器负责。
基本用法:跟踪一次代理请求
由于 README 未公开具体的构造函数或方法名称,理解用法最稳妥的方式是按照文档所述的组件流程进行跟踪。
- 创建或恢复会话。会话存储提供持久化历史记录和恢复支持。
- 使用稳定 ID 提交输入。重新传递同一逻辑事件时,应重复使用相同的 ID。
- 通过会话收件箱去重。在活动会话中,收件箱会根据实现行为拒绝或忽略重复输入。
- 持久化已接受的输入。协调器会将其记录到规范的追加式会话历史记录中。
- 构建模型上下文。上下文构建器会组装内存中的模型输入,并报告其省略、截断或压缩的任何内容。
- 运行 LLM 轮次。LLM 适配器将准备好的输入发送给提供方,并返回规范化的已完成响应。
- 解析工具调用。协调器通过注册表查找每个获准使用的工具。
- 同步转换。选定的转换器会验证调用,并生成验证错误或可序列化的操作。
- 原子提交。会话存储会将工具调用状态和操作一起记录。
- 异步分发。操作管理器执行已提交的操作,并独立于转换状态跟踪其执行状态。
- 为模型格式化结果。转换器将记录的调用状态与准备好的操作输出结合起来,生成面向模型的结果。
工具调用生命周期示例
带稳定 ID 的输入
-> 收件箱去重
-> 持久化会话事件
-> 上下文构建
-> 规范化 LLM 响应
-> 工具注册表查找
-> 同步验证与转换
-> 原子提交状态和操作
-> 异步执行操作
-> 格式化面向模型的结果如果验证失败,转换器会记录验证错误,而不会生成操作。如果验证成功,状态会引用已提交的操作,而操作管理器则独立跟踪这些操作是否处于待处理、运行中、已完成状态,或处于其实现定义的其他状态。
选择工具
工具注册表负责管理 Bash、ViewImage 和技能使用的定义与转换器。主机决定要公开其中哪些工具。
仅公开特定部署所需的功能。README 未定义授权或沙箱策略,因此这些问题应由主机环境和操作执行层处理。
扩展 Harness
Unreal Agent 的组件旨在实现可组合。只要保留文档中规定的职责和不变量,就可以用其他实现替换由接口支持的组件。
实现工具转换器
自定义转换器应遵循以下顺序:
- 根据工具的架构验证模型生成的参数。
- 请求无效时返回验证错误。
- 请求有效时,创建一个或多个可序列化、带版本的操作描述。
- 返回引用已提交操作的状态。
- 提供格式化逻辑,将记录的状态和准备好的操作输出转换为面向模型的结果。
保持转换过程确定且快速。不要在转换器中发出网络请求、访问文件、等待子进程,或执行其他 I/O。
替换操作管理器
本地操作管理器可以替换。一个有文档记录的扩展是代理管理器:它会序列化操作,并将其发送给运行在远程沙箱进程中的另一个本地操作管理器。
这种设计使协调器和转换器专注于验证与持久化意图,同时允许在隔离环境中执行操作。
实现存储
替代会话存储必须保留可序列化性、版本控制、恢复行为,以及工具调用状态与生成操作之间的原子关系。
项目致力于维持会话的向后兼容性。如果不支持某个会话版本,恢复该会话必须以明确错误失败,而不能悄然误读数据。
高级提示
- 在调用方边界生成输入 ID。 将该 ID 与产生它的事件一同存储,以便重试和重新投递时保留相同的身份。
- 不要将收件箱去重与持久化历史混为一谈。 收件箱是不稳定且仅限会话范围的,而会话存储会持久化规范事件。
- 保持转换器纯粹且同步。 将请求转换为操作,而不是直接执行工作。
- 为每种操作格式设置版本。 操作的生命周期可能超过创建它们的进程,或跨越进程和沙箱边界。
- 保留原子提交。 如果只记录成功的工具调用状态而没有记录其操作,进程崩溃后可能会导致会话状态不一致。
- 独立跟踪转换和执行。 有效的调用可能生成已提交但尚未完成的操作。
- 使用上下文构建器元数据。 监控哪些内容被省略、截断或压缩,以便诊断模型行为。
- 集中处理提供商相关问题。 将凭据、取消操作和提供商错误保留在 LLM 适配器内部。
- 为实验创建会话分支。 分支可以探索不同的后续流程,同时保留源会话仅追加的历史记录。
- 使用代理操作管理器实现隔离。 序列化后的操作可以转发到远程沙箱内的运行时,而无需将同步转换移入其中。
重要不变量
扩展应保留以下保证:
- 会话存储项保持可序列化。
- 存储格式保持版本化。
- 不支持的会话版本会产生明确的恢复错误。
- 操作保持可序列化并具有版本信息。
- 上下文构建不执行 I/O,也不接受持久化依赖。
- 工具转换不执行 I/O,也绝不会挂起协调器的事件循环。
结论
Unreal Agent 为需要持久化会话、输入去重、协调 LLM 轮次、经过验证的工具调用以及持久化异步工作的代理提供了模块化基础。其核心设计原则是在同步转换与异步执行之间建立清晰边界。请从现有可执行程序入手,遵循文档记录的事件流,并在替换或扩展组件时保留序列化、版本控制和原子性。
