How to Add User Confirmation to Tool Call Requests#

python-icon Download Python Script

Python script/notebook for this guide.

User Confirmation how-to script

Prerequisites

This guide assumes familiarity with:

WayFlow Agents can be equipped with Tools to enhance their capabilities. However, end users may want to confirm or deny tool call requests emitted from the agent.

This guide shows you how to achieve this with the ServerTool. You can also do this using a ClientTool

Basic implementation#

In this example, you will build a simple Agent equipped with three tools:

  • A tool to add numbers

  • A tool to subtract numbers

  • A tool to multiply numbers

This guide requires the use of an LLM. WayFlow supports several LLM API providers. Select an LLM from the options below:

from wayflowcore.models import OCIGenAIModel

if __name__ == "__main__":

    llm = OCIGenAIModel(
        model_id="provider.model-id",
        service_endpoint="https://url-to-service-endpoint.com",
        compartment_id="compartment-id",
        auth_type="API_KEY",
    )

To learn more about the different LLM providers, read the guide on How to Use LLMs from Different Providers. The sample LLM used for this guide is defined as follows:

from wayflowcore.models import VllmModel

llm = VllmModel(
    model_id="model-id",
    host_port="VLLM_HOST_PORT",
)

Creating the tools#

Sometimes you will want to ask for user confirmation before executing certain tools. You can do this by using a ServerTool with the flag requires_confirmation set to True. This will raise a ToolExecutionConfirmationStatus whenever the Agent tries to execute the tool. We set the multiply_numbers tool to not require confirmation to highlight the differences. Note that the requires_confirmation flag can be used for any WayFlow tool.

from wayflowcore.tools.toolhelpers import tool
from wayflowcore.executors.executionstatus import ToolExecutionConfirmationStatus

@tool(requires_confirmation=True, description_mode="only_docstring")
def add_numbers_tool(number1: float, number2:  float) -> float:
    "Add two numbers"
    return number1 + number2

@tool(requires_confirmation=True, description_mode="only_docstring")
def subtract_numbers_tool(number1: float, number2:  float) -> float:
    "Subtract two numbers"
    return number1 - number2

@tool(requires_confirmation=False, description_mode="only_docstring")
def multiply_numbers_tool(number1: float, number2:  float) -> float:
    "Multiply two numbers"
    return number1 * number2

Creating the user-side execution logic#

To enable users to accept or deny tool call requests, you add simple validation logic before executing the tools requested by the agent.

def handle_tool_execution_confirmation(
    status: ToolExecutionConfirmationStatus
) -> None:
    for tool_request in status.tool_requests:
        if tool_request.name == "add_numbers":
            status.confirm_tool_execution(tool_request = tool_request)
        elif tool_request.name == "subtract_numbers":
            status.reject_tool_execution(tool_request = tool_request, reason = "The given numbers could not be subtracted as the tool is not currently functional")
        elif tool_request.name == "multiply_numbers":
            raise ValueError(f"Tool name {tool_request.name} should not raise a ToolExecutionConfirmationStatus as it does not require confirmation")
        else:
            raise ValueError(f"Tool name {tool_request.name} is not recognized")

Here, you simply loop until the user answers whether to accept the tool request or reject it. You can accept the tool request by using the status.confirm_tool_execution method. While accepting, you need to specify the specific tool request and you also have the option to add modified_args in this method to change the arguments of the called tool. Similarly, for rejection you can use the status.reject_tool_execution with an optional reason so that the Agent can take the reason into account while planning the next action to take.

Creating the agent#

Finally, you create a simple Agent to test the execution code written in the previous section.

from wayflowcore.agent import Agent

assistant = Agent(
    llm=llm,
    tools=[add_numbers_tool, subtract_numbers_tool, multiply_numbers_tool],
    custom_instruction="Use the tools at your disposal to answer the user requests.",
)

Running the agent in an execution loop#

Now, you create a simple execution loop to test the agent. In this loop, you can input the instructions you want the agent to execute and test it out for yourself!

from wayflowcore.executors.executionstatus import (
    FinishedStatus, UserMessageRequestStatus
)

def run_agent_in_command_line(assistant: Agent) -> None:
    conversation_inputs = {}
    conversation = assistant.start_conversation(inputs=conversation_inputs)

    while True:
        status = conversation.execute()
        assistant_reply = conversation.get_last_message()
        if assistant_reply:
            print(f"Assistant>>> {assistant_reply.content}\n")
        if isinstance(status, FinishedStatus):
            print(f"Finished assistant execution. Output values:\n{status.output_values}",)
            break
        elif isinstance(status, UserMessageRequestStatus):
            user_input = input("User>>> ")
            print("\n")
            conversation.append_user_message(user_input)
        elif isinstance(status, ToolExecutionConfirmationStatus):
            handle_tool_execution_confirmation(status)

        else:
            raise ValueError(f"Unsupported execution status: '{status}'")

# run_agent_in_command_line(assistant)
# ^ uncomment and execute

Recap#

In this guide, you learned how to support user-side confirmation for tool call requests by using ServerTool.

Next steps#

Having learned how to add user confirmation for tool calls, you may now proceed to:

Full code#

Click on the card at the top of this page to download the full code for this guide or copy the code below.

  1# Copyright © 2025 Oracle and/or its affiliates.
  2#
  3# This software is under the Apache License 2.0
  4# %%[markdown]
  5# Code Example - How to Add User Confirmation
  6# -------------------------------------------
  7
  8# How to use:
  9# Create a new Python virtual environment and install the latest WayFlow version.
 10# ```bash
 11# python -m venv venv-wayflowcore
 12# source venv-wayflowcore/bin/activate
 13# pip install --upgrade pip
 14# pip install "wayflowcore==26.1" 
 15# ```
 16
 17# You can now run the script
 18# 1. As a Python file:
 19# ```bash
 20# python howto_userconfirmation.py
 21# ```
 22# 2. As a Notebook (in VSCode):
 23# When viewing the file,
 24#  - press the keys Ctrl + Enter to run the selected cell
 25#  - or Shift + Enter to run the selected cell and move to the cell below# (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or Universal Permissive License
 26# (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl), at your option.
 27
 28
 29
 30# %%[markdown]
 31##Configure LLM
 32
 33# %%
 34from wayflowcore.models import VllmModel
 35
 36llm = VllmModel(
 37    model_id="model-id",
 38    host_port="VLLM_HOST_PORT",
 39)
 40
 41
 42
 43# %%[markdown]
 44##Create tools
 45
 46# %%
 47from wayflowcore.tools.toolhelpers import tool
 48from wayflowcore.executors.executionstatus import ToolExecutionConfirmationStatus
 49
 50@tool(requires_confirmation=True, description_mode="only_docstring")
 51def add_numbers_tool(number1: float, number2:  float) -> float:
 52    "Add two numbers"
 53    return number1 + number2
 54
 55@tool(requires_confirmation=True, description_mode="only_docstring")
 56def subtract_numbers_tool(number1: float, number2:  float) -> float:
 57    "Subtract two numbers"
 58    return number1 - number2
 59
 60@tool(requires_confirmation=False, description_mode="only_docstring")
 61def multiply_numbers_tool(number1: float, number2:  float) -> float:
 62    "Multiply two numbers"
 63    return number1 * number2
 64
 65
 66# %%[markdown]
 67##Create tool execution
 68
 69# %%
 70def handle_tool_execution_confirmation(
 71    status: ToolExecutionConfirmationStatus
 72) -> None:
 73    for tool_request in status.tool_requests:
 74        if tool_request.name == "add_numbers":
 75            status.confirm_tool_execution(tool_request = tool_request)
 76        elif tool_request.name == "subtract_numbers":
 77            status.reject_tool_execution(tool_request = tool_request, reason = "The given numbers could not be subtracted as the tool is not currently functional")
 78        elif tool_request.name == "multiply_numbers":
 79            raise ValueError(f"Tool name {tool_request.name} should not raise a ToolExecutionConfirmationStatus as it does not require confirmation")
 80        else:
 81            raise ValueError(f"Tool name {tool_request.name} is not recognized")
 82
 83
 84
 85# %%[markdown]
 86##Create agent
 87
 88# %%
 89from wayflowcore.agent import Agent
 90
 91assistant = Agent(
 92    llm=llm,
 93    tools=[add_numbers_tool, subtract_numbers_tool, multiply_numbers_tool],
 94    custom_instruction="Use the tools at your disposal to answer the user requests.",
 95)
 96
 97
 98# %%[markdown]
 99##Run tool loop
100
101# %%
102from wayflowcore.executors.executionstatus import (
103    FinishedStatus, UserMessageRequestStatus
104)
105
106def run_agent_in_command_line(assistant: Agent) -> None:
107    conversation_inputs = {}
108    conversation = assistant.start_conversation(inputs=conversation_inputs)
109
110    while True:
111        status = conversation.execute()
112        assistant_reply = conversation.get_last_message()
113        if assistant_reply:
114            print(f"Assistant>>> {assistant_reply.content}\n")
115        if isinstance(status, FinishedStatus):
116            print(f"Finished assistant execution. Output values:\n{status.output_values}",)
117            break
118        elif isinstance(status, UserMessageRequestStatus):
119            user_input = input("User>>> ")
120            print("\n")
121            conversation.append_user_message(user_input)
122        elif isinstance(status, ToolExecutionConfirmationStatus):
123            handle_tool_execution_confirmation(status)
124
125        else:
126            raise ValueError(f"Unsupported execution status: '{status}'")
127
128# run_agent_in_command_line(assistant)
129# ^ uncomment and execute