User Confirmation

Require explicit user approval before executing tool calls in your agents.

User confirmation allows you to pause execution and require explicit user approval before proceeding with tool calls. This is useful for:

  • Sensitive operations
  • API calls that modify data
  • Actions with significant consequences

How It Works

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

  1. Pause execution when the tool is about to be called
  2. Set is_paused to True on the run response
  3. Wait for you to review the tool call and decide whether to approve or reject it
  4. Continue execution once you call continue_run() with your decision

This gives you complete control over which tools execute and when, making it perfect for production scenarios where you need human oversight.

Basic Example

The following example shows how to implement user confirmation with a custom tool:

1from kern.tools import tool
2from kern.agent import Agent
3from kern.models.openai import OpenAIResponses
4
5@tool(requires_confirmation=True)
6def sensitive_operation(data: str) -> str:
7 """Perform a sensitive operation that requires confirmation."""
8 # Implementation here
9 return "Operation completed"
10
11agent = Agent(
12 model=OpenAIResponses(id="gpt-5.2"),
13 tools=[sensitive_operation],
14)
15
16# Run the agent
17run_response = agent.run("Perform sensitive operation")
18
19# Handle confirmation
20for requirement in run_response.active_requirements:
21 if requirement.needs_confirmation:
22 # Get user confirmation
23 print(f"Tool {requirement.tool.tool_name}({requirement.tool.tool_args}) requires confirmation")
24 confirmed = input(f"Confirm? (y/n): ").lower() == "y"
25 requirement.confirmed = confirmed
26
27# After resolving the requirement, you can continue the run:
28response = agent.continue_run(run_id=run_response.run_id, requirements=run_response.requirements)

Toolkit-Level Confirmation

You can also specify which specific tools in a toolkit require confirmation using the requires_confirmation_tools parameter. This is super useful when you want to protect only certain operations in a toolkit while allowing others to run freely:

1from kern.agent import Agent
2from kern.models.openai import OpenAIResponses
3from kern.tools import tool
4from kern.tools.yfinance import YFinanceTools
5from kern.utils import pprint
6from rich.console import Console
7from rich.prompt import Prompt
8
9console = Console()
10
11agent = Agent(
12 model=OpenAIResponses(id="gpt-5.2"),
13 tools=[YFinanceTools(requires_confirmation_tools=["get_stock_price"])],
14 markdown=True,
15)
16
17run_response = agent.run("Get the current stock price of Apple?")
18
19for requirement in run_response.active_requirements:
20 if requirement.needs_confirmation:
21 # Ask for confirmation
22 console.print(
23 f"Tool name [bold blue]{tool.tool_name}({tool.tool_args})[/] requires confirmation."
24 )
25 message = (
26 Prompt.ask("Do you want to continue?", choices=["y", "n"], default="y")
27 .strip()
28 .lower()
29 )
30
31 if message == "n":
32 requirement.reject()
33 else:
34 # Update the tools in place
35 requirement.confirm()
36
37response = agent.continue_run(run_id=run_response.run_id, requirements=run_response.requirements)
38pprint.pprint_run_response(run_response)

Providing Rejection Feedback

When rejecting a tool call, you can provide feedback to the agent using the confirmation_note property. This helps the agent understand why the operation was rejected and potentially choose a better approach:

1if run_response.is_paused:
2 for tool in run_response.tools_requiring_confirmation:
3 print(f"Tool {tool.tool_name}({tool.tool_args}) requires confirmation")
4 confirmed = input(f"Confirm? (y/n): ").lower() == "y"
5
6 if confirmed:
7 tool.confirmed = True
8 else:
9 tool.confirmed = False
10 tool.confirmation_note = "This operation was rejected because it targets the wrong resource. Please use the alternative method."
11
12 response = agent.continue_run(run_id=run_response.run_id, updated_tools=run_response.tools)

Mixed Tool Scenarios

You can mix tools that require confirmation with tools that don't. The agent will execute the non-confirmation tools automatically and only pause for those that need approval:

1from kern.agent import Agent
2from kern.models.openai import OpenAIResponses
3from kern.tools import tool
4
5def safe_operation() -> str:
6 """This runs automatically without confirmation."""
7 return "Safe operation completed"
8
9@tool(requires_confirmation=True)
10def risky_operation() -> str:
11 """This requires user confirmation."""
12 return "Risky operation completed"
13
14agent = Agent(
15 model=OpenAIResponses(id="gpt-5.2"),
16 tools=[safe_operation, risky_operation],
17)
18
19run_response = agent.run("Perform both operations")
20
21if run_response.is_paused:
22 # Only the risky_operation will be in tools_requiring_confirmation
23 for tool in run_response.tools_requiring_confirmation:
24 # Handle confirmation...
25 tool.confirmed = True
26
27 response = agent.continue_run(run_id=run_response.run_id, updated_tools=run_response.tools)

Async Support

User confirmation works seamlessly with async agents. Just use arun() and acontinue_run():

1run_response = await agent.arun("Perform sensitive operation")
2
3if run_response.is_paused:
4 for tool in run_response.tools_requiring_confirmation:
5 tool.confirmed = True
6
7 response = await agent.acontinue_run(run_response=run_response)

Streaming Support

User confirmation also works with streaming responses. The agent will pause mid-stream when it encounters a tool that requires confirmation:

1for run_event in agent.run("Perform sensitive operation", stream=True):
2 if run_event.is_paused:
3 for tool in run_event.tools_requiring_confirmation:
4 tool.confirmed = True
5
6 # Continue streaming
7 response = agent.continue_run(
8 run_id=run_event.run_id,
9 updated_tools=run_event.tools,
10 stream=True
11 )
Warning

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

A tool can only use one of these patterns at a time.

Usage Examples