> ## Documentation Index
> Fetch the complete documentation index at: https://agno-v2-agui.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're actually providing *data* to fill in the tool's parameters, not just approving or rejecting 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 will be filled by the agent automatically based on 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.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 or 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}"


agent = Agent(
    model=OpenAIResponses(id="gpt-5.2"),
    tools=[send_email],
    markdown=True,
)

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

If you want the user to provide *all* fields instead of letting the agent fill some automatically, simply omit the `user_input_fields` parameter or pass an empty list:

```python theme={null}
@tool(requires_user_input=True)  # No user_input_fields means all fields need user input
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}"
```

This is useful when you want complete control over the data being passed to sensitive operations, or when you don't trust the LLM to extract the right values from context.

## Handling Pre-Filled Values

When you specify `user_input_fields`, you're telling the agent which parameters the user should provide. The agent will automatically fill in the 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 fills 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}
# You can either specify the user_input_fields or 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}"

agent = Agent(
    model=OpenAIResponses(id="gpt-5.2"),
    tools=[send_email],
)

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 seamlessly with async agents. Just 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>

## Developer Resources
