Skip to content

第 20 章 · Workflow 入门:Steps 步骤编排

本章目标:理解 Workflow 与 Team 的本质区别,学会用 Workflow + Step 把 Agent、Team 和普通函数编排成确定性的流水线。

20.1 为什么需要 Workflow

Team 是"模型主导"的:leader 临场决定派谁、派什么任务。这带来灵活性,也带来不确定性——同样的问题可能走出不同的执行路径。而很多业务流程恰恰不允许临场发挥

  • 内容生产:必须先调研、再撰写、后审校,顺序不能乱;
  • 数据处理:清洗 → 分析 → 报告,每步输入输出固定;
  • 合规场景:某些步骤必须无条件执行,不能由模型决定跳过。

Agno 官方对两者的定位是:

TeamWorkflow
控制权Leader 模型自主决策开发者用代码定义控制流
适用角色协作、任务分派确定性流程、结构化管道
原语mode / 委派 / 任务清单Step / Parallel / Condition / Loop / Router

20.2 你的第一个两步工作流:撰写 → 审校

Workflow 管理一次运行,steps 列表按顺序执行。每个 Step 包裹恰好一个执行器:Agent、Team、普通 Python 函数,甚至嵌套的 Workflow。

python
import os
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.workflow import Step, StepInput, StepOutput, Workflow

model = OpenAIChat(
    id="deepseek-chat",
    api_key=os.getenv("DEEPSEEK_API_KEY"),
    base_url="https://api.deepseek.com/v1",
)

writer = Agent(
    name="Writer",
    model=model,
    instructions=["根据给定主题写一篇 300 字以内的短文。"],
)

reviewer = Agent(
    name="Reviewer",
    model=model,
    instructions=[
        "审校上一步的文章:检查事实表述、语法和结构。",
        "直接输出修改后的最终版本。",
    ],
)

# 撰写 -> 审校,顺序由代码保证
workflow = Workflow(
    name="writing-pipeline",
    steps=[
        Step(name="draft", executor=writer),
        Step(name="review", executor=reviewer),
    ],
)

workflow.print_response(
    "主题:为什么自动化测试值得投入", markdown=True
)

运行时 draft 步骤的输出会自动成为 review 步骤的输入——这条数据流不需要你手动接线。

20.3 Step 执行器的三种形态

python
from agno.team import Team
from agno.workflow import Step, StepInput, StepOutput, Workflow


def data_preprocessor(step_input: StepInput) -> StepOutput:
    """函数执行器:做确定性加工,不消耗 token"""
    research = step_input.previous_step_content or "没有收到调研内容"
    return StepOutput(content=f"待分析的调研材料:\n{research}")


research_team = Team(name="Research Team", members=[...], model=model)

workflow = Workflow(
    name="mixed-pipeline",
    steps=[
        research_team,        # 形态一:直接放 Agent/Team(自动包装成 Step)
        data_preprocessor,    # 形态二:直接放函数
        Step(                 # 形态三:显式 Step 包装,推荐用于需要命名/描述的场景
            name="analysis",
            executor=writer,
            description="基于调研产出分析报告",
        ),
    ],
)

三种形态可以自由混用。给步骤命名(name=)不只是为了可读性:事件追踪和输出查找都以步骤名为键。

20.4 StepInput 与 StepOutput:步骤间的数据契约

函数执行器遵循一个标准签名——接收 StepInput,返回 StepOutput

python
def summarize(step_input: StepInput) -> StepOutput:
    # input:本次工作流的原始输入(始终保留)
    original = str(step_input.input)
    # previous_step_content:上一个步骤输出的正文
    prev = step_input.previous_step_content or ""
    # previous_step_outputs:若上游是并行块,可拿到各命名步骤的输出字典
    return StepOutput(
        content=f"原始需求: {original}\n\n材料摘要:\n{prev[:500]}",
    )

常用字段速查:

StepInput 字段含义
input工作流的原始用户输入
previous_step_content上一步骤输出的内容文本
previous_step_outputs上游各步骤输出的集合(并行聚合后尤其有用)
additional_data运行时附加的自定义数据

函数步骤的价值

在两个 Agent 之间插入纯函数步骤是 Workflow 最常用的模式:格式转换、长度截断、结果校验都不该烧 token,交给 Python 即可。

20.5 运行与解析输出

print_response() 适合调试;生产代码用 run() 拿到结构化结果:

python
result = workflow.run("主题:向量数据库选型")

# workflow_output.content 是最后一个步骤的输出
print(result.content)

# 更细粒度:逐步查看每个步骤的执行结果
for step_result in (result.step_results or []):
    print(step_result.step_name, "->", str(step_result.content)[:80])

也可以用 arun() 异步执行,或在 run(..., stream=True) 时迭代事件流观察每个步骤的开始与结束事件。

20.6 本章小结

  • Team = 模型主导的灵活协作;Workflow = 代码定义的确定性控制流;
  • Step 的执行器可以是 Agent、Team、函数或嵌套 Workflow,三者可在同一个 steps 列表混用;
  • 数据通过 StepInput.previous_step_content 自动向下游流动,StepOutput(content=...) 是函数步骤的标准出口;
  • 生产代码用 run() 并遍历 step_results 解析各步骤输出,而不是解析打印文本。

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. 关于 Agno 中 Team 和 Workflow 的分工,正确的是?

2. Workflow 中一个 Step 的合法执行器不包括以下哪种?

3. 函数步骤中想获取「上一个步骤的输出」,应该读取?

4. 为什么推荐在两个 LLM 步骤之间插入纯 Python 函数步骤?

🛠️ 动手实践

  1. 把第 18 章的研究团队作为第一个步骤接入本章的写作流水线,实现"调研→撰写→审校"三步。
  2. 在撰写和审校之间加一个函数步骤 word_limit,把超过 400 字的草稿截断并附提示。
  3. run() 跑通整条流水线,并打印每个 step_result 的名称与前 100 字符。

下一章解锁 Workflow 的全部控制流原语:并行、分支与循环