How to Change Input and Output Descriptors of Components#

python-icon Download Python Script

Python script/notebook for this guide.

IO descriptors how-to script

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"
}

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