User Input Required
Mark a tool with requires_user_input so the run pauses to collect the to_address field.
"""
User Input Required
=============================
Human-in-the-Loop: Allowing users to provide input externally.
"""
from typing import List
from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.models.openai import OpenAIResponses
from agno.tools import tool
from agno.tools.function import UserInputField
from agno.utils import pprint
# You can either specify the user_input_fields leave empty for all fields to be provided by the user
@tool(requires_user_input=True, user_input_fields=["to_address"])
def send_email(subject: str, body: str, to_address: str) -> str:
"""
Send an email.
Args:
subject (str): The subject of the email.
body (str): The body of the email.
to_address (str): The address to send the email to.
"""
return f"Sent email to {to_address} with subject {subject} and body {body}"
# ---------------------------------------------------------------------------
# Create Agent
# ---------------------------------------------------------------------------
agent = Agent(
model=OpenAIResponses(id="gpt-5-mini"),
tools=[send_email],
markdown=True,
db=SqliteDb(db_file="tmp/user_input_required.db"),
)
# ---------------------------------------------------------------------------
# Run Agent
# ---------------------------------------------------------------------------
if __name__ == "__main__":
run_response = agent.run(
"Send an email with the subject 'Hello' and the body 'Hello, world!'"
)
for requirement in run_response.active_requirements:
if requirement.needs_user_input:
input_schema: List[UserInputField] = requirement.user_input_schema # type: ignore
for field in input_schema:
# Get user input for each field in the schema
field_type = field.field_type
field_description = field.description
# Display field information to the user
print(f"\nField: {field.name}")
print(f"Description: {field_description}")
print(f"Type: {field_type}")
# Get user input
if field.value is None:
user_value = input(f"Please enter a value for {field.name}: ")
else:
print(f"Value: {field.value}")
user_value = field.value
# Update the field value
field.value = user_value
run_response = agent.continue_run(
run_id=run_response.run_id,
requirements=run_response.requirements,
) # or agent.continue_run(run_response=run_response)
pprint.pprint_run_response(run_response)
# Or for simple debug flow
# agent.print_response("Send an email with the subject 'Hello' and the body 'Hello, world!'")Continue only a paused run
After handling the requirements, replace the final continue_run() and printing block with the following. If the model answers without requesting a tool, print that completed response; continuing it would fork another run.
if run_response.is_paused:
run_response = agent.continue_run(
run_id=run_response.run_id,
requirements=run_response.requirements,
)
pprint.pprint_run_response(run_response)A continuation can pause again. Applications should inspect each returned status and resolve any new requirements before continuing.
Run the Example
Set up your virtual environment
uv venv --python 3.12
source .venv/bin/activateInstall dependencies
uv pip install -U agno openai sqlalchemyExport your OpenAI API key
export OPENAI_API_KEY="your_openai_api_key_here"Run the example
Save the code above as user_input_required.py, then run:
python user_input_required.pyFull source: cookbook/02_agents/10_human_in_the_loop/user_input_required.py