> ## Documentation Index
> Fetch the complete documentation index at: https://agno-v2-codex-docs-audit-20260719-0149.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# User Input

> Gather specific information from users during agent execution.

User input flows allow you to gather specific information from users during execution. This is useful for:

* Collecting required parameters
* Getting user preferences
* Gathering missing information

## How It Works

When you mark a tool with `@tool(requires_user_input=True)`, your agent will:

1. **Pause execution** before calling the tool
2. **Set `is_paused` to `True`** on the run response
3. **Populate `user_input_schema`** with the fields that need to be filled
4. **Wait for you** to provide the requested values
5. **Continue execution** once you call `continue_run()` with the filled values

The key difference from user confirmation is that here you provide *data* to fill in the tool's parameters. User confirmation only approves or rejects the tool call.

## Collecting Specific Fields

You can control which fields require user input using the `user_input_fields` parameter. Fields not in this list remain in the tool schema and may be filled by the agent from the conversation context.

In the example below, the agent pauses to collect the `to_address` parameter from the user for the `send_email` tool:

```python theme={null}
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


# Explicitly list fields that must be supplied 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}"


# A database is required to continue a run by run_id
agent = Agent(
    model=OpenAIResponses(id="gpt-5.2"),
    tools=[send_email],
    markdown=True,
    db=SqliteDb(db_file="tmp/example.db"),
)

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

# After resolving the run requirements, you can continue the run
run_response = agent.continue_run(run_id=run_response.run_id, requirements=run_response.requirements)
pprint.pprint_run_response(run_response)
```

In this example, the agent will fill in `subject` and `body` based on the user's request ("Hello" and "Hello, world!"), but will pause and ask the user for the `to_address` since it's in the `user_input_fields` list.

## Understanding UserInputField

The `RunOutput` object has a list of requirements. When a tool requires user input, you will find a requirement object with a `user_input_schema` field, populated with `UserInputField` objects:

```python theme={null}
class UserInputField:
    name: str  # The name of the field
    field_type: Type  # The required type of the field
    description: Optional[str] = None  # The description of the field
    value: Optional[Any] = None  # The value of the field. Populated by the agent or the user.
```

<Note>
  If `field.value` is already set (not `None`), it means the agent has pre-filled it from the conversation context. You can either use that value or override it with user input.

  The same `UserInputField` structure is used in [Dynamic User Input](/hitl/dynamic-user-input), where the agent dynamically creates these fields when it needs information.
</Note>

## Collecting All Fields

Omitting `user_input_fields` or passing an empty list leaves all parameters in the tool schema. It does not force the user to provide every field. To require user input for all parameters, list every field explicitly:

```python theme={null}
@tool(
    requires_user_input=True,
    user_input_fields=["subject", "body", "to_address"],
)
def send_email(subject: str, body: str, to_address: str) -> str:
    """Send an email."""
    return f"Sent email to {to_address} with subject {subject} and body {body}"
```

Listed fields are removed from the model-facing tool schema and remain available in `user_input_schema` for your application to fill before continuing the run.

## Handling Pre-Filled Values

When you specify `user_input_fields`, you're telling the agent which parameters the user should provide. The agent can fill in other parameters based on the conversation context.

For example, with `user_input_fields=["to_address"]` on a `send_email(subject, body, to_address)` function:

* **`subject` and `body`** (not in the list) → Agent can fill these from context, `value="Hello"` etc.
* **`to_address`** (in the list) → User must provide this, `value=None`

The `user_input_schema` will include all parameters, but you only need to collect values for fields where `value=None`:

```python theme={null}
# Explicitly list fields that must be supplied 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}"

agent = Agent(
    model=OpenAIResponses(id="gpt-5.2"),
    tools=[send_email],
    db=SqliteDb(db_file="tmp/example.db"),
)

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

        for field in input_schema:
            # Display field information to the user
            print(f"\nField: {field.name} ({field.field_type.__name__}) -> {field.description}")

            # Get user input (if the value is not set, it means the user needs to provide the value)
            if field.value is None:
                user_value = input(f"Please enter a value for {field.name}: ")
                field.value = user_value
            else:
                print(f"Value provided by the agent: {field.value}")

run_response = (
    agent.continue_run(run_id=run_response.run_id, requirements=run_response.requirements)
)
```

## Async Support

User input works with async agents. Use `arun()` and `acontinue_run()`:

```python theme={null}
run_response = await agent.arun("Send an email with the subject 'Hello'")

for requirement in run_response.active_requirements:
    if requirement.needs_user_input:
        for field in requirement.user_input_schema:
            if field.value is None:
                field.value = input(f"Please enter {field.name}: ")

response = await agent.acontinue_run(run_id=run_response.run_id, requirements=run_response.requirements)
```

<Note>
  [Dynamic User Input](/hitl/dynamic-user-input#async-support) also supports async patterns with the same methods.
</Note>

## Streaming Support

User input also works with streaming. The agent will emit events until it needs user input, then pause:

```python theme={null}
for run_event in agent.run("Send an email", stream=True):
    if run_event.is_paused:
        for tool in run_event.tools_requiring_user_input:
            for field in tool.user_input_schema:
                if field.value is None:
                    field.value = input(f"Please enter {field.name}: ")

# Continue streaming
response = agent.continue_run(
    run_id=run_event.run_id,
    updated_tools=run_event.tools,
    stream=True
)
```

<Warning>
  Remember that tools marked with `@tool(requires_user_input=True)` are mutually exclusive with `@tool(requires_confirmation=True)` and `@tool(external_execution=True)`.

  A tool can only use one of these patterns at a time.
</Warning>

## Usage Examples

<CardGroup cols={2}>
  <Card title="Basic User Input" icon="keyboard" href="/hitl/usage/user-input-required">
    Simple user input collection
  </Card>

  <Card title="All Fields Input" icon="list-check" href="/hitl/usage/user-input-required-all-fields">
    Collecting all tool parameters from user
  </Card>

  <Card title="Async User Input" icon="bolt" href="/hitl/usage/user-input-required-async">
    Using user input with async agents
  </Card>

  <Card title="Streaming User Input" icon="water" href="/hitl/usage/user-input-required-stream-async">
    User input with streaming responses
  </Card>
</CardGroup>
