Agno's UserInputField.to_dict() now writes a requires_user_input parameter typed as a PEP 604 union, such as quantity: int | None, as the string "int | None". The method used to read the type's __name__, which a union lacks, and it runs while Agno saves a paused run, so the save is what broke.
The old failure was quiet. The run paused and the caller got a normal RunOutput with status paused. The database write raised, Agno logged a warning, and the run never reached the runs table, so resuming by ID raised RunNotFoundError.
We ran the same script on both releases with a SQLite database and a scripted stand-in model, copied from the release's own test, that calls the tool once and then replies:
@tool(requires_user_input=True, user_input_fields=["quantity"])
def place_order(item: str, quantity: int | None = None) -> str:
return f"Ordered {quantity} x {item}"
agent = Agent(
model=ScriptedModel(...), # stand-in: calls place_order(item="widget"), then says "Order placed."
tools=[place_order],
db=SqliteDb(db_file="orders.db"),
)
paused = agent.run("Order a widget.", session_id="orders")
# The caller fills quantity = 3 on paused.active_requirements, then resumes by ID
resumed = agent.continue_run(run_id=paused.run_id, session_id="orders", requirements=paused.requirements)# Before (real output)
WARNING Error upserting run into db: 'types.UnionType' object has no attribute '__name__'
status: RunStatus.paused
saved in db: False
RunNotFoundError: No runs found for run ID c07d5283-2a5f-4de2-bab4-666bb613058b
# Now (real output)
status: RunStatus.paused
saved in db: True
resumed: RunStatus.completed | Ordered 3 x widget | Order placed.The string fallback also changes the field_type label for parameterized types. A list[str] parameter now reads "list[str]" and Optional[int] reads "typing.Optional[int]". The label is descriptive only, and the resumed tool call takes the value the caller supplied.
See the cookbook, and learn more about UserInputField in the documentation.
Frequently asked questions
In earlier releases, a requires_user_input tool with a parameter typed as a PEP 604 union such as int | None broke the database write for the paused run. Agno logged a warning, the run stayed out of the runs table, and resuming by ID found nothing. This release saves the run and the resume completes.
It returns the type as a string, so int | None becomes "int | None". Plain classes still serialize by name, such as "int".
Yes. A list[str] parameter now serializes as "list[str]" and Optional[int] as "typing.Optional[int]". Earlier releases wrote "list" and "Optional". Agno does not validate the resumed value against this label.




