> ## Documentation Index
> Fetch the complete documentation index at: https://docs.narada.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# prompt_for_user_input

> Prompt the user for workflow variable values in the Narada browser UI

The `prompt_for_user_input` method shows a form in the Narada browser UI and waits for the user to provide values for one or more workflow variables.

Use this when a Python agent needs structured input before it can continue.

<Note>
  For a higher-level guide covering both human-in-the-loop methods, see [Human-in-the-Loop Steps](/documentation/human-in-the-loop).
</Note>

## Method Signature

```python theme={null}
async def prompt_for_user_input(
    self,
    *,
    step_id: str,
    variables: list[PromptForUserInputVariable],
    prompt_message: str | None = None,
    timeout: int | None = 300,
) -> dict[str, Any]
```

## Parameters

<ParamField query="step_id" type="str" required>
  A stable identifier for this prompt step.

  ```python theme={null}
  step_id="collect-report-filters"
  ```
</ParamField>

<ParamField query="variables" type="list[PromptForUserInputVariable]" required>
  The variables to ask the user to fill. Each variable has:

  * `name`: variable name
  * `type`: one of `string`, `number`, `boolean`, `enum`, `dataTable`, `object`, or `array`
  * `required`: whether the user must provide a value
  * `enum_values`: allowed values for `enum` variables

  ```python theme={null}
  variables=[
      {"name": "region", "type": "enum", "required": True, "enum_values": ["west", "east"]},
      {"name": "max_accounts", "type": "number", "required": True},
      {"name": "notes", "type": "string", "required": False},
  ]
  ```
</ParamField>

<ParamField query="prompt_message" type="str | None" default="None">
  Text to show above the generated input fields. Use this to explain what the user should enter in plain language.

  ```python theme={null}
  prompt_message="Enter the Jira project where the requirements are located."
  ```
</ParamField>

<ParamField query="timeout" type="int | None" default="300">
  Maximum time in seconds to wait for the user response. The default is 300 seconds, and the maximum is 3600 seconds.
</ParamField>

## Return Value

Returns a dictionary keyed by variable name:

```python theme={null}
{
    "region": "west",
    "max_accounts": 25,
}
```

Optional variables may be omitted if the user leaves them blank. If the interaction is cancelled or aborted, the method raises `UserAbortedError`.

For `dataTable` variables, returned values use the canonical table shape:

```python theme={null}
{
    "columnNames": ["Name", "Email"],
    "rows": [
        ["Ada Lovelace", "ada@example.com"],
        ["Grace Hopper", "grace@example.com"],
    ],
}
```

## Example

```python theme={null}
import asyncio

from narada import Agent, BrowserEnvironment, UserAbortedError

async def main():
    env = BrowserEnvironment()
    agent = Agent(environment=env)

    try:
        try:
            values = await agent.prompt_for_user_input(
                step_id="collect-search-options",
                variables=[
                    {"name": "search_query", "type": "string", "required": True},
                    {"name": "max_results", "type": "number", "required": True},
                    {
                        "name": "source",
                        "type": "enum",
                        "required": False,
                        "enum_values": ["web", "crm", "docs"],
                    },
                ],
                prompt_message="Choose what to search for and how many results to return.",
                timeout=300,
            )
        except UserAbortedError:
            print("The prompt was cancelled.")
            return

        response = await agent.run(
            prompt=(
                f"Search {values.get('source', 'web')} for "
                f"{values['search_query']} and return the top {values['max_results']} results."
            )
        )
        print(response.text)
    finally:
        await env.close()

if __name__ == "__main__":
    asyncio.run(main())
```
