Skip to main content
高级/兼容程序化示例。此页代码片段仅作机制说明;HostEnv 或 workspace 不提供隔离。新项目先按 Quickstart 使用 Session 与明确资源配置。
Engine 是 QitOS 所有智能体工作流共享的执行内核(kernel)。它运行步骤循环,协调 AgentModule 的钩子,分发工具调用,执行评估器,检查停止条件,并写出追踪记录产物。只有当你需要比 agent.run() 更细粒度的控制时,才会直接和它交互。
QitOS 强制遵守单内核规则:一次运行只有一个 Engine。解析器、评估器、记忆适配器、工具集等扩展都挂接在这条主流水线上,而不是再引入第二个执行循环。

循环是如何工作的

每一步都遵循固定顺序:
  1. prepare:agent.prepare(state) 把状态格式化成模型可直接消费的提示词文本。
  2. decide:先调用 agent.decide(state, observation);若返回 None,再走 Engine 的默认模型调用路径。
  3. act:把 Decision.actions 中的工具调用交给 ToolRegistry 执行。
  4. reduce:agent.reduce(state, observation, decision) 用新的观测结果更新状态。
  5. 评估器:所有已注册的 Critic 在此步后评估当前结果,必要时可停止或重试。
  6. check_stop:检查预算、FinalResultCriteria、agent.should_stop() 以及自定义 StopCriteria。
  7. 追踪记录:把本步的步骤记录与运行时事件写入 TraceWriter。

构造函数

示意片段(非独立程序;完整执行文件见本页链接)。
单次运行的普通场景优先用 agent.run()。当你需要跨多次任务复用同一个 Engine,或在运行间动态调整钩子时,再直接使用 Engine。

Docker 环境路径与变量

DockerEnv(container_env={...}) 会在创建容器时传入显式环境变量映射。相对文件路径基于容器 workdir 解析;绝对路径表示容器内的绝对路径。QitOS 不会隐式复制 benchmark 或任务专属的宿主机环境变量。

协议解析

Engine 在每次运行中按照以下优先级解析模型协议:
  1. 直接传给 Engine 的 protocol。
  2. agent.model_protocol。
  3. 从 Engine 或 Agent parser 推断的协议。
  4. agent.llm.qitos_protocol,然后是 agent.llm.qitos_harness_metadata["protocol"]。
  5. 根据模型名称推断的协议。
  6. 框架默认协议 react_text_v1。
第 4 步中的模型声明由 build_model_for_preset(...) 写入。因此,即使服务商使用了 QitOS 无法从名称识别的模型别名,直接调用 Engine(agent=agent) 也会保留显式选择的 family preset。无法识别的模型级协议声明会被忽略,原有的模型名称推断和框架默认回退仍然有效。选择这些声明时,trace 会将解析来源记录为 model_qitos_protocol 或 model_harness_metadata。

空模型响应

模型调用完成后,Engine 会先记录规范化响应,并优先让 AgentModule.interpret_model_response() 将其解释为决策。如果该钩子返回 None,且响应既没有非空白文本也没有工具调用,Engine 会在进入 parser 之前将其归类为 model_error。默认恢复路径会重试一次;若连续第二次仍为空,运行会以 unrecoverable_error 停止,而不是继续生成 parser wait 并消耗剩余步数预算。 model_output 事件和 StepRecord.model_response 仍会保留响应的 finish_reason、usage、model 与 provider 字段。该防护不会改变原生工具调用响应、显式 Decision.wait,也不会改变对非空但格式错误输出的 parser feedback 行为。

Engine.run(task)

示意片段(非独立程序;完整执行文件见本页链接)。
它接受普通字符串任务,也接受结构化 Task 对象,返回一个 EngineResult。 当传入 Task 时,Engine 会读取 task.budget 并覆盖自身默认预算,同时自动管理资源预检、环境重置/观测/关闭等生命周期。

EngineResult

示意片段(非独立程序;完整执行文件见本页链接)。
常见用法: 示意片段(非独立程序;完整执行文件见本页链接)。

钩子

钩子用于在不修改 Engine 内部逻辑的前提下观察或响应生命周期事件。它们通常实现 EngineHook,在 on_before_step 与 on_after_step 等边界被调用。 示意片段(非独立程序;完整执行文件见本页链接)。
你也可以在构造时通过 hooks 传入,或在 agent.run(hooks=[...]) 中动态附加。

预算耗尽

当步数、墙钟时间或令牌预算耗尽时,Engine 会把 state.stop_reason 设置为对应值,并写出 END 事件。运行会优雅结束,仍然返回 EngineResult,你可以通过检查 state.stop_reason 判断是否发生了预算耗尽。 示意片段(非独立程序;完整执行文件见本页链接)。

从 AgentModule 构建 Engine

AgentModule.build_engine() 是一个便捷工厂,会创建一个和当前智能体绑定好的 Engine: 示意片段(非独立程序;完整执行文件见本页链接)。
这与直接写 Engine(agent=agent, ...) 等价,也是 agent.run() 在内部采用的路径。

AsyncEngine

AsyncEngine 提供非阻塞的智能体执行能力。它封装了同样的 Engine 循环,但把阻塞调用放到线程池中执行,因此在 asyncio 事件循环中使用是安全的。 示意片段(非独立程序;完整执行文件见本页链接)。

AsyncEngine.arun(task)

异步运行智能体循环,返回与 Engine.run() 相同的 EngineResult。 示意片段(非独立程序;完整执行文件见本页链接)。

AsyncEngine.arun_stream(task)

异步运行智能体循环,并在事件发生时产出结构化的 EngineEvent 对象——非常适合实时 UI 更新或将进度流式推送给客户端。 示意片段(非独立程序;完整执行文件见本页链接)。
事件在步骤边界(step_start、step_end)、阶段切换(decide、act、reduce、critic、check_stop)和多智能体事件(handoff、delegate、fanout)时产出。流总是以 run_start 开始、以 run_end 结束。

EngineEvent

示意片段(非独立程序;完整执行文件见本页链接)。

EventStream

EventStream 是支撑 arun_stream() 的异步队列。你也可以独立使用它,将事件扇出到多个消费者: 示意片段(非独立程序;完整执行文件见本页链接)。

异步模型

当配置的模型实现了 acall()(来自 AsyncModel)时,AsyncEngine 可以在不阻塞事件循环的情况下调用它。内置的异步模型适配器: 示意片段(非独立程序;完整执行文件见本页链接)。
AsyncEngine.arun() 与任何模型都兼容——同步模型会自动调度到线程池。当你需要真正的非阻塞 I/O(例如在高并发 Web 服务器中)时,才需要使用异步模型适配器。