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:
- Pause execution before calling the tool
- Set
is_pausedtoTrueon the run response - Populate
user_input_schemawith the fields that need to be filled - Wait for you to provide the requested values
- 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:
1from typing import List23from kern.agent import Agent4from kern.models.openai import OpenAIResponses5from kern.tools import tool6from kern.tools.function import UserInputField7from kern.utils import pprint8910# You can either specify the user_input_fields or leave empty for all fields to be provided by the user11@tool(requires_user_input=True, user_input_fields=["to_address"])12def send_email(subject: str, body: str, to_address: str) -> str:13 """14 Send an email.1516 Args:17 subject (str): The subject of the email.18 body (str): The body of the email.19 to_address (str): The address to send the email to.20 """21 return f"Sent email to {to_address} with subject {subject} and body {body}"222324agent = Agent(25 model=OpenAIResponses(id="gpt-5.2"),26 tools=[send_email],27 markdown=True,28)2930run_response = agent.run(31 "Send an email with the subject 'Hello' and the body 'Hello, world!'"32)3334for requirement in run_response.active_requirements:35 if requirement.needs_user_input:36 input_schema: List[UserInputField] = requirement.user_input_schema # type: ignore3738 for field in input_schema:39 # Get user input for each field in the schema40 field_type = field.field_type41 field_description = field.description4243 # Display field information to the user44 print(f"\nField: {field.name}")45 print(f"Description: {field_description}")46 print(f"Type: {field_type}")4748 # Get user input49 if field.value is None:50 user_value = input(f"Please enter a value for {field.name}: ")51 else:52 print(f"Value: {field.value}")53 user_value = field.value5455 # Update the field value56 field.value = user_value5758# After resolving the run requirements, you can continue the run59run_response = agent.continue_run(run_id=run_response.run_id, requirements=run_response.requirements)60pprint.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:
1class UserInputField:2 name: str # The name of the field3 field_type: Type # The required type of the field4 description: Optional[str] = None # The description of the field5 value: Optional[Any] = None # The value of the field. Populated by the agent or the user.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, where the agent dynamically creates these fields when it needs information.
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:
1@tool(requires_user_input=True) # No user_input_fields means all fields need user input2def send_email(subject: str, body: str, to_address: str) -> str:3 """Send an email."""4 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:
subjectandbody(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:
1# You can either specify the user_input_fields or leave empty for all fields to be provided by the user2@tool(requires_user_input=True, user_input_fields=["to_address"])3def send_email(subject: str, body: str, to_address: str) -> str:4 """5 Send an email.67 Args:8 subject (str): The subject of the email.9 body (str): The body of the email.10 to_address (str): The address to send the email to.11 """12 return f"Sent email to {to_address} with subject {subject} and body {body}"1314agent = Agent(15 model=OpenAIResponses(id="gpt-5.2"),16 tools=[send_email],17)1819run_response = agent.run("Send an email with the subject 'Hello' and the body 'Hello, world!'")20for requirement in run_response.active_requirements:21 if requirement.needs_user_input:22 input_schema: List[UserInputField] = requirement.user_input_schema2324 for field in input_schema:25 # Display field information to the user26 print(f"\nField: {field.name} ({field.field_type.__name__}) -> {field.description}")2728 # Get user input (if the value is not set, it means the user needs to provide the value)29 if field.value is None:30 user_value = input(f"Please enter a value for {field.name}: ")31 field.value = user_value32 else:33 print(f"Value provided by the agent: {field.value}")3435run_response = (36 agent.continue_run(run_id=run_response.run_id, requirements=run_response.requirements)37)Async Support
User input works seamlessly with async agents. Just use arun() and acontinue_run():
1run_response = await agent.arun("Send an email with the subject 'Hello'")23for requirement in run_response.active_requirements:4 if requirement.needs_user_input:5 for field in requirement.user_input_schema:6 if field.value is None:7 field.value = input(f"Please enter {field.name}: ")89response = await agent.acontinue_run(run_id=run_response.run_id, requirements=run_response.requirements)Dynamic User Input also supports async patterns with the same methods.
Streaming Support
User input also works with streaming. The agent will emit events until it needs user input, then pause:
1for run_event in agent.run("Send an email", stream=True):2 if run_event.is_paused:3 for tool in run_event.tools_requiring_user_input:4 for field in tool.user_input_schema:5 if field.value is None:6 field.value = input(f"Please enter {field.name}: ")78# Continue streaming9response = agent.continue_run(10 run_id=run_event.run_id,11 updated_tools=run_event.tools,12 stream=True13)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.
Usage Examples
Basic User Input
Simple user input collection
All Fields Input
Collecting all tool parameters from user
Async User Input
Using user input with async agents
Streaming User Input
User input with streaming responses