The following example shows how to implement user confirmation with a custom tool:
from agno.tools import toolfrom agno.agent import Agentfrom agno.models.openai import OpenAIResponses@tool(requires_confirmation=True)def sensitive_operation(data: str) -> str: """Perform a sensitive operation that requires confirmation.""" # Implementation here return "Operation completed"agent = Agent( model=OpenAIResponses(id="gpt-5.2"), tools=[sensitive_operation],)# Run the agentrun_response = agent.run("Perform sensitive operation")# Handle confirmationfor requirement in run_response.active_requirements: if requirement.needs_confirmation: # Get user confirmation print(f"Tool {requirement.tool.tool_name}({requirement.tool.tool_args}) requires confirmation") confirmed = input(f"Confirm? (y/n): ").lower() == "y" requirement.confirmed = confirmed# After resolving the requirement, you can continue the run:response = agent.continue_run(run_id=run_response.run_id, requirements=run_response.requirements)
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:
from agno.agent import Agentfrom agno.models.openai import OpenAIResponsesfrom agno.tools import toolfrom agno.tools.yfinance import YFinanceToolsfrom agno.utils import pprintfrom rich.console import Consolefrom rich.prompt import Promptconsole = Console()agent = Agent( model=OpenAIResponses(id="gpt-5.2"), tools=[YFinanceTools(requires_confirmation_tools=["get_stock_price"])], markdown=True,)run_response = agent.run("Get the current stock price of Apple?")for requirement in run_response.active_requirements: if requirement.needs_confirmation: # Ask for confirmation console.print( f"Tool name [bold blue]{tool.tool_name}({tool.tool_args})[/] requires confirmation." ) message = ( Prompt.ask("Do you want to continue?", choices=["y", "n"], default="y") .strip() .lower() ) if message == "n": requirement.reject() else: # Update the tools in place requirement.confirm()response = agent.continue_run(run_id=run_response.run_id, requirements=run_response.requirements)pprint.pprint_run_response(run_response)
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:
if run_response.is_paused: for tool in run_response.tools_requiring_confirmation: print(f"Tool {tool.tool_name}({tool.tool_args}) requires confirmation") confirmed = input(f"Confirm? (y/n): ").lower() == "y" if confirmed: tool.confirmed = True else: tool.confirmed = False tool.confirmation_note = "This operation was rejected because it targets the wrong resource. Please use the alternative method." response = agent.continue_run(run_id=run_response.run_id, updated_tools=run_response.tools)
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:
from agno.agent import Agentfrom agno.models.openai import OpenAIResponsesfrom agno.tools import tooldef safe_operation() -> str: """This runs automatically without confirmation.""" return "Safe operation completed"@tool(requires_confirmation=True)def risky_operation() -> str: """This requires user confirmation.""" return "Risky operation completed"agent = Agent( model=OpenAIResponses(id="gpt-5.2"), tools=[safe_operation, risky_operation],)run_response = agent.run("Perform both operations")if run_response.is_paused: # Only the risky_operation will be in tools_requiring_confirmation for tool in run_response.tools_requiring_confirmation: # Handle confirmation... tool.confirmed = True response = agent.continue_run(run_id=run_response.run_id, updated_tools=run_response.tools)
User confirmation also works with streaming responses. The agent will pause mid-stream when it encounters a tool that requires confirmation:
for run_event in agent.run("Perform sensitive operation", stream=True): if run_event.is_paused: for tool in run_event.tools_requiring_confirmation: tool.confirmed = True # Continue streaming response = agent.continue_run( run_id=run_event.run_id, updated_tools=run_event.tools, stream=True )
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.