Skip to content
Changelog

Workflow step content keeps 0 and False after a reload

ContributorKaustubh ShuklaSenior Software Engineer

October 27, 20261 min read

Agno's StepOutput.to_dict() now writes ints, floats, bools and strs as themselves, so a step that returned 0 reads back as 0 once the workflow session comes out of the database. Earlier releases saved that value as "0", and "0" is truthy, so a later step that branched on it went the other way after a reload.

The same serializer feeds a HITL resume by run_id, a later run reading step_results from the session, and the AgentOS workflow API, so all three now return the original type. We ran this workflow on SQLite and read the session back through a second Workflow object:

from agno.db.sqlite import SqliteDb
from agno.workflow import Step, Workflow
from agno.workflow.types import StepInput, StepOutput
 
def count_errors(step_input: StepInput) -> StepOutput:
    return StepOutput(content=0)
 
def needs_review(step_input: StepInput) -> StepOutput:
    return StepOutput(content=False)
 
steps = [Step(name="count_errors", executor=count_errors), Step(name="needs_review", executor=needs_review)]
Workflow(name="checks", db=SqliteDb(db_file="tmp/checks.db"), steps=steps).run(input="go", session_id="s1")
 
reloaded = Workflow(name="checks", db=SqliteDb(db_file="tmp/checks.db"), steps=steps)
for step in reloaded.get_session(session_id="s1").runs[-1].step_results:
    print(step.step_name, repr(step.content), bool(step.content))

Real output, earlier release and this release:

# Before
count_errors '0' True
needs_review 'False' True
 
# Now
count_errors 0 False
needs_review False False

Rows written by earlier releases keep their strings, because a stored "0" can't be told apart from a real string "0".

See the cookbook, and learn more about accessing previous steps in the documentation.

Frequently asked questions

StepOutput.to_dict() used to turn every value other than a dict, list or Pydantic model into a string. Both "0" and "False" are truthy, so a later step branching on them took the wrong branch. This release stores ints, floats, bools and strs as themselves.

Any path that serializes step results: resuming a paused HITL run by run_id, reading an earlier run through the workflow session, and the step_results the AgentOS workflow API returns.

No. A stored "0" looks the same as a real string "0", so rows written by earlier releases keep the strings they hold. New runs store the original types.

Values like datetimes or arbitrary objects still fall back to str(). Pydantic models still serialize to a dict.

Shipped around the same time