Skip to content
Changelog

Files made inside Parallel, Steps, Loop, Condition and Router reach the next step

October 19, 20261 min read

Agno's Parallel now collects the File objects its branches return and hands them to the step after it and to workflow_run_response.files. Inside Steps, Loop, Condition and Router, each inner step now receives the files the steps before it produced in step_input.files.

Earlier releases carried images, video and audio through all five containers and dropped files. A pipeline that wrote a CSV in one branch of a Parallel and summarized it in the next step got an empty list, and so did a Loop whose second step was meant to check the first step's output.

We ran the same workflows on both releases with plain Python function steps and no model. One step returns report.csv and the step after it prints what it received:

from agno.media import File
from agno.workflow import Loop, Parallel, Step, Workflow
from agno.workflow.types import StepInput, StepOutput
 
def write_report(step_input: StepInput) -> StepOutput:
    return StepOutput(
        content="report written",
        files=[File(content=b"q3 numbers", filename="report.csv", mime_type="text/csv")],
    )
 
def other(step_input: StepInput) -> StepOutput:
    return StepOutput(content="other branch done")
 
def read_files(step_input: StepInput) -> StepOutput:
    return StepOutput(content=f"files={[f.filename for f in (step_input.files or [])]}")
 
write = Step(name="write_report", executor=write_report)
read = Step(name="read_files", executor=read_files)
 
Workflow(steps=[Parallel(write, Step(name="other", executor=other)), read])
Workflow(steps=[Loop(steps=[write, read], max_iterations=1)])  # same shape for Steps, Condition and Router
# earlier releases
Parallel  read_files saw files=[] | run files=[]
Steps     read_files saw files=[]
Loop      read_files saw files=[]
Condition read_files saw files=[]
Router    read_files saw files=[]
 
# this release
Parallel  read_files saw files=['report.csv'] | run files=['report.csv']
Steps     read_files saw files=['report.csv']
Loop      read_files saw files=['report.csv']
Condition read_files saw files=['report.csv']
Router    read_files saw files=['report.csv']

For Steps, Loop, Condition and Router, read_files ran as the second step inside the container.

See the cookbook, and learn more about advanced workflow patterns in the documentation.

Frequently asked questions

Parallel merged the images, video and audio of its branches but skipped their files, so a File returned by a branch disappeared. Agno now merges files too, and they reach the step after the Parallel and the run response.

Yes. Each of these containers hands step_input.files from one inner step to the next, alongside images, video and audio, and keeps any files that were already on the input.

No. A plain Python function step can return StepOutput(files=[File(...)]), and the following step reads them from step_input.files.

Shipped around the same time