How to Change Input and Output Descriptors of Components#
Prerequisites
This guide assumes familiarity with Flows.
WayFlow components such as Agents, Flows, and Steps accept inputs and produce outputs.
These inputs and outputs allow you to pass values to be used, and return some new values.
You can inspect the input/output descriptors on classes that inherit from ComponentWithInputsOutputs
by accessing the input_descriptors
and output_descriptors
attributes, respectively.
See the Property API documentation to learn more about the IO typing system operations.
Sometimes, it is helpful to change their description, either because the type is not specific enough, or if you want to specify a default value.
This guide will show you how to override the default input and output descriptions of Agents, Flows, or Steps.
Basic implementation#
When creating a step, input and output descriptors are automatically detected based on the step’s configuration.
from wayflowcore.steps import InputMessageStep
step = InputMessageStep(
message_template="You're trying to connect to {{service}}. Please enter your username:"
)
print("Input descriptors: ", *step.input_descriptors)
# Input descriptors: StringProperty(name="service", description=""service" input variable for the template")
print("Output descriptors: ", *step.output_descriptors)
# Output descriptors: StringProperty(name="user_provided_input", description="the input value provided by the user")
In this case, the input descriptor service
does not have a default value, and the description is not very informative.
To improve the user experience, you can provide a more informative description and set a default value by overriding the input descriptors:
from wayflowcore.property import StringProperty
from wayflowcore.steps import InputMessageStep
step = InputMessageStep(
message_template="You're trying to connect to {{service}}. Please enter your username:",
input_descriptors=[
StringProperty(
name="service",
description="service to which the user wants to connect to",
default_value="OCI",
)
],
)
print("Input descriptors: ", *step.input_descriptors)
# Input descriptors: StringProperty(name="service", description="service to which the user wants to connect to", default_value="OCI")
Note
Since a step requires specific variables to work well, the overriding descriptor must have the same name
as the original descriptor.
The same process can be applied to output descriptors.
Refining a type#
In certain situations, the automatic detection of input and output types may not determine the appropriate type for a variable.
For example, consider the following step where an AnyProperty
input is detected:
step = InputMessageStep(
message_template="Here are some snacks: {% for snack in snacks %}{{snack}}{% endfor %}. Which one is your favorite?",
)
print("Input descriptors: ", *step.input_descriptors)
# Input descriptors: AnyProperty(name="snacks", description=""snacks" input variable for the template")
Here, the service input is expected to be a list.
To improve clarity, you can override the AnyProperty
descriptor to specify the expected type:
from wayflowcore.property import ListProperty
step = InputMessageStep(
message_template="Here are some snacks: {% for snack in snacks %}{{snack}}{% endfor %}. Which one is your favorite?",
input_descriptors=[
ListProperty(
name="snacks",
description="list of snacks",
item_type=StringProperty(),
)
],
)
print("Input descriptors: ", *step.input_descriptors)
# Input descriptors: ListProperty(name="snacks", item=StringProperty(), description="list of snacks")
Note
Currently, type validation is not implemented. When overriding a descriptor’s type, make sure to specify the correct type to prevent runtime crashes during step execution.
Changing the name of a descriptor#
Sometimes, the default name of an input or output descriptor can be complex or unclear.
In this case, you can not just modify the names of the input_descriptors
or output_descriptors
, as these names are integral to mapping between new and default descriptors.
You can still rename the input or output descriptor of a Step
by using input_mapping
or output_mapping
.
These mappings associate the default descriptor names (keys) with the desired new names (values).
The associated input_descriptors
and output_descriptors
need to reflect these new names accordingly.
step = InputMessageStep(
message_template="Hi {{unclear_var_name}}. How are you doing?",
input_descriptors=[StringProperty(name="username")],
input_mapping={"unclear_var_name": "username"},
)
print("Input descriptors: ", *step.input_descriptors)
# Input descriptors: StringProperty(name="username")
Without providing the input_mapping
value, the step will not recognize the input descriptor name and will raise an error.
step = InputMessageStep(
message_template="Hi {{unclear_var_name}}. How are you doing?",
input_descriptors=[StringProperty(name="username", description="name of the current user")],
)
# ValueError: Unknown input descriptor specified: StringProperty(name='username', description='name of the current user'). Make sure there is no misspelling.
# Expected input descriptors are: [StringProperty(name='unclear_var_name', description='"unclear_var_name" input variable for the template')]
Agent Spec Exporting/Loading#
You can export the step configuration to its Agent Spec configuration using the AgentSpecExporter
.
from wayflowcore.agentspec import AgentSpecExporter
config = AgentSpecExporter().to_json(step)
Here is what the Agent Spec representation will look like ↓
Click here to see the assistant configuration.
{
"component_type": "PluginInputMessageNode",
"id": "c7f3b49e-0db5-45b6-9a18-42c565230dc9",
"name": "step_7137de34",
"description": "",
"metadata": {
"__metadata_info__": {}
},
"inputs": [
{
"type": "string",
"title": "username"
}
],
"outputs": [
{
"description": "the input value provided by the user",
"type": "string",
"title": "user_provided_input"
}
],
"branches": [
"next"
],
"input_mapping": {
"unclear_var_name": "username"
},
"output_mapping": {},
"message_template": "Hi {{unclear_var_name}}. How are you doing?",
"rephrase": false,
"llm_config": null,
"component_plugin_name": "NodesPlugin",
"component_plugin_version": "25.4.0.dev0",
"agentspec_version": "25.4.1"
}
component_type: PluginInputMessageNode
id: c7f3b49e-0db5-45b6-9a18-42c565230dc9
name: step_7137de34
description: ''
metadata:
__metadata_info__: {}
inputs:
- type: string
title: username
outputs:
- description: the input value provided by the user
type: string
title: user_provided_input
branches:
- next
input_mapping:
unclear_var_name: username
output_mapping: {}
message_template: Hi {{unclear_var_name}}. How are you doing?
rephrase: false
llm_config: null
component_plugin_name: NodesPlugin
component_plugin_version: 25.4.0.dev0
agentspec_version: 25.4.1
You can then load the configuration back to an assistant using the AgentSpecLoader
.
from wayflowcore.agentspec import AgentSpecLoader
new_step = AgentSpecLoader().load_json(config)
Note
This guide uses the following extension/plugin Agent Spec components:
PluginInputMessageNode
See the list of available Agent Spec extension/plugin components in the API Reference
Next steps#
Having learned how to override the default input and output descriptions of a component, 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# WayFlow Code Example - How to change input and output descriptors of Components
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_io_descriptors.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
31# %%[markdown]
32## Auto IO detection
33
34# %%
35from wayflowcore.steps import InputMessageStep
36
37step = InputMessageStep(
38 message_template="You're trying to connect to {{service}}. Please enter your username:"
39)
40print("Input descriptors: ", *step.input_descriptors)
41# Input descriptors: StringProperty(name="service", description=""service" input variable for the template")
42print("Output descriptors: ", *step.output_descriptors)
43# Output descriptors: StringProperty(name="user_provided_input", description="the input value provided by the user")
44
45# %%[markdown]
46## Specify input descriptor:
47
48# %%
49from wayflowcore.property import StringProperty
50from wayflowcore.steps import InputMessageStep
51
52step = InputMessageStep(
53 message_template="You're trying to connect to {{service}}. Please enter your username:",
54 input_descriptors=[
55 StringProperty(
56 name="service",
57 description="service to which the user wants to connect to",
58 default_value="OCI",
59 )
60 ],
61)
62print("Input descriptors: ", *step.input_descriptors)
63# Input descriptors: StringProperty(name="service", description="service to which the user wants to connect to", default_value="OCI")
64
65# %%[markdown]
66## Default any descriptor
67
68# %%
69step = InputMessageStep(
70 message_template="Here are some snacks: {% for snack in snacks %}{{snack}}{% endfor %}. Which one is your favorite?",
71)
72print("Input descriptors: ", *step.input_descriptors)
73# Input descriptors: AnyProperty(name="snacks", description=""snacks" input variable for the template")
74
75# %%[markdown]
76## List descriptor
77
78# %%
79from wayflowcore.property import ListProperty
80
81step = InputMessageStep(
82 message_template="Here are some snacks: {% for snack in snacks %}{{snack}}{% endfor %}. Which one is your favorite?",
83 input_descriptors=[
84 ListProperty(
85 name="snacks",
86 description="list of snacks",
87 item_type=StringProperty(),
88 )
89 ],
90)
91print("Input descriptors: ", *step.input_descriptors)
92# Input descriptors: ListProperty(name="snacks", item=StringProperty(), description="list of snacks")
93
94# %%[markdown]
95## Rename a descriptor
96
97# %%
98step = InputMessageStep(
99 message_template="Hi {{unclear_var_name}}. How are you doing?",
100 input_descriptors=[StringProperty(name="username")],
101 input_mapping={"unclear_var_name": "username"},
102)
103print("Input descriptors: ", *step.input_descriptors)
104# Input descriptors: StringProperty(name="username")
105
106# %%[markdown]
107## Export config to Agent Spec
108
109# %%
110from wayflowcore.agentspec import AgentSpecExporter
111
112config = AgentSpecExporter().to_json(step)
113
114# %%[markdown]
115## Load Agent Spec config
116
117# %%
118from wayflowcore.agentspec import AgentSpecLoader
119
120new_step = AgentSpecLoader().load_json(config)
121