主线:一次运行如何跑完 24 步管线(核心)
30 秒导读: 你调用
agent.do(task),Upsonic 内部把这一次运行拆成一条从上到下的线性管线—— 24 个小步骤(缓存检查、建 prompt、装工具、调模型、跑工具、存记忆……)依次执行。每一步都改写同一个 共享上 下文AgentRunOutput。真正"思考+动手"的活都挤在第 14 步ModelExecutionStep里;其余 23 步 是它的前置准备和善后。本章讲清这条管线怎么被驱动、怎么在中途暂停又原地续跑。
本章是全库最核心的一章。读完你应该能回答:一次 agent 运行,从 do() 到拿到结果,中间到底发生了
什么、按什么顺序、谁在指挥。上层的 Agent / Task 抽象见 01-agent-and-task.md;
模型怎么被调用见 03-model-layer.md;工具与 HITL 的细节见
04-tools-system.md;两个安全步骤见 05-safety-engine.md。
1. 先建立直觉:什么是"管线"
一次 agent 运行不是一个大函数,而是一串小步骤。 Upsonic 把运行拆成很多个独立的 Step,排成一条
队列,由一个"调度员"PipelineManager 从头到尾依次调用。
为什么要这么拆?三个好处,后面会一一兑现:
- 可观察 —— 每步有名字、有状态、有耗时,debug 时能看到"卡在哪一步"。
- 可中断可续跑 —— 需要等人确认时,记住"停在第几步",人回话后从那一步继续,不重头再来。
- 可组合 —— 普通调用、超时调用、流式调用只是换一份步骤清单,主循环不变。
一个生活化的类比:把它当成工厂流水线。原料(你的 Task)从传送带一头进去,依次经过 24 个工位
(每个工位就是一个 Step),每个工位在同一块"工单"(AgentRunOutput)上盖章、补信息,最后一头出来
就是成品(结果文本 / 结构化对象)。
三个最基础的概念
管线的地基是三个类型,都在 agent/pipeline/step.py:
| 概念 | 是什么 | 源码 |
|---|---|---|
Step | 一个工位的抽象基类。子类实现 execute() 干活 | agent/pipeline/step.py:91 Step |
StepResult | 一步跑完的收据:名字、序号、状态、耗时、消息 | agent/pipeline/step.py:59 StepResult |
StepStatus | 这一步的结局枚举:RUNNING/COMPLETED/PAUSED/CANCELLED/ERROR/SKIPPED | agent/pipeline/step.py:35 StepStatus |
StepStatus 有个细节值得记住:它能映射回运行级的状态 RunStatus,其中 SKIPPED 会被当成
completed(跳过 = 正常),而 PAUSED 会保留成暂停——这为后面的"暂停续跑"埋了伏笔
(agent/pipeline/step.py:44 StepStatus.to_run_status)。