Skip to main content
当一项任务必须按固定顺序经过几个里程碑、且每个里程碑都要验收后才能进入下一个时,开发者可以用 agentscope.sop 模块把它写成标准作业流程(Standard Operating Procedure,SOP)。流程只规定有哪些步骤、各步要证明什么,至于每一步怎么完成,交给执行它的智能体自己决定。 该模块由以下几部分组成: 与目标流水线相比,SOP 由多个有序的里程碑组成,每个里程碑有各自的验证者与重试次数,并且运行状态可以落盘,隔多久都能接着跑。
SOP 模块处于实验阶段,接口可能在后续版本调整。
判断一件事该不该写成 SOP,可以先问两个问题:不运行它,能否说清一共几步、每步由谁完成?如果不能,它不是 SOP。某一步完成时真的有人检查吗?如果没有,它不该单独成为一步。

定义流程

以下示例定义一个两步流程:先写出大纲并由审稿智能体验收,再按大纲写正文:
sop_quickstart.py
SOPStep 的构造参数如下: 执行者与验证者只要满足 AgentLike 协议即可,Agent 天然满足。同一个智能体用在多个步骤里时,它的上下文在这些步骤间是连续的;各步使用不同的智能体,上下文就互相独立。
验收是验证者的职责,不要单独写成一步。某一步被驳回时,重做的是这一步自己:如果把「检查大纲」写成独立步骤,驳回后重跑的只是检查本身,得出的结论不会变,直到次数用尽。

推进步骤

引擎按顺序逐步推进,已完成的步骤会被跳过。每一步的一次尝试分为执行与验收两半:
1

执行者工作

执行者收到步骤说明与上一步的交接内容,完成后以结构化输出交出 handover,即交给后续步骤的说明。
2

验证者验收

验证者看到步骤说明、这一步收到的输入以及执行者的交付,以结构化输出给出 passed 与 message。
3

通过则进入下一步

通过后这一步标记为完成,它的交付成为下一步的输入。
4

驳回则重做

驳回后交付被清空,message 连同当前是第几次尝试一起交给执行者重做。驳回次数达到 max_attempts 时,这一步与整个运行都标记为失败。
步骤之间只传递交付内容,不传递文件或对话。第一步收到运行的输入,之后每一步收到的是上一步的交付,包在 <handover from="上一步名称"> 标签里。因此执行者写交付时,要假设后续步骤没有看过它的任何工作过程。 以下情况也会被记为一次驳回,同样消耗 max_attempts: 运行过程中,引擎在每次尝试前后各产出一个 CustomEvent,便于开发者展示进度:

查看运行阶段

步骤与整个运行共用同一组阶段 SOPPhase: 整个运行的阶段由各步骤的阶段推算得出,规则依次为:全部未开始时为 PENDING,任一步失败即为 FAILED,全部完成为 COMPLETED,任一步挂起为 AWAITING,其余情况为 RUNNING。通过 engine.phase 或 engine.state.phase 可以读取。

挂起与恢复

执行者或验证者停在工具授权或外部执行上时,这一步进入 AWAITING,reply_stream 随即结束,不占用协程,也不持有任何锁。开发者拿到答复后再调用一次 reply_stream 即可继续:
挂起后恢复
reply_stream 接受的输入如下:

持久化运行状态

SOPRunState 是一个 Pydantic 模型,包含运行的输入、每一步的阶段、交付与历次结论。开发者可以把它存下来,在之后任意时间、甚至另一个进程里重建引擎继续运行:
保存与恢复运行状态
SOPRunState 只包含流程自己的状态。执行者与验证者作为 Agent 各自持有上下文,需要开发者按智能体自己的方式另行保存与恢复,再用它们构造 SOP 交给引擎。流程在保存之后若增删了步骤,步骤数与状态对不上,SOPEngine 会抛出 ValueError。

自定义步骤

当一个步骤不是「一人执行、一人验收」的形态时,开发者可以继承 SOPStepBase 并实现 reply_stream。引擎从不查看步骤内部,只要求一次调用就是一次尝试,并且这次尝试要么挂起,要么在传入的状态上记下结论:
自定义步骤
SOPStepBase 提供以下接口:

在终端中调试

SOPEngine 满足流水线的 PipelineProtocol,可以像智能体一样直接交给终端界面运行,工具授权与中断都由界面处理:
在终端中运行 SOP

延伸阅读

SOP 服务

在智能体服务中存储流程、发起运行,并由人工在线验收。

目标流水线

只有一个目标时,用执行者与验证者的循环逼近它。