How to Ask for User Input in Flows#
WayFlow allows you to build powerful automation and agentic workflows. In many real-world scenarios, your flows will need to request and incorporate input from a human user — either to execute a particular action, validate a decision, or simply continue the process.
This guide explains how to design flows that pause for user input, receive responses, and resume execution seamlessly (also known as Human-in-the-loop (HITL) machine learning).
Overview#
There are two standard patterns for requesting user input within a flow:
Simple user requests (e.g., prompting the user for a question or parameter)
Interactive/branching patterns (e.g., asking for confirmation before performing an action, with logic based on the user’s response)
This guide will show you how to:
Add a user input request to your flow using the InputMessageStep
Connect user responses to further steps for flexible flow logic
Chain multiple interactions, including branching for confirmation scenarios
Note
User input is always delivered via InputMessageStep
. WayFlow’s status objects make it easy to detect when input is required and to resume execution once the user has responded.
Basic implementation#
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",
)
from wayflowcore.models import VllmModel
llm = VllmModel(
model_id="model-id",
host_port="VLLM_HOST_PORT",
)
from wayflowcore.models import OllamaModel
llm = OllamaModel(
model_id="model-id",
)
The easiest way to capture user input is with InputMessageStep
.
Used in combination with an execution loop, this step is used to prompt the user for input,
pause flow execution, and deliver the user’s response into the flow’s data context for
use by subsequent steps.
from wayflowcore.controlconnection import ControlFlowEdge
from wayflowcore.dataconnection import DataFlowEdge
from wayflowcore.flow import Flow
from wayflowcore.steps import (
BranchingStep,
CompleteStep,
ExtractValueFromJsonStep,
InputMessageStep,
PromptExecutionStep,
StartStep,
ToolExecutionStep,
)
from wayflowcore.tools import tool
@tool(description_mode="only_docstring")
def get_user_name_tool() -> str:
"""Tool to get user name."""
return "Alice"
start_step = StartStep(name="start")
get_user_name_step = ToolExecutionStep(
name="get_user_name_step",
tool=get_user_name_tool,
)
ask_user_request_step = InputMessageStep(
name="ask_user_request_step", message_template="Hi {{username}}. What can I do for you today?"
)
answer_request_step = PromptExecutionStep(
name="answer_request_step",
llm=llm,
prompt_template="Your are an helpful assistant. Help answer the user request: {{request}}",
output_mapping={
PromptExecutionStep.OUTPUT: "my_output"
}, # what we want to expose as the output name
)
end_step = CompleteStep(name="end")
flow = Flow(
begin_step=start_step,
control_flow_edges=[
ControlFlowEdge(start_step, get_user_name_step),
ControlFlowEdge(get_user_name_step, ask_user_request_step),
ControlFlowEdge(ask_user_request_step, answer_request_step),
ControlFlowEdge(answer_request_step, end_step),
],
data_flow_edges=[
DataFlowEdge(
get_user_name_step, ToolExecutionStep.TOOL_OUTPUT, ask_user_request_step, "username"
),
DataFlowEdge(
ask_user_request_step,
InputMessageStep.USER_PROVIDED_INPUT,
answer_request_step,
"request",
),
],
)
API Reference: Flow | InputMessageStep | CompleteStep
You can then execute this flow as shown below. Notice how the execution is paused until the user enters their input:
from wayflowcore.executors.executionstatus import FinishedStatus, UserMessageRequestStatus
conversation = flow.start_conversation()
status = (
conversation.execute()
) # will get the user input, then pause the execution to ask for the user input
if not isinstance(status, UserMessageRequestStatus):
raise ValueError(
f"Execution status should be {UserMessageRequestStatus.__name__}, was {type(status)}"
)
print(conversation.get_last_message().content)
# Hi Alice. What can I do for you today?
conversation.append_user_message("What is heavier? 20 pounds of bricks of 20 feathers?")
status = conversation.execute() # we resume the execution
if not isinstance(status, FinishedStatus):
raise ValueError(f"Execution status should be {FinishedStatus.__name__}, was {type(status)}")
print(
status.output_values["my_output"]
) # using the key name that we defined in the `output_mapping`
# [...] a surprisingly simple answer emerges: 20 pounds of bricks is heavier than 20 feathers by a massive margin, approximately 69.78 pounds.
Note
When conversation.execute()
returns a UserMessageRequestStatus
, you must append a user message (with conversation.append_user_message(...)
) to continue the flow.
Advanced pattern: Request user input for tool calls or approvals#
See also
For details on enabling client-side confirmations, see the guide How to Add User Confirmation to Tool Call Requests.
In some cases, it is necessary not only to collect a user’s initial input but also request confirmation before executing certain actions — such as validating tool calls or branching flow execution based on user responses.
The following example demonstrates a more sophisticated flow. The flow pauses both for the user’s main request and again for tool call confirmation, using branching to repeat or skip steps depending on the response.
import json
from typing import Dict
from wayflowcore.contextproviders.constantcontextprovider import ConstantContextProvider
from wayflowcore.property import DictProperty, StringProperty
@tool(description_mode="only_docstring")
def my_tool(params: Dict[str, str]) -> str:
"""Params: {"param": str}"""
return f"Invoked tool with {params=}"
prompt_template = """
Your are an helpful assistant. Help answer the user request.
Here is the list of tools:
{{tools}}
Here is the user request:
{{request}}
## Reponse format
Your response should be JSON-compliant dictionary with the following structure.
{
"action": "answer|execute_tool",
"tool_name": "None|tool_name",
"tool_args": {"param1": "value1"}
}
When the action is "answer", "tool_name" should be "None" and "tool_args" should be {}
When the action is "execute_tool", "tool_name" should be the name of the tool to execute
and "tool_args" should be the JSON-compliant dictionary of arguments to pass to the tool.
CRITICAL: Only output the JSON-compliant dictionary otherwise the parsing will fail.
fail.
""".strip()
available_tools = [my_tool]
tool_context_provider = ConstantContextProvider(
json.dumps([tool_.to_dict() for tool_ in available_tools]),
output_description=StringProperty("tool_info"),
)
generate_action_step = PromptExecutionStep(
name="generate_action_step", llm=llm, prompt_template=prompt_template
)
extract_result_step = ExtractValueFromJsonStep(
name="extract_result_step",
output_values={
"action": ".action",
"tool_name": ".tool_name",
"tool_args": ".tool_args",
},
output_descriptors=[
StringProperty(name='action'),
StringProperty(name='tool_name'),
DictProperty(name='tool_args'),
]
)
branching_step = BranchingStep(
name="branching_step", branch_name_mapping={"answer": "answer", "execute_tool": "execute_tool"}
)
answer_end_step = CompleteStep(name="answer_end_step")
user_tool_validation_step = InputMessageStep(
name="user_tool_validation_step",
message_template="Requesting to invoke tool {{name}} with parameters {{params}}. Do you accept the request? (y/n)",
)
tool_selection_branching_step = BranchingStep(
name="tool_selection_branching_step",
branch_name_mapping={"y": "execute_tool", "n": "retry_llm"},
)
invoke_tool_step = ToolExecutionStep(
name="invoke_tool_step",
tool=my_tool,
)
invoke_tool_end_step = CompleteStep(name="invoke_tool_end_step")
flow = Flow(
begin_step=start_step,
control_flow_edges=[
ControlFlowEdge(start_step, get_user_name_step),
ControlFlowEdge(get_user_name_step, ask_user_request_step),
ControlFlowEdge(ask_user_request_step, generate_action_step),
ControlFlowEdge(generate_action_step, extract_result_step),
ControlFlowEdge(extract_result_step, branching_step),
ControlFlowEdge(branching_step, answer_end_step, source_branch="answer"),
ControlFlowEdge(branching_step, user_tool_validation_step, source_branch="execute_tool"),
ControlFlowEdge(
branching_step, answer_end_step, source_branch=BranchingStep.BRANCH_DEFAULT
),
ControlFlowEdge(user_tool_validation_step, tool_selection_branching_step),
ControlFlowEdge(
tool_selection_branching_step, invoke_tool_step, source_branch="execute_tool"
),
ControlFlowEdge(
tool_selection_branching_step, generate_action_step, source_branch="retry_llm"
),
ControlFlowEdge(
tool_selection_branching_step,
generate_action_step,
source_branch=BranchingStep.BRANCH_DEFAULT,
),
ControlFlowEdge(invoke_tool_step, invoke_tool_end_step),
],
data_flow_edges=[
DataFlowEdge(
get_user_name_step, ToolExecutionStep.TOOL_OUTPUT, ask_user_request_step, "username"
),
DataFlowEdge(
ask_user_request_step,
InputMessageStep.USER_PROVIDED_INPUT,
generate_action_step,
"request",
),
DataFlowEdge(tool_context_provider, "tool_info", generate_action_step, "tools"),
DataFlowEdge(
generate_action_step,
PromptExecutionStep.OUTPUT,
extract_result_step,
ExtractValueFromJsonStep.TEXT,
),
DataFlowEdge(extract_result_step, "action", branching_step, BranchingStep.NEXT_BRANCH_NAME),
DataFlowEdge(extract_result_step, "tool_name", user_tool_validation_step, "name"),
DataFlowEdge(extract_result_step, "tool_args", user_tool_validation_step, "params"),
DataFlowEdge(
user_tool_validation_step,
InputMessageStep.USER_PROVIDED_INPUT,
tool_selection_branching_step,
BranchingStep.NEXT_BRANCH_NAME,
),
DataFlowEdge(extract_result_step, "tool_args", invoke_tool_step, "params"),
],
)
API Reference: Flow | InputMessageStep | BranchingStep | ToolExecutionStep
Note
The InputMessageStep
can be reused at multiple points in a flow for different types of input—questions, approvals, parameter selection, etc. Use BranchingStep
to control your logic flow depending on the user’s reply.
To drive this advanced flow, you execute and interact with the agent as follows:
conversation = flow.start_conversation()
status = (
conversation.execute()
) # will get the user input, then pause the execution to ask for the user input
if not isinstance(status, UserMessageRequestStatus):
raise ValueError(
f"Execution status should be {UserMessageRequestStatus.__name__}, was {type(status)}"
)
print(conversation.get_last_message().content)
# Hi Alice. What can I do for you today?
conversation.append_user_message("Invoke the tool with parameter 'value#007'")
status = conversation.execute() # we resume the execution
if not isinstance(status, UserMessageRequestStatus):
raise ValueError(
f"Execution status should be {UserMessageRequestStatus.__name__}, was {type(status)}"
)
print(conversation.get_last_message().content)
# Requesting to invoke tool my_tool with parameters {"param": "value#007"}. Do you accept the request? (y/n)
conversation.append_user_message("y") # we accept the tool call request
status = conversation.execute() # we resume the execution
if not isinstance(status, FinishedStatus):
raise ValueError(f"Execution status should be {FinishedStatus.__name__}, was {type(status)}")
print(status.output_values[ToolExecutionStep.TOOL_OUTPUT])
# Invoked tool with params={'param': 'value#007'}
Tip
Design your message_template
and branching mapping to ensure robust, user-friendly interactions.
You can combine user input at any point with decision logic for flexible, agent-like flows.
You can also use CatchExceptionStep to handle issues such as user typing something else than “y/n”.
Agent Spec Exporting/Loading#
You can export the flow configuration to its Agent Spec configuration using the AgentSpecExporter
.
from wayflowcore.agentspec import AgentSpecExporter
config = AgentSpecExporter().to_json(flow)
Here is what the Agent Spec representation will look like ↓
Click here to see the assistant configuration.
{
"component_type": "ExtendedFlow",
"id": "44ca9623-5567-4abc-8972-065df61d94e7",
"name": "flow_edbb400a__auto",
"description": "",
"metadata": {
"__metadata_info__": {}
},
"inputs": [],
"outputs": [
{
"type": "string",
"title": "tool_output"
},
{
"description": "the generated text",
"type": "string",
"title": "output"
},
{
"type": "string",
"title": "tool_name"
},
{
"type": "object",
"additionalProperties": {
"type": "string"
},
"key_type": {
"type": "string"
},
"title": "tool_args"
},
{
"type": "string",
"title": "action"
},
{
"description": "the input value provided by the user",
"type": "string",
"title": "user_provided_input"
}
],
"start_node": {
"$component_ref": "df2e111a-b6ac-4c66-8d57-99e0b9c94fdd"
},
"nodes": [
{
"$component_ref": "df2e111a-b6ac-4c66-8d57-99e0b9c94fdd"
},
{
"$component_ref": "a3614787-eae2-4330-a5be-cf8bdad4544d"
},
{
"$component_ref": "28f6f69b-aa81-49f7-be22-c51a3b0baaa5"
},
{
"$component_ref": "d093d2ee-d8cd-40f7-9163-154d3ae72a22"
},
{
"$component_ref": "b31c569b-2a66-4f2b-a98d-f52bfca2dfeb"
},
{
"$component_ref": "6e5fcaaf-1cf2-443d-9def-14c99333be68"
},
{
"$component_ref": "e2126f15-b523-44de-a087-971799a810c2"
},
{
"$component_ref": "82460353-8eac-483d-967e-04fa7614d5c4"
},
{
"$component_ref": "6c170ac9-3277-4581-841a-8edf4db175e0"
},
{
"$component_ref": "2ae6af7c-4c67-49a8-b578-f1666466a4ca"
},
{
"$component_ref": "d326fb5d-a9b0-4845-aaba-b8f01e523471"
}
],
"control_flow_connections": [
{
"component_type": "ControlFlowEdge",
"id": "42271781-8986-4ffc-be77-2700dd947ec5",
"name": "start_to_get_user_name_step_control_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"from_node": {
"$component_ref": "df2e111a-b6ac-4c66-8d57-99e0b9c94fdd"
},
"from_branch": null,
"to_node": {
"$component_ref": "a3614787-eae2-4330-a5be-cf8bdad4544d"
}
},
{
"component_type": "ControlFlowEdge",
"id": "1c830ec0-c8a5-41da-8565-12cc0a933e19",
"name": "get_user_name_step_to_ask_user_request_step_control_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"from_node": {
"$component_ref": "a3614787-eae2-4330-a5be-cf8bdad4544d"
},
"from_branch": null,
"to_node": {
"$component_ref": "28f6f69b-aa81-49f7-be22-c51a3b0baaa5"
}
},
{
"component_type": "ControlFlowEdge",
"id": "cb0100a1-307a-4352-bc69-550eb5c62d9a",
"name": "ask_user_request_step_to_generate_action_step_control_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"from_node": {
"$component_ref": "28f6f69b-aa81-49f7-be22-c51a3b0baaa5"
},
"from_branch": null,
"to_node": {
"$component_ref": "d093d2ee-d8cd-40f7-9163-154d3ae72a22"
}
},
{
"component_type": "ControlFlowEdge",
"id": "07c38ae3-0246-492b-bf11-7922004432fa",
"name": "generate_action_step_to_extract_result_step_control_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"from_node": {
"$component_ref": "d093d2ee-d8cd-40f7-9163-154d3ae72a22"
},
"from_branch": null,
"to_node": {
"$component_ref": "b31c569b-2a66-4f2b-a98d-f52bfca2dfeb"
}
},
{
"component_type": "ControlFlowEdge",
"id": "04308f40-8171-4651-8dbf-fbf527f8f9ed",
"name": "extract_result_step_to_branching_step_control_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"from_node": {
"$component_ref": "b31c569b-2a66-4f2b-a98d-f52bfca2dfeb"
},
"from_branch": null,
"to_node": {
"$component_ref": "6e5fcaaf-1cf2-443d-9def-14c99333be68"
}
},
{
"component_type": "ControlFlowEdge",
"id": "dab13845-d78b-4e5c-addf-cbd28f84da70",
"name": "branching_step_to_answer_end_step_control_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"from_node": {
"$component_ref": "6e5fcaaf-1cf2-443d-9def-14c99333be68"
},
"from_branch": "answer",
"to_node": {
"$component_ref": "2ae6af7c-4c67-49a8-b578-f1666466a4ca"
}
},
{
"component_type": "ControlFlowEdge",
"id": "29c13062-7060-4878-8f32-b2a3735bf892",
"name": "branching_step_to_user_tool_validation_step_control_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"from_node": {
"$component_ref": "6e5fcaaf-1cf2-443d-9def-14c99333be68"
},
"from_branch": "execute_tool",
"to_node": {
"$component_ref": "e2126f15-b523-44de-a087-971799a810c2"
}
},
{
"component_type": "ControlFlowEdge",
"id": "46f0cae7-aef3-4387-8c34-c8442f6008f5",
"name": "branching_step_to_answer_end_step_control_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"from_node": {
"$component_ref": "6e5fcaaf-1cf2-443d-9def-14c99333be68"
},
"from_branch": "default",
"to_node": {
"$component_ref": "2ae6af7c-4c67-49a8-b578-f1666466a4ca"
}
},
{
"component_type": "ControlFlowEdge",
"id": "aec3a3d8-feba-40dd-839a-59690f17939c",
"name": "user_tool_validation_step_to_tool_selection_branching_step_control_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"from_node": {
"$component_ref": "e2126f15-b523-44de-a087-971799a810c2"
},
"from_branch": null,
"to_node": {
"$component_ref": "82460353-8eac-483d-967e-04fa7614d5c4"
}
},
{
"component_type": "ControlFlowEdge",
"id": "4506945a-6f39-4839-a910-c3eee14ad872",
"name": "tool_selection_branching_step_to_invoke_tool_step_control_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"from_node": {
"$component_ref": "82460353-8eac-483d-967e-04fa7614d5c4"
},
"from_branch": "execute_tool",
"to_node": {
"$component_ref": "6c170ac9-3277-4581-841a-8edf4db175e0"
}
},
{
"component_type": "ControlFlowEdge",
"id": "eac1e546-a9e9-436b-a83b-63a74ad93bc6",
"name": "tool_selection_branching_step_to_generate_action_step_control_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"from_node": {
"$component_ref": "82460353-8eac-483d-967e-04fa7614d5c4"
},
"from_branch": "retry_llm",
"to_node": {
"$component_ref": "d093d2ee-d8cd-40f7-9163-154d3ae72a22"
}
},
{
"component_type": "ControlFlowEdge",
"id": "8a20f70d-399f-41f1-8191-85502c5e947a",
"name": "tool_selection_branching_step_to_generate_action_step_control_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"from_node": {
"$component_ref": "82460353-8eac-483d-967e-04fa7614d5c4"
},
"from_branch": "default",
"to_node": {
"$component_ref": "d093d2ee-d8cd-40f7-9163-154d3ae72a22"
}
},
{
"component_type": "ControlFlowEdge",
"id": "2487e15a-0f1c-4529-8b60-d21c43e1b926",
"name": "invoke_tool_step_to_invoke_tool_end_step_control_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"from_node": {
"$component_ref": "6c170ac9-3277-4581-841a-8edf4db175e0"
},
"from_branch": null,
"to_node": {
"$component_ref": "d326fb5d-a9b0-4845-aaba-b8f01e523471"
}
}
],
"data_flow_connections": [
{
"component_type": "DataFlowEdge",
"id": "3f74cc4f-237c-491d-8fd1-3ff44e08b6a8",
"name": "get_user_name_step_tool_output_to_ask_user_request_step_username_data_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"source_node": {
"$component_ref": "a3614787-eae2-4330-a5be-cf8bdad4544d"
},
"source_output": "tool_output",
"destination_node": {
"$component_ref": "28f6f69b-aa81-49f7-be22-c51a3b0baaa5"
},
"destination_input": "username"
},
{
"component_type": "DataFlowEdge",
"id": "476856ed-4b35-49e0-bb12-c29a53faf97f",
"name": "ask_user_request_step_user_provided_input_to_generate_action_step_request_data_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"source_node": {
"$component_ref": "28f6f69b-aa81-49f7-be22-c51a3b0baaa5"
},
"source_output": "user_provided_input",
"destination_node": {
"$component_ref": "d093d2ee-d8cd-40f7-9163-154d3ae72a22"
},
"destination_input": "request"
},
{
"component_type": "DataFlowEdge",
"id": "c40dadcb-35e9-4b41-bae1-2960e69852ce",
"name": "a91502a3-117f-40af-a000-3663a3db87e3_tool_info_to_generate_action_step_tools_data_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"source_node": {
"$component_ref": "a91502a3-117f-40af-a000-3663a3db87e3"
},
"source_output": "tool_info",
"destination_node": {
"$component_ref": "d093d2ee-d8cd-40f7-9163-154d3ae72a22"
},
"destination_input": "tools"
},
{
"component_type": "DataFlowEdge",
"id": "eec02f81-55e0-42c7-b3f4-12c364c52ed2",
"name": "generate_action_step_output_to_extract_result_step_text_data_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"source_node": {
"$component_ref": "d093d2ee-d8cd-40f7-9163-154d3ae72a22"
},
"source_output": "output",
"destination_node": {
"$component_ref": "b31c569b-2a66-4f2b-a98d-f52bfca2dfeb"
},
"destination_input": "text"
},
{
"component_type": "DataFlowEdge",
"id": "f7e9acbe-c472-45d8-bf92-b35f436190be",
"name": "extract_result_step_action_to_branching_step_next_step_name_data_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"source_node": {
"$component_ref": "b31c569b-2a66-4f2b-a98d-f52bfca2dfeb"
},
"source_output": "action",
"destination_node": {
"$component_ref": "6e5fcaaf-1cf2-443d-9def-14c99333be68"
},
"destination_input": "next_step_name"
},
{
"component_type": "DataFlowEdge",
"id": "3a2ff915-ca72-43f3-b6a2-f9a3dbceb621",
"name": "extract_result_step_tool_name_to_user_tool_validation_step_name_data_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"source_node": {
"$component_ref": "b31c569b-2a66-4f2b-a98d-f52bfca2dfeb"
},
"source_output": "tool_name",
"destination_node": {
"$component_ref": "e2126f15-b523-44de-a087-971799a810c2"
},
"destination_input": "name"
},
{
"component_type": "DataFlowEdge",
"id": "30845c9b-4b4c-4108-9b4e-4ebb9f881e32",
"name": "extract_result_step_tool_args_to_user_tool_validation_step_params_data_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"source_node": {
"$component_ref": "b31c569b-2a66-4f2b-a98d-f52bfca2dfeb"
},
"source_output": "tool_args",
"destination_node": {
"$component_ref": "e2126f15-b523-44de-a087-971799a810c2"
},
"destination_input": "params"
},
{
"component_type": "DataFlowEdge",
"id": "3baa59bf-c302-434c-ac8c-55e5051db3e3",
"name": "user_tool_validation_step_user_provided_input_to_tool_selection_branching_step_next_step_name_data_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"source_node": {
"$component_ref": "e2126f15-b523-44de-a087-971799a810c2"
},
"source_output": "user_provided_input",
"destination_node": {
"$component_ref": "82460353-8eac-483d-967e-04fa7614d5c4"
},
"destination_input": "next_step_name"
},
{
"component_type": "DataFlowEdge",
"id": "c0fd3d7a-9d7d-471e-962a-a99e5fb52c96",
"name": "extract_result_step_tool_args_to_invoke_tool_step_params_data_flow_edge",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"source_node": {
"$component_ref": "b31c569b-2a66-4f2b-a98d-f52bfca2dfeb"
},
"source_output": "tool_args",
"destination_node": {
"$component_ref": "6c170ac9-3277-4581-841a-8edf4db175e0"
},
"destination_input": "params"
},
{
"component_type": "DataFlowEdge",
"id": "9596e6a9-2b6f-4cc7-b9d8-ce778112c92d",
"name": "get_user_name_step_tool_output_to_answer_end_step_tool_output_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "a3614787-eae2-4330-a5be-cf8bdad4544d"
},
"source_output": "tool_output",
"destination_node": {
"$component_ref": "2ae6af7c-4c67-49a8-b578-f1666466a4ca"
},
"destination_input": "tool_output"
},
{
"component_type": "DataFlowEdge",
"id": "16eece12-6815-479e-b47f-7b09fc400604",
"name": "invoke_tool_step_tool_output_to_answer_end_step_tool_output_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "6c170ac9-3277-4581-841a-8edf4db175e0"
},
"source_output": "tool_output",
"destination_node": {
"$component_ref": "2ae6af7c-4c67-49a8-b578-f1666466a4ca"
},
"destination_input": "tool_output"
},
{
"component_type": "DataFlowEdge",
"id": "a16f467c-401a-4135-9d43-b777800e48fa",
"name": "generate_action_step_output_to_answer_end_step_output_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "d093d2ee-d8cd-40f7-9163-154d3ae72a22"
},
"source_output": "output",
"destination_node": {
"$component_ref": "2ae6af7c-4c67-49a8-b578-f1666466a4ca"
},
"destination_input": "output"
},
{
"component_type": "DataFlowEdge",
"id": "dd868b71-39c5-41c3-b6b0-520595600b9c",
"name": "extract_result_step_tool_name_to_answer_end_step_tool_name_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "b31c569b-2a66-4f2b-a98d-f52bfca2dfeb"
},
"source_output": "tool_name",
"destination_node": {
"$component_ref": "2ae6af7c-4c67-49a8-b578-f1666466a4ca"
},
"destination_input": "tool_name"
},
{
"component_type": "DataFlowEdge",
"id": "a489f8cc-3be4-435a-8a2c-1bffd290f5c2",
"name": "extract_result_step_tool_args_to_answer_end_step_tool_args_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "b31c569b-2a66-4f2b-a98d-f52bfca2dfeb"
},
"source_output": "tool_args",
"destination_node": {
"$component_ref": "2ae6af7c-4c67-49a8-b578-f1666466a4ca"
},
"destination_input": "tool_args"
},
{
"component_type": "DataFlowEdge",
"id": "739bacd9-78b9-470a-9dae-f784870998c1",
"name": "extract_result_step_action_to_answer_end_step_action_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "b31c569b-2a66-4f2b-a98d-f52bfca2dfeb"
},
"source_output": "action",
"destination_node": {
"$component_ref": "2ae6af7c-4c67-49a8-b578-f1666466a4ca"
},
"destination_input": "action"
},
{
"component_type": "DataFlowEdge",
"id": "9e275423-8504-4d56-8c02-229101af294c",
"name": "ask_user_request_step_user_provided_input_to_answer_end_step_user_provided_input_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "28f6f69b-aa81-49f7-be22-c51a3b0baaa5"
},
"source_output": "user_provided_input",
"destination_node": {
"$component_ref": "2ae6af7c-4c67-49a8-b578-f1666466a4ca"
},
"destination_input": "user_provided_input"
},
{
"component_type": "DataFlowEdge",
"id": "da295e5e-8abb-4d16-b39b-3853e0df310d",
"name": "user_tool_validation_step_user_provided_input_to_answer_end_step_user_provided_input_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "e2126f15-b523-44de-a087-971799a810c2"
},
"source_output": "user_provided_input",
"destination_node": {
"$component_ref": "2ae6af7c-4c67-49a8-b578-f1666466a4ca"
},
"destination_input": "user_provided_input"
},
{
"component_type": "DataFlowEdge",
"id": "4bc35cfb-8f77-4537-8ce6-a12f6f19a554",
"name": "get_user_name_step_tool_output_to_invoke_tool_end_step_tool_output_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "a3614787-eae2-4330-a5be-cf8bdad4544d"
},
"source_output": "tool_output",
"destination_node": {
"$component_ref": "d326fb5d-a9b0-4845-aaba-b8f01e523471"
},
"destination_input": "tool_output"
},
{
"component_type": "DataFlowEdge",
"id": "4a1242bb-cb58-4578-be57-4a11764f19a5",
"name": "invoke_tool_step_tool_output_to_invoke_tool_end_step_tool_output_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "6c170ac9-3277-4581-841a-8edf4db175e0"
},
"source_output": "tool_output",
"destination_node": {
"$component_ref": "d326fb5d-a9b0-4845-aaba-b8f01e523471"
},
"destination_input": "tool_output"
},
{
"component_type": "DataFlowEdge",
"id": "307aef79-4a11-4bd7-8cfd-90d8ab4c5d52",
"name": "generate_action_step_output_to_invoke_tool_end_step_output_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "d093d2ee-d8cd-40f7-9163-154d3ae72a22"
},
"source_output": "output",
"destination_node": {
"$component_ref": "d326fb5d-a9b0-4845-aaba-b8f01e523471"
},
"destination_input": "output"
},
{
"component_type": "DataFlowEdge",
"id": "c31a0fba-93c9-46a8-a21e-efdcff8d1130",
"name": "extract_result_step_tool_name_to_invoke_tool_end_step_tool_name_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "b31c569b-2a66-4f2b-a98d-f52bfca2dfeb"
},
"source_output": "tool_name",
"destination_node": {
"$component_ref": "d326fb5d-a9b0-4845-aaba-b8f01e523471"
},
"destination_input": "tool_name"
},
{
"component_type": "DataFlowEdge",
"id": "d5ea1f13-b60a-4010-bfd9-318a81cba2f3",
"name": "extract_result_step_tool_args_to_invoke_tool_end_step_tool_args_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "b31c569b-2a66-4f2b-a98d-f52bfca2dfeb"
},
"source_output": "tool_args",
"destination_node": {
"$component_ref": "d326fb5d-a9b0-4845-aaba-b8f01e523471"
},
"destination_input": "tool_args"
},
{
"component_type": "DataFlowEdge",
"id": "8b3a2623-4d26-41ba-881a-8b5a566b8d7e",
"name": "extract_result_step_action_to_invoke_tool_end_step_action_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "b31c569b-2a66-4f2b-a98d-f52bfca2dfeb"
},
"source_output": "action",
"destination_node": {
"$component_ref": "d326fb5d-a9b0-4845-aaba-b8f01e523471"
},
"destination_input": "action"
},
{
"component_type": "DataFlowEdge",
"id": "5361e910-0b85-490a-b9bd-0613eed38037",
"name": "ask_user_request_step_user_provided_input_to_invoke_tool_end_step_user_provided_input_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "28f6f69b-aa81-49f7-be22-c51a3b0baaa5"
},
"source_output": "user_provided_input",
"destination_node": {
"$component_ref": "d326fb5d-a9b0-4845-aaba-b8f01e523471"
},
"destination_input": "user_provided_input"
},
{
"component_type": "DataFlowEdge",
"id": "346f5ff8-f0a6-4b0d-9727-69a79a2f5489",
"name": "user_tool_validation_step_user_provided_input_to_invoke_tool_end_step_user_provided_input_data_flow_edge",
"description": null,
"metadata": {},
"source_node": {
"$component_ref": "e2126f15-b523-44de-a087-971799a810c2"
},
"source_output": "user_provided_input",
"destination_node": {
"$component_ref": "d326fb5d-a9b0-4845-aaba-b8f01e523471"
},
"destination_input": "user_provided_input"
}
],
"context_providers": [
{
"$component_ref": "a91502a3-117f-40af-a000-3663a3db87e3"
}
],
"component_plugin_name": "FlowPlugin",
"component_plugin_version": "25.4.0.dev0",
"$referenced_components": {
"28f6f69b-aa81-49f7-be22-c51a3b0baaa5": {
"component_type": "PluginInputMessageNode",
"id": "28f6f69b-aa81-49f7-be22-c51a3b0baaa5",
"name": "ask_user_request_step",
"description": "",
"metadata": {
"__metadata_info__": {}
},
"inputs": [
{
"description": "\"username\" input variable for the template",
"type": "string",
"title": "username"
}
],
"outputs": [
{
"description": "the input value provided by the user",
"type": "string",
"title": "user_provided_input"
}
],
"branches": [
"next"
],
"input_mapping": {},
"output_mapping": {},
"message_template": "Hi {{username}}. What can I do for you today?",
"rephrase": false,
"llm_config": null,
"component_plugin_name": "NodesPlugin",
"component_plugin_version": "25.4.0.dev0"
},
"a3614787-eae2-4330-a5be-cf8bdad4544d": {
"component_type": "ExtendedToolNode",
"id": "a3614787-eae2-4330-a5be-cf8bdad4544d",
"name": "get_user_name_step",
"description": "",
"metadata": {
"__metadata_info__": {}
},
"inputs": [],
"outputs": [
{
"type": "string",
"title": "tool_output"
}
],
"branches": [
"next"
],
"tool": {
"component_type": "ServerTool",
"id": "cfd9cae9-38b9-4b48-9a52-d324899a4859",
"name": "get_user_name_tool",
"description": "Tool to get user name.",
"metadata": {
"__metadata_info__": {}
},
"inputs": [],
"outputs": [
{
"type": "string",
"title": "tool_output"
}
]
},
"input_mapping": {},
"output_mapping": {},
"raise_exceptions": false,
"component_plugin_name": "NodesPlugin",
"component_plugin_version": "25.4.0.dev0"
},
"d093d2ee-d8cd-40f7-9163-154d3ae72a22": {
"component_type": "LlmNode",
"id": "d093d2ee-d8cd-40f7-9163-154d3ae72a22",
"name": "generate_action_step",
"description": "",
"metadata": {
"__metadata_info__": {}
},
"inputs": [
{
"description": "\"tools\" input variable for the template",
"type": "string",
"title": "tools"
},
{
"description": "\"request\" input variable for the template",
"type": "string",
"title": "request"
}
],
"outputs": [
{
"description": "the generated text",
"type": "string",
"title": "output"
}
],
"branches": [
"next"
],
"llm_config": {
"component_type": "VllmConfig",
"id": "5fdf143c-a7ee-459c-8ff8-409df206e73b",
"name": "LLAMA_MODEL_ID",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"default_generation_parameters": null,
"url": "LLAMA_API_URL",
"model_id": "LLAMA_MODEL_ID"
},
"prompt_template": "Your are an helpful assistant. Help answer the user request.\n\nHere is the list of tools:\n{{tools}}\n\nHere is the user request:\n{{request}}\n\n## Reponse format\nYour response should be JSON-compliant dictionary with the following structure.\n\n{\n \"action\": \"answer|execute_tool\",\n \"tool_name\": \"None|tool_name\",\n \"tool_args\": {\"param1\": \"value1\"}\n}\n\nWhen the action is \"answer\", \"tool_name\" should be \"None\" and \"tool_args\" should be {}\nWhen the action is \"execute_tool\", \"tool_name\" should be the name of the tool to execute\nand \"tool_args\" should be the JSON-compliant dictionary of arguments to pass to the tool.\n\nCRITICAL: Only output the JSON-compliant dictionary otherwise the parsing will fail.\nfail."
},
"a91502a3-117f-40af-a000-3663a3db87e3": {
"component_type": "PluginConstantContextProvider",
"id": "a91502a3-117f-40af-a000-3663a3db87e3",
"name": "a91502a3-117f-40af-a000-3663a3db87e3",
"description": null,
"metadata": {},
"inputs": [],
"outputs": [
{
"type": "string",
"title": "tool_info"
}
],
"branches": [
"next"
],
"value": "[{\"name\": \"my_tool\", \"description\": \"Params: {\\\"param\\\": str}\", \"parameters\": {\"params\": {\"type\": \"object\", \"additionalProperties\": {\"type\": \"string\"}, \"title\": \"Params\"}}}]",
"component_plugin_name": "ContextProviderPlugin",
"component_plugin_version": "25.4.0.dev0"
},
"b31c569b-2a66-4f2b-a98d-f52bfca2dfeb": {
"component_type": "PluginExtractNode",
"id": "b31c569b-2a66-4f2b-a98d-f52bfca2dfeb",
"name": "extract_result_step",
"description": "",
"metadata": {
"__metadata_info__": {}
},
"inputs": [
{
"description": "raw text to extract information from",
"type": "string",
"title": "text"
}
],
"outputs": [
{
"type": "string",
"title": "action"
},
{
"type": "string",
"title": "tool_name"
},
{
"type": "object",
"additionalProperties": {
"type": "string"
},
"key_type": {
"type": "string"
},
"title": "tool_args"
}
],
"branches": [
"next"
],
"input_mapping": {},
"output_mapping": {},
"output_values": {
"action": ".action",
"tool_name": ".tool_name",
"tool_args": ".tool_args"
},
"component_plugin_name": "NodesPlugin",
"component_plugin_version": "25.4.0.dev0"
},
"6e5fcaaf-1cf2-443d-9def-14c99333be68": {
"component_type": "BranchingNode",
"id": "6e5fcaaf-1cf2-443d-9def-14c99333be68",
"name": "branching_step",
"description": "",
"metadata": {
"__metadata_info__": {}
},
"inputs": [
{
"description": "Next branch name in the flow",
"type": "string",
"title": "next_step_name",
"default": "default"
}
],
"outputs": [],
"branches": [
"answer",
"default",
"execute_tool"
],
"mapping": {
"answer": "answer",
"execute_tool": "execute_tool"
}
},
"e2126f15-b523-44de-a087-971799a810c2": {
"component_type": "PluginInputMessageNode",
"id": "e2126f15-b523-44de-a087-971799a810c2",
"name": "user_tool_validation_step",
"description": "",
"metadata": {
"__metadata_info__": {}
},
"inputs": [
{
"description": "\"name\" input variable for the template",
"type": "string",
"title": "name"
},
{
"description": "\"params\" input variable for the template",
"type": "string",
"title": "params"
}
],
"outputs": [
{
"description": "the input value provided by the user",
"type": "string",
"title": "user_provided_input"
}
],
"branches": [
"next"
],
"input_mapping": {},
"output_mapping": {},
"message_template": "Requesting to invoke tool {{name}} with parameters {{params}}. Do you accept the request? (y/n)",
"rephrase": false,
"llm_config": null,
"component_plugin_name": "NodesPlugin",
"component_plugin_version": "25.4.0.dev0"
},
"82460353-8eac-483d-967e-04fa7614d5c4": {
"component_type": "BranchingNode",
"id": "82460353-8eac-483d-967e-04fa7614d5c4",
"name": "tool_selection_branching_step",
"description": "",
"metadata": {
"__metadata_info__": {}
},
"inputs": [
{
"description": "Next branch name in the flow",
"type": "string",
"title": "next_step_name",
"default": "default"
}
],
"outputs": [],
"branches": [
"default",
"execute_tool",
"retry_llm"
],
"mapping": {
"y": "execute_tool",
"n": "retry_llm"
}
},
"6c170ac9-3277-4581-841a-8edf4db175e0": {
"component_type": "ExtendedToolNode",
"id": "6c170ac9-3277-4581-841a-8edf4db175e0",
"name": "invoke_tool_step",
"description": "",
"metadata": {
"__metadata_info__": {}
},
"inputs": [
{
"type": "object",
"additionalProperties": {
"type": "string"
},
"title": "params"
}
],
"outputs": [
{
"type": "string",
"title": "tool_output"
}
],
"branches": [
"next"
],
"tool": {
"component_type": "ServerTool",
"id": "5886e17c-c2c5-400d-9bf1-fdfe8490c35b",
"name": "my_tool",
"description": "Params: {\"param\": str}",
"metadata": {
"__metadata_info__": {}
},
"inputs": [
{
"type": "object",
"additionalProperties": {
"type": "string"
},
"title": "params"
}
],
"outputs": [
{
"type": "string",
"title": "tool_output"
}
]
},
"input_mapping": {},
"output_mapping": {},
"raise_exceptions": false,
"component_plugin_name": "NodesPlugin",
"component_plugin_version": "25.4.0.dev0"
},
"2ae6af7c-4c67-49a8-b578-f1666466a4ca": {
"component_type": "EndNode",
"id": "2ae6af7c-4c67-49a8-b578-f1666466a4ca",
"name": "answer_end_step",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"inputs": [
{
"type": "string",
"title": "tool_output"
},
{
"description": "the generated text",
"type": "string",
"title": "output"
},
{
"type": "string",
"title": "tool_name"
},
{
"type": "object",
"additionalProperties": {
"type": "string"
},
"key_type": {
"type": "string"
},
"title": "tool_args"
},
{
"type": "string",
"title": "action"
},
{
"description": "the input value provided by the user",
"type": "string",
"title": "user_provided_input"
}
],
"outputs": [
{
"type": "string",
"title": "tool_output"
},
{
"description": "the generated text",
"type": "string",
"title": "output"
},
{
"type": "string",
"title": "tool_name"
},
{
"type": "object",
"additionalProperties": {
"type": "string"
},
"key_type": {
"type": "string"
},
"title": "tool_args"
},
{
"type": "string",
"title": "action"
},
{
"description": "the input value provided by the user",
"type": "string",
"title": "user_provided_input"
}
],
"branches": [],
"branch_name": "answer_end_step"
},
"d326fb5d-a9b0-4845-aaba-b8f01e523471": {
"component_type": "EndNode",
"id": "d326fb5d-a9b0-4845-aaba-b8f01e523471",
"name": "invoke_tool_end_step",
"description": null,
"metadata": {
"__metadata_info__": {}
},
"inputs": [
{
"type": "string",
"title": "tool_output"
},
{
"description": "the generated text",
"type": "string",
"title": "output"
},
{
"type": "string",
"title": "tool_name"
},
{
"type": "object",
"additionalProperties": {
"type": "string"
},
"key_type": {
"type": "string"
},
"title": "tool_args"
},
{
"type": "string",
"title": "action"
},
{
"description": "the input value provided by the user",
"type": "string",
"title": "user_provided_input"
}
],
"outputs": [
{
"type": "string",
"title": "tool_output"
},
{
"description": "the generated text",
"type": "string",
"title": "output"
},
{
"type": "string",
"title": "tool_name"
},
{
"type": "object",
"additionalProperties": {
"type": "string"
},
"key_type": {
"type": "string"
},
"title": "tool_args"
},
{
"type": "string",
"title": "action"
},
{
"description": "the input value provided by the user",
"type": "string",
"title": "user_provided_input"
}
],
"branches": [],
"branch_name": "invoke_tool_end_step"
},
"df2e111a-b6ac-4c66-8d57-99e0b9c94fdd": {
"component_type": "StartNode",
"id": "df2e111a-b6ac-4c66-8d57-99e0b9c94fdd",
"name": "start",
"description": "",
"metadata": {
"__metadata_info__": {}
},
"inputs": [],
"outputs": [],
"branches": [
"next"
]
}
},
"agentspec_version": "25.4.1"
}
component_type: ExtendedFlow
id: 44ca9623-5567-4abc-8972-065df61d94e7
name: flow_edbb400a__auto
description: ''
metadata:
__metadata_info__: {}
inputs: []
outputs:
- type: string
title: tool_output
- description: the generated text
type: string
title: output
- type: string
title: tool_name
- type: object
additionalProperties:
type: string
key_type:
type: string
title: tool_args
- type: string
title: action
- description: the input value provided by the user
type: string
title: user_provided_input
start_node:
$component_ref: df2e111a-b6ac-4c66-8d57-99e0b9c94fdd
nodes:
- $component_ref: df2e111a-b6ac-4c66-8d57-99e0b9c94fdd
- $component_ref: a3614787-eae2-4330-a5be-cf8bdad4544d
- $component_ref: 28f6f69b-aa81-49f7-be22-c51a3b0baaa5
- $component_ref: d093d2ee-d8cd-40f7-9163-154d3ae72a22
- $component_ref: b31c569b-2a66-4f2b-a98d-f52bfca2dfeb
- $component_ref: 6e5fcaaf-1cf2-443d-9def-14c99333be68
- $component_ref: e2126f15-b523-44de-a087-971799a810c2
- $component_ref: 82460353-8eac-483d-967e-04fa7614d5c4
- $component_ref: 6c170ac9-3277-4581-841a-8edf4db175e0
- $component_ref: 2ae6af7c-4c67-49a8-b578-f1666466a4ca
- $component_ref: d326fb5d-a9b0-4845-aaba-b8f01e523471
control_flow_connections:
- component_type: ControlFlowEdge
id: 42271781-8986-4ffc-be77-2700dd947ec5
name: start_to_get_user_name_step_control_flow_edge
description: null
metadata:
__metadata_info__: {}
from_node:
$component_ref: df2e111a-b6ac-4c66-8d57-99e0b9c94fdd
from_branch: null
to_node:
$component_ref: a3614787-eae2-4330-a5be-cf8bdad4544d
- component_type: ControlFlowEdge
id: 1c830ec0-c8a5-41da-8565-12cc0a933e19
name: get_user_name_step_to_ask_user_request_step_control_flow_edge
description: null
metadata:
__metadata_info__: {}
from_node:
$component_ref: a3614787-eae2-4330-a5be-cf8bdad4544d
from_branch: null
to_node:
$component_ref: 28f6f69b-aa81-49f7-be22-c51a3b0baaa5
- component_type: ControlFlowEdge
id: cb0100a1-307a-4352-bc69-550eb5c62d9a
name: ask_user_request_step_to_generate_action_step_control_flow_edge
description: null
metadata:
__metadata_info__: {}
from_node:
$component_ref: 28f6f69b-aa81-49f7-be22-c51a3b0baaa5
from_branch: null
to_node:
$component_ref: d093d2ee-d8cd-40f7-9163-154d3ae72a22
- component_type: ControlFlowEdge
id: 07c38ae3-0246-492b-bf11-7922004432fa
name: generate_action_step_to_extract_result_step_control_flow_edge
description: null
metadata:
__metadata_info__: {}
from_node:
$component_ref: d093d2ee-d8cd-40f7-9163-154d3ae72a22
from_branch: null
to_node:
$component_ref: b31c569b-2a66-4f2b-a98d-f52bfca2dfeb
- component_type: ControlFlowEdge
id: 04308f40-8171-4651-8dbf-fbf527f8f9ed
name: extract_result_step_to_branching_step_control_flow_edge
description: null
metadata:
__metadata_info__: {}
from_node:
$component_ref: b31c569b-2a66-4f2b-a98d-f52bfca2dfeb
from_branch: null
to_node:
$component_ref: 6e5fcaaf-1cf2-443d-9def-14c99333be68
- component_type: ControlFlowEdge
id: dab13845-d78b-4e5c-addf-cbd28f84da70
name: branching_step_to_answer_end_step_control_flow_edge
description: null
metadata:
__metadata_info__: {}
from_node:
$component_ref: 6e5fcaaf-1cf2-443d-9def-14c99333be68
from_branch: answer
to_node:
$component_ref: 2ae6af7c-4c67-49a8-b578-f1666466a4ca
- component_type: ControlFlowEdge
id: 29c13062-7060-4878-8f32-b2a3735bf892
name: branching_step_to_user_tool_validation_step_control_flow_edge
description: null
metadata:
__metadata_info__: {}
from_node:
$component_ref: 6e5fcaaf-1cf2-443d-9def-14c99333be68
from_branch: execute_tool
to_node:
$component_ref: e2126f15-b523-44de-a087-971799a810c2
- component_type: ControlFlowEdge
id: 46f0cae7-aef3-4387-8c34-c8442f6008f5
name: branching_step_to_answer_end_step_control_flow_edge
description: null
metadata:
__metadata_info__: {}
from_node:
$component_ref: 6e5fcaaf-1cf2-443d-9def-14c99333be68
from_branch: default
to_node:
$component_ref: 2ae6af7c-4c67-49a8-b578-f1666466a4ca
- component_type: ControlFlowEdge
id: aec3a3d8-feba-40dd-839a-59690f17939c
name: user_tool_validation_step_to_tool_selection_branching_step_control_flow_edge
description: null
metadata:
__metadata_info__: {}
from_node:
$component_ref: e2126f15-b523-44de-a087-971799a810c2
from_branch: null
to_node:
$component_ref: 82460353-8eac-483d-967e-04fa7614d5c4
- component_type: ControlFlowEdge
id: 4506945a-6f39-4839-a910-c3eee14ad872
name: tool_selection_branching_step_to_invoke_tool_step_control_flow_edge
description: null
metadata:
__metadata_info__: {}
from_node:
$component_ref: 82460353-8eac-483d-967e-04fa7614d5c4
from_branch: execute_tool
to_node:
$component_ref: 6c170ac9-3277-4581-841a-8edf4db175e0
- component_type: ControlFlowEdge
id: eac1e546-a9e9-436b-a83b-63a74ad93bc6
name: tool_selection_branching_step_to_generate_action_step_control_flow_edge
description: null
metadata:
__metadata_info__: {}
from_node:
$component_ref: 82460353-8eac-483d-967e-04fa7614d5c4
from_branch: retry_llm
to_node:
$component_ref: d093d2ee-d8cd-40f7-9163-154d3ae72a22
- component_type: ControlFlowEdge
id: 8a20f70d-399f-41f1-8191-85502c5e947a
name: tool_selection_branching_step_to_generate_action_step_control_flow_edge
description: null
metadata:
__metadata_info__: {}
from_node:
$component_ref: 82460353-8eac-483d-967e-04fa7614d5c4
from_branch: default
to_node:
$component_ref: d093d2ee-d8cd-40f7-9163-154d3ae72a22
- component_type: ControlFlowEdge
id: 2487e15a-0f1c-4529-8b60-d21c43e1b926
name: invoke_tool_step_to_invoke_tool_end_step_control_flow_edge
description: null
metadata:
__metadata_info__: {}
from_node:
$component_ref: 6c170ac9-3277-4581-841a-8edf4db175e0
from_branch: null
to_node:
$component_ref: d326fb5d-a9b0-4845-aaba-b8f01e523471
data_flow_connections:
- component_type: DataFlowEdge
id: 3f74cc4f-237c-491d-8fd1-3ff44e08b6a8
name: get_user_name_step_tool_output_to_ask_user_request_step_username_data_flow_edge
description: null
metadata:
__metadata_info__: {}
source_node:
$component_ref: a3614787-eae2-4330-a5be-cf8bdad4544d
source_output: tool_output
destination_node:
$component_ref: 28f6f69b-aa81-49f7-be22-c51a3b0baaa5
destination_input: username
- component_type: DataFlowEdge
id: 476856ed-4b35-49e0-bb12-c29a53faf97f
name: ask_user_request_step_user_provided_input_to_generate_action_step_request_data_flow_edge
description: null
metadata:
__metadata_info__: {}
source_node:
$component_ref: 28f6f69b-aa81-49f7-be22-c51a3b0baaa5
source_output: user_provided_input
destination_node:
$component_ref: d093d2ee-d8cd-40f7-9163-154d3ae72a22
destination_input: request
- component_type: DataFlowEdge
id: c40dadcb-35e9-4b41-bae1-2960e69852ce
name: a91502a3-117f-40af-a000-3663a3db87e3_tool_info_to_generate_action_step_tools_data_flow_edge
description: null
metadata:
__metadata_info__: {}
source_node:
$component_ref: a91502a3-117f-40af-a000-3663a3db87e3
source_output: tool_info
destination_node:
$component_ref: d093d2ee-d8cd-40f7-9163-154d3ae72a22
destination_input: tools
- component_type: DataFlowEdge
id: eec02f81-55e0-42c7-b3f4-12c364c52ed2
name: generate_action_step_output_to_extract_result_step_text_data_flow_edge
description: null
metadata:
__metadata_info__: {}
source_node:
$component_ref: d093d2ee-d8cd-40f7-9163-154d3ae72a22
source_output: output
destination_node:
$component_ref: b31c569b-2a66-4f2b-a98d-f52bfca2dfeb
destination_input: text
- component_type: DataFlowEdge
id: f7e9acbe-c472-45d8-bf92-b35f436190be
name: extract_result_step_action_to_branching_step_next_step_name_data_flow_edge
description: null
metadata:
__metadata_info__: {}
source_node:
$component_ref: b31c569b-2a66-4f2b-a98d-f52bfca2dfeb
source_output: action
destination_node:
$component_ref: 6e5fcaaf-1cf2-443d-9def-14c99333be68
destination_input: next_step_name
- component_type: DataFlowEdge
id: 3a2ff915-ca72-43f3-b6a2-f9a3dbceb621
name: extract_result_step_tool_name_to_user_tool_validation_step_name_data_flow_edge
description: null
metadata:
__metadata_info__: {}
source_node:
$component_ref: b31c569b-2a66-4f2b-a98d-f52bfca2dfeb
source_output: tool_name
destination_node:
$component_ref: e2126f15-b523-44de-a087-971799a810c2
destination_input: name
- component_type: DataFlowEdge
id: 30845c9b-4b4c-4108-9b4e-4ebb9f881e32
name: extract_result_step_tool_args_to_user_tool_validation_step_params_data_flow_edge
description: null
metadata:
__metadata_info__: {}
source_node:
$component_ref: b31c569b-2a66-4f2b-a98d-f52bfca2dfeb
source_output: tool_args
destination_node:
$component_ref: e2126f15-b523-44de-a087-971799a810c2
destination_input: params
- component_type: DataFlowEdge
id: 3baa59bf-c302-434c-ac8c-55e5051db3e3
name: user_tool_validation_step_user_provided_input_to_tool_selection_branching_step_next_step_name_data_flow_edge
description: null
metadata:
__metadata_info__: {}
source_node:
$component_ref: e2126f15-b523-44de-a087-971799a810c2
source_output: user_provided_input
destination_node:
$component_ref: 82460353-8eac-483d-967e-04fa7614d5c4
destination_input: next_step_name
- component_type: DataFlowEdge
id: c0fd3d7a-9d7d-471e-962a-a99e5fb52c96
name: extract_result_step_tool_args_to_invoke_tool_step_params_data_flow_edge
description: null
metadata:
__metadata_info__: {}
source_node:
$component_ref: b31c569b-2a66-4f2b-a98d-f52bfca2dfeb
source_output: tool_args
destination_node:
$component_ref: 6c170ac9-3277-4581-841a-8edf4db175e0
destination_input: params
- component_type: DataFlowEdge
id: 9596e6a9-2b6f-4cc7-b9d8-ce778112c92d
name: get_user_name_step_tool_output_to_answer_end_step_tool_output_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: a3614787-eae2-4330-a5be-cf8bdad4544d
source_output: tool_output
destination_node:
$component_ref: 2ae6af7c-4c67-49a8-b578-f1666466a4ca
destination_input: tool_output
- component_type: DataFlowEdge
id: 16eece12-6815-479e-b47f-7b09fc400604
name: invoke_tool_step_tool_output_to_answer_end_step_tool_output_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: 6c170ac9-3277-4581-841a-8edf4db175e0
source_output: tool_output
destination_node:
$component_ref: 2ae6af7c-4c67-49a8-b578-f1666466a4ca
destination_input: tool_output
- component_type: DataFlowEdge
id: a16f467c-401a-4135-9d43-b777800e48fa
name: generate_action_step_output_to_answer_end_step_output_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: d093d2ee-d8cd-40f7-9163-154d3ae72a22
source_output: output
destination_node:
$component_ref: 2ae6af7c-4c67-49a8-b578-f1666466a4ca
destination_input: output
- component_type: DataFlowEdge
id: dd868b71-39c5-41c3-b6b0-520595600b9c
name: extract_result_step_tool_name_to_answer_end_step_tool_name_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: b31c569b-2a66-4f2b-a98d-f52bfca2dfeb
source_output: tool_name
destination_node:
$component_ref: 2ae6af7c-4c67-49a8-b578-f1666466a4ca
destination_input: tool_name
- component_type: DataFlowEdge
id: a489f8cc-3be4-435a-8a2c-1bffd290f5c2
name: extract_result_step_tool_args_to_answer_end_step_tool_args_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: b31c569b-2a66-4f2b-a98d-f52bfca2dfeb
source_output: tool_args
destination_node:
$component_ref: 2ae6af7c-4c67-49a8-b578-f1666466a4ca
destination_input: tool_args
- component_type: DataFlowEdge
id: 739bacd9-78b9-470a-9dae-f784870998c1
name: extract_result_step_action_to_answer_end_step_action_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: b31c569b-2a66-4f2b-a98d-f52bfca2dfeb
source_output: action
destination_node:
$component_ref: 2ae6af7c-4c67-49a8-b578-f1666466a4ca
destination_input: action
- component_type: DataFlowEdge
id: 9e275423-8504-4d56-8c02-229101af294c
name: ask_user_request_step_user_provided_input_to_answer_end_step_user_provided_input_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: 28f6f69b-aa81-49f7-be22-c51a3b0baaa5
source_output: user_provided_input
destination_node:
$component_ref: 2ae6af7c-4c67-49a8-b578-f1666466a4ca
destination_input: user_provided_input
- component_type: DataFlowEdge
id: da295e5e-8abb-4d16-b39b-3853e0df310d
name: user_tool_validation_step_user_provided_input_to_answer_end_step_user_provided_input_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: e2126f15-b523-44de-a087-971799a810c2
source_output: user_provided_input
destination_node:
$component_ref: 2ae6af7c-4c67-49a8-b578-f1666466a4ca
destination_input: user_provided_input
- component_type: DataFlowEdge
id: 4bc35cfb-8f77-4537-8ce6-a12f6f19a554
name: get_user_name_step_tool_output_to_invoke_tool_end_step_tool_output_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: a3614787-eae2-4330-a5be-cf8bdad4544d
source_output: tool_output
destination_node:
$component_ref: d326fb5d-a9b0-4845-aaba-b8f01e523471
destination_input: tool_output
- component_type: DataFlowEdge
id: 4a1242bb-cb58-4578-be57-4a11764f19a5
name: invoke_tool_step_tool_output_to_invoke_tool_end_step_tool_output_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: 6c170ac9-3277-4581-841a-8edf4db175e0
source_output: tool_output
destination_node:
$component_ref: d326fb5d-a9b0-4845-aaba-b8f01e523471
destination_input: tool_output
- component_type: DataFlowEdge
id: 307aef79-4a11-4bd7-8cfd-90d8ab4c5d52
name: generate_action_step_output_to_invoke_tool_end_step_output_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: d093d2ee-d8cd-40f7-9163-154d3ae72a22
source_output: output
destination_node:
$component_ref: d326fb5d-a9b0-4845-aaba-b8f01e523471
destination_input: output
- component_type: DataFlowEdge
id: c31a0fba-93c9-46a8-a21e-efdcff8d1130
name: extract_result_step_tool_name_to_invoke_tool_end_step_tool_name_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: b31c569b-2a66-4f2b-a98d-f52bfca2dfeb
source_output: tool_name
destination_node:
$component_ref: d326fb5d-a9b0-4845-aaba-b8f01e523471
destination_input: tool_name
- component_type: DataFlowEdge
id: d5ea1f13-b60a-4010-bfd9-318a81cba2f3
name: extract_result_step_tool_args_to_invoke_tool_end_step_tool_args_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: b31c569b-2a66-4f2b-a98d-f52bfca2dfeb
source_output: tool_args
destination_node:
$component_ref: d326fb5d-a9b0-4845-aaba-b8f01e523471
destination_input: tool_args
- component_type: DataFlowEdge
id: 8b3a2623-4d26-41ba-881a-8b5a566b8d7e
name: extract_result_step_action_to_invoke_tool_end_step_action_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: b31c569b-2a66-4f2b-a98d-f52bfca2dfeb
source_output: action
destination_node:
$component_ref: d326fb5d-a9b0-4845-aaba-b8f01e523471
destination_input: action
- component_type: DataFlowEdge
id: 5361e910-0b85-490a-b9bd-0613eed38037
name: ask_user_request_step_user_provided_input_to_invoke_tool_end_step_user_provided_input_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: 28f6f69b-aa81-49f7-be22-c51a3b0baaa5
source_output: user_provided_input
destination_node:
$component_ref: d326fb5d-a9b0-4845-aaba-b8f01e523471
destination_input: user_provided_input
- component_type: DataFlowEdge
id: 346f5ff8-f0a6-4b0d-9727-69a79a2f5489
name: user_tool_validation_step_user_provided_input_to_invoke_tool_end_step_user_provided_input_data_flow_edge
description: null
metadata: {}
source_node:
$component_ref: e2126f15-b523-44de-a087-971799a810c2
source_output: user_provided_input
destination_node:
$component_ref: d326fb5d-a9b0-4845-aaba-b8f01e523471
destination_input: user_provided_input
context_providers:
- $component_ref: a91502a3-117f-40af-a000-3663a3db87e3
component_plugin_name: FlowPlugin
component_plugin_version: 25.4.0.dev0
$referenced_components:
28f6f69b-aa81-49f7-be22-c51a3b0baaa5:
component_type: PluginInputMessageNode
id: 28f6f69b-aa81-49f7-be22-c51a3b0baaa5
name: ask_user_request_step
description: ''
metadata:
__metadata_info__: {}
inputs:
- description: '"username" input variable for the template'
type: string
title: username
outputs:
- description: the input value provided by the user
type: string
title: user_provided_input
branches:
- next
input_mapping: {}
output_mapping: {}
message_template: Hi {{username}}. What can I do for you today?
rephrase: false
llm_config: null
component_plugin_name: NodesPlugin
component_plugin_version: 25.4.0.dev0
a3614787-eae2-4330-a5be-cf8bdad4544d:
component_type: ExtendedToolNode
id: a3614787-eae2-4330-a5be-cf8bdad4544d
name: get_user_name_step
description: ''
metadata:
__metadata_info__: {}
inputs: []
outputs:
- type: string
title: tool_output
branches:
- next
tool:
component_type: ServerTool
id: cfd9cae9-38b9-4b48-9a52-d324899a4859
name: get_user_name_tool
description: Tool to get user name.
metadata:
__metadata_info__: {}
inputs: []
outputs:
- type: string
title: tool_output
input_mapping: {}
output_mapping: {}
raise_exceptions: false
component_plugin_name: NodesPlugin
component_plugin_version: 25.4.0.dev0
d093d2ee-d8cd-40f7-9163-154d3ae72a22:
component_type: LlmNode
id: d093d2ee-d8cd-40f7-9163-154d3ae72a22
name: generate_action_step
description: ''
metadata:
__metadata_info__: {}
inputs:
- description: '"tools" input variable for the template'
type: string
title: tools
- description: '"request" input variable for the template'
type: string
title: request
outputs:
- description: the generated text
type: string
title: output
branches:
- next
llm_config:
component_type: VllmConfig
id: 5fdf143c-a7ee-459c-8ff8-409df206e73b
name: LLAMA_MODEL_ID
description: null
metadata:
__metadata_info__: {}
default_generation_parameters: null
url: LLAMA_API_URL
model_id: LLAMA_MODEL_ID
prompt_template: "Your are an helpful assistant. Help answer the user request.\n\
\nHere is the list of tools:\n{{tools}}\n\nHere is the user request:\n{{request}}\n\
\n## Reponse format\nYour response should be JSON-compliant dictionary with\
\ the following structure.\n\n{\n \"action\": \"answer|execute_tool\",\n\
\ \"tool_name\": \"None|tool_name\",\n \"tool_args\": {\"param1\": \"\
value1\"}\n}\n\nWhen the action is \"answer\", \"tool_name\" should be \"None\"\
\ and \"tool_args\" should be {}\nWhen the action is \"execute_tool\", \"tool_name\"\
\ should be the name of the tool to execute\nand \"tool_args\" should be the\
\ JSON-compliant dictionary of arguments to pass to the tool.\n\nCRITICAL: Only\
\ output the JSON-compliant dictionary otherwise the parsing will fail.\nfail."
a91502a3-117f-40af-a000-3663a3db87e3:
component_type: PluginConstantContextProvider
id: a91502a3-117f-40af-a000-3663a3db87e3
name: a91502a3-117f-40af-a000-3663a3db87e3
description: null
metadata: {}
inputs: []
outputs:
- type: string
title: tool_info
branches:
- next
value: '[{"name": "my_tool", "description": "Params: {\"param\": str}", "parameters":
{"params": {"type": "object", "additionalProperties": {"type": "string"}, "title":
"Params"}}}]'
component_plugin_name: ContextProviderPlugin
component_plugin_version: 25.4.0.dev0
b31c569b-2a66-4f2b-a98d-f52bfca2dfeb:
component_type: PluginExtractNode
id: b31c569b-2a66-4f2b-a98d-f52bfca2dfeb
name: extract_result_step
description: ''
metadata:
__metadata_info__: {}
inputs:
- description: raw text to extract information from
type: string
title: text
outputs:
- type: string
title: action
- type: string
title: tool_name
- type: object
additionalProperties:
type: string
key_type:
type: string
title: tool_args
branches:
- next
input_mapping: {}
output_mapping: {}
output_values:
action: .action
tool_name: .tool_name
tool_args: .tool_args
component_plugin_name: NodesPlugin
component_plugin_version: 25.4.0.dev0
6e5fcaaf-1cf2-443d-9def-14c99333be68:
component_type: BranchingNode
id: 6e5fcaaf-1cf2-443d-9def-14c99333be68
name: branching_step
description: ''
metadata:
__metadata_info__: {}
inputs:
- description: Next branch name in the flow
type: string
title: next_step_name
default: default
outputs: []
branches:
- answer
- default
- execute_tool
mapping:
answer: answer
execute_tool: execute_tool
e2126f15-b523-44de-a087-971799a810c2:
component_type: PluginInputMessageNode
id: e2126f15-b523-44de-a087-971799a810c2
name: user_tool_validation_step
description: ''
metadata:
__metadata_info__: {}
inputs:
- description: '"name" input variable for the template'
type: string
title: name
- description: '"params" input variable for the template'
type: string
title: params
outputs:
- description: the input value provided by the user
type: string
title: user_provided_input
branches:
- next
input_mapping: {}
output_mapping: {}
message_template: Requesting to invoke tool {{name}} with parameters {{params}}.
Do you accept the request? (y/n)
rephrase: false
llm_config: null
component_plugin_name: NodesPlugin
component_plugin_version: 25.4.0.dev0
82460353-8eac-483d-967e-04fa7614d5c4:
component_type: BranchingNode
id: 82460353-8eac-483d-967e-04fa7614d5c4
name: tool_selection_branching_step
description: ''
metadata:
__metadata_info__: {}
inputs:
- description: Next branch name in the flow
type: string
title: next_step_name
default: default
outputs: []
branches:
- default
- execute_tool
- retry_llm
mapping:
y: execute_tool
n: retry_llm
6c170ac9-3277-4581-841a-8edf4db175e0:
component_type: ExtendedToolNode
id: 6c170ac9-3277-4581-841a-8edf4db175e0
name: invoke_tool_step
description: ''
metadata:
__metadata_info__: {}
inputs:
- type: object
additionalProperties:
type: string
title: params
outputs:
- type: string
title: tool_output
branches:
- next
tool:
component_type: ServerTool
id: 5886e17c-c2c5-400d-9bf1-fdfe8490c35b
name: my_tool
description: 'Params: {"param": str}'
metadata:
__metadata_info__: {}
inputs:
- type: object
additionalProperties:
type: string
title: params
outputs:
- type: string
title: tool_output
input_mapping: {}
output_mapping: {}
raise_exceptions: false
component_plugin_name: NodesPlugin
component_plugin_version: 25.4.0.dev0
2ae6af7c-4c67-49a8-b578-f1666466a4ca:
component_type: EndNode
id: 2ae6af7c-4c67-49a8-b578-f1666466a4ca
name: answer_end_step
description: null
metadata:
__metadata_info__: {}
inputs:
- type: string
title: tool_output
- description: the generated text
type: string
title: output
- type: string
title: tool_name
- type: object
additionalProperties:
type: string
key_type:
type: string
title: tool_args
- type: string
title: action
- description: the input value provided by the user
type: string
title: user_provided_input
outputs:
- type: string
title: tool_output
- description: the generated text
type: string
title: output
- type: string
title: tool_name
- type: object
additionalProperties:
type: string
key_type:
type: string
title: tool_args
- type: string
title: action
- description: the input value provided by the user
type: string
title: user_provided_input
branches: []
branch_name: answer_end_step
d326fb5d-a9b0-4845-aaba-b8f01e523471:
component_type: EndNode
id: d326fb5d-a9b0-4845-aaba-b8f01e523471
name: invoke_tool_end_step
description: null
metadata:
__metadata_info__: {}
inputs:
- type: string
title: tool_output
- description: the generated text
type: string
title: output
- type: string
title: tool_name
- type: object
additionalProperties:
type: string
key_type:
type: string
title: tool_args
- type: string
title: action
- description: the input value provided by the user
type: string
title: user_provided_input
outputs:
- type: string
title: tool_output
- description: the generated text
type: string
title: output
- type: string
title: tool_name
- type: object
additionalProperties:
type: string
key_type:
type: string
title: tool_args
- type: string
title: action
- description: the input value provided by the user
type: string
title: user_provided_input
branches: []
branch_name: invoke_tool_end_step
df2e111a-b6ac-4c66-8d57-99e0b9c94fdd:
component_type: StartNode
id: df2e111a-b6ac-4c66-8d57-99e0b9c94fdd
name: start
description: ''
metadata:
__metadata_info__: {}
inputs: []
outputs: []
branches:
- next
agentspec_version: 25.4.1
You can then load the configuration back to an assistant using the AgentSpecLoader
.
from wayflowcore.agentspec import AgentSpecLoader
print(config)
new_flow = AgentSpecLoader(
tool_registry={
'get_user_name_tool': get_user_name_tool,
'my_tool': my_tool
}
).load_json(config)
Note
This guide uses the following extension/plugin Agent Spec components:
PluginInputMessageNode
PluginConstantContextProvider
PluginExtractNode
ExtendedToolNode
ExtendedFlow
See the list of available Agent Spec extension/plugin components in the API Reference
Next steps#
In this guide, you learned how to request and handle user input and approval inside WayFlow flows using InputMessageStep
, as well as how to combine input with branching for selective actions. 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 Universal Permissive License
4# %%[markdown]
5# Code Example - How to Ask for User Input in Flows
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_userinputinflows.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# (UPL) 1.0 (LICENSE-UPL or https://oss.oracle.com/licenses/upl) or Apache License
26# 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0), at your option.
27
28
29
30# %%[markdown]
31## Create LLM
32
33# %%
34from wayflowcore.models import VllmModel
35
36llm = VllmModel(
37 model_id="LLAMA_MODEL_ID",
38 host_port="LLAMA_API_URL",
39)
40
41# %%[markdown]
42## Create Simple Flow
43
44# %%
45from wayflowcore.controlconnection import ControlFlowEdge
46from wayflowcore.dataconnection import DataFlowEdge
47from wayflowcore.flow import Flow
48from wayflowcore.steps import (
49 BranchingStep,
50 CompleteStep,
51 ExtractValueFromJsonStep,
52 InputMessageStep,
53 PromptExecutionStep,
54 StartStep,
55 ToolExecutionStep,
56)
57from wayflowcore.tools import tool
58
59@tool(description_mode="only_docstring")
60def get_user_name_tool() -> str:
61 """Tool to get user name."""
62 return "Alice"
63
64start_step = StartStep(name="start")
65
66get_user_name_step = ToolExecutionStep(
67 name="get_user_name_step",
68 tool=get_user_name_tool,
69)
70
71ask_user_request_step = InputMessageStep(
72 name="ask_user_request_step", message_template="Hi {{username}}. What can I do for you today?"
73)
74
75answer_request_step = PromptExecutionStep(
76 name="answer_request_step",
77 llm=llm,
78 prompt_template="Your are an helpful assistant. Help answer the user request: {{request}}",
79 output_mapping={
80 PromptExecutionStep.OUTPUT: "my_output"
81 }, # what we want to expose as the output name
82)
83
84end_step = CompleteStep(name="end")
85
86flow = Flow(
87 begin_step=start_step,
88 control_flow_edges=[
89 ControlFlowEdge(start_step, get_user_name_step),
90 ControlFlowEdge(get_user_name_step, ask_user_request_step),
91 ControlFlowEdge(ask_user_request_step, answer_request_step),
92 ControlFlowEdge(answer_request_step, end_step),
93 ],
94 data_flow_edges=[
95 DataFlowEdge(
96 get_user_name_step, ToolExecutionStep.TOOL_OUTPUT, ask_user_request_step, "username"
97 ),
98 DataFlowEdge(
99 ask_user_request_step,
100 InputMessageStep.USER_PROVIDED_INPUT,
101 answer_request_step,
102 "request",
103 ),
104 ],
105)
106
107# %%[markdown]
108## Execute Simple Flow
109
110# %%
111from wayflowcore.executors.executionstatus import FinishedStatus, UserMessageRequestStatus
112conversation = flow.start_conversation()
113status = (
114 conversation.execute()
115) # will get the user input, then pause the execution to ask for the user input
116
117if not isinstance(status, UserMessageRequestStatus):
118 raise ValueError(
119 f"Execution status should be {UserMessageRequestStatus.__name__}, was {type(status)}"
120 )
121print(conversation.get_last_message().content)
122# Hi Alice. What can I do for you today?
123
124conversation.append_user_message("What is heavier? 20 pounds of bricks of 20 feathers?")
125status = conversation.execute() # we resume the execution
126
127if not isinstance(status, FinishedStatus):
128 raise ValueError(f"Execution status should be {FinishedStatus.__name__}, was {type(status)}")
129print(
130 status.output_values["my_output"]
131) # using the key name that we defined in the `output_mapping`
132# [...] a surprisingly simple answer emerges: 20 pounds of bricks is heavier than 20 feathers by a massive margin, approximately 69.78 pounds.
133
134# %%[markdown]
135## Create Complex Flow
136
137# %%
138import json
139from typing import Dict
140
141from wayflowcore.contextproviders.constantcontextprovider import ConstantContextProvider
142from wayflowcore.property import DictProperty, StringProperty
143
144@tool(description_mode="only_docstring")
145def my_tool(params: Dict[str, str]) -> str:
146 """Params: {"param": str}"""
147 return f"Invoked tool with {params=}"
148
149prompt_template = """
150Your are an helpful assistant. Help answer the user request.
151
152Here is the list of tools:
153{{tools}}
154
155Here is the user request:
156{{request}}
157
158## Reponse format
159Your response should be JSON-compliant dictionary with the following structure.
160
161{
162 "action": "answer|execute_tool",
163 "tool_name": "None|tool_name",
164 "tool_args": {"param1": "value1"}
165}
166
167When the action is "answer", "tool_name" should be "None" and "tool_args" should be {}
168When the action is "execute_tool", "tool_name" should be the name of the tool to execute
169and "tool_args" should be the JSON-compliant dictionary of arguments to pass to the tool.
170
171CRITICAL: Only output the JSON-compliant dictionary otherwise the parsing will fail.
172fail.
173""".strip()
174
175available_tools = [my_tool]
176tool_context_provider = ConstantContextProvider(
177 json.dumps([tool_.to_dict() for tool_ in available_tools]),
178 output_description=StringProperty("tool_info"),
179)
180
181generate_action_step = PromptExecutionStep(
182 name="generate_action_step", llm=llm, prompt_template=prompt_template
183)
184
185extract_result_step = ExtractValueFromJsonStep(
186 name="extract_result_step",
187 output_values={
188 "action": ".action",
189 "tool_name": ".tool_name",
190 "tool_args": ".tool_args",
191 },
192 output_descriptors=[
193 StringProperty(name='action'),
194 StringProperty(name='tool_name'),
195 DictProperty(name='tool_args'),
196 ]
197)
198
199branching_step = BranchingStep(
200 name="branching_step", branch_name_mapping={"answer": "answer", "execute_tool": "execute_tool"}
201)
202
203answer_end_step = CompleteStep(name="answer_end_step")
204
205user_tool_validation_step = InputMessageStep(
206 name="user_tool_validation_step",
207 message_template="Requesting to invoke tool {{name}} with parameters {{params}}. Do you accept the request? (y/n)",
208)
209
210tool_selection_branching_step = BranchingStep(
211 name="tool_selection_branching_step",
212 branch_name_mapping={"y": "execute_tool", "n": "retry_llm"},
213)
214
215invoke_tool_step = ToolExecutionStep(
216 name="invoke_tool_step",
217 tool=my_tool,
218)
219
220invoke_tool_end_step = CompleteStep(name="invoke_tool_end_step")
221
222flow = Flow(
223 begin_step=start_step,
224 control_flow_edges=[
225 ControlFlowEdge(start_step, get_user_name_step),
226 ControlFlowEdge(get_user_name_step, ask_user_request_step),
227 ControlFlowEdge(ask_user_request_step, generate_action_step),
228 ControlFlowEdge(generate_action_step, extract_result_step),
229 ControlFlowEdge(extract_result_step, branching_step),
230 ControlFlowEdge(branching_step, answer_end_step, source_branch="answer"),
231 ControlFlowEdge(branching_step, user_tool_validation_step, source_branch="execute_tool"),
232 ControlFlowEdge(
233 branching_step, answer_end_step, source_branch=BranchingStep.BRANCH_DEFAULT
234 ),
235 ControlFlowEdge(user_tool_validation_step, tool_selection_branching_step),
236 ControlFlowEdge(
237 tool_selection_branching_step, invoke_tool_step, source_branch="execute_tool"
238 ),
239 ControlFlowEdge(
240 tool_selection_branching_step, generate_action_step, source_branch="retry_llm"
241 ),
242 ControlFlowEdge(
243 tool_selection_branching_step,
244 generate_action_step,
245 source_branch=BranchingStep.BRANCH_DEFAULT,
246 ),
247 ControlFlowEdge(invoke_tool_step, invoke_tool_end_step),
248 ],
249 data_flow_edges=[
250 DataFlowEdge(
251 get_user_name_step, ToolExecutionStep.TOOL_OUTPUT, ask_user_request_step, "username"
252 ),
253 DataFlowEdge(
254 ask_user_request_step,
255 InputMessageStep.USER_PROVIDED_INPUT,
256 generate_action_step,
257 "request",
258 ),
259 DataFlowEdge(tool_context_provider, "tool_info", generate_action_step, "tools"),
260 DataFlowEdge(
261 generate_action_step,
262 PromptExecutionStep.OUTPUT,
263 extract_result_step,
264 ExtractValueFromJsonStep.TEXT,
265 ),
266 DataFlowEdge(extract_result_step, "action", branching_step, BranchingStep.NEXT_BRANCH_NAME),
267 DataFlowEdge(extract_result_step, "tool_name", user_tool_validation_step, "name"),
268 DataFlowEdge(extract_result_step, "tool_args", user_tool_validation_step, "params"),
269 DataFlowEdge(
270 user_tool_validation_step,
271 InputMessageStep.USER_PROVIDED_INPUT,
272 tool_selection_branching_step,
273 BranchingStep.NEXT_BRANCH_NAME,
274 ),
275 DataFlowEdge(extract_result_step, "tool_args", invoke_tool_step, "params"),
276 ],
277)
278
279# %%[markdown]
280## Execute Complex Flow
281
282# %%
283conversation = flow.start_conversation()
284status = (
285 conversation.execute()
286) # will get the user input, then pause the execution to ask for the user input
287
288if not isinstance(status, UserMessageRequestStatus):
289 raise ValueError(
290 f"Execution status should be {UserMessageRequestStatus.__name__}, was {type(status)}"
291 )
292print(conversation.get_last_message().content)
293# Hi Alice. What can I do for you today?
294
295conversation.append_user_message("Invoke the tool with parameter 'value#007'")
296status = conversation.execute() # we resume the execution
297
298if not isinstance(status, UserMessageRequestStatus):
299 raise ValueError(
300 f"Execution status should be {UserMessageRequestStatus.__name__}, was {type(status)}"
301 )
302print(conversation.get_last_message().content)
303# Requesting to invoke tool my_tool with parameters {"param": "value#007"}. Do you accept the request? (y/n)
304
305conversation.append_user_message("y") # we accept the tool call request
306status = conversation.execute() # we resume the execution
307
308if not isinstance(status, FinishedStatus):
309 raise ValueError(f"Execution status should be {FinishedStatus.__name__}, was {type(status)}")
310
311print(status.output_values[ToolExecutionStep.TOOL_OUTPUT])
312# Invoked tool with params={'param': 'value#007'}
313
314
315# %%[markdown]
316## Export Config to Agent Spec
317
318# %%
319from wayflowcore.agentspec import AgentSpecExporter
320
321config = AgentSpecExporter().to_json(flow)
322
323# %%[markdown]
324## Load Agent Spec Config
325
326# %%
327from wayflowcore.agentspec import AgentSpecLoader
328
329print(config)
330new_flow = AgentSpecLoader(
331 tool_registry={
332 'get_user_name_tool': get_user_name_tool,
333 'my_tool': my_tool
334 }
335).load_json(config)