> For the complete documentation index, see llms.txt.
Skip to main content

Check out Port for yourself ➜ 

Input nodes

Input nodes pause a workflow and wait for a response before it continues. Use them to add human-in-the-loop steps such as approvals, manual gates, and decision points that require extra input.

When the workflow reaches an input node, the node stays in progress and notifies the responders you defined. Each responder opens the run, fills in a form, and clicks one of the node's buttons. Like condition nodes, an input node branches: it routes the workflow down a different path depending on which button responders press and how many of them respond.

How it works

The lifecycle of an input node is:

  1. The workflow reaches the input node, which enters an in progress state and pauses the run on that branch.
  2. Port notifies the configured responders (by email and/or webhook).
  3. A responder opens the run, clicks Provide inputs, fills in the form fields, and clicks one of the submit buttons.
  4. Port records the response and re-evaluates the node's outlets.
  5. When an outlet reaches its required number of responders, the node completes and the workflow continues down that outlet's path.

Example

The following input node asks responders to approve or decline, and continues on the approve path only after two approvals, or on the decline path after a single decline:

{
"identifier": "inputNode",
"title": "Approve/Decline",
"config": {
"type": "INPUT",
"description": "Approve or decline the production deployment.",
"userInputs": {
"properties": {
"reason": {
"type": "string",
"title": "Reason",
"description": "The reason for the approve/decline."
}
},
"buttons": [
{
"identifier": "approve",
"label": "Approve",
"variant": "PRIMARY"
},
{
"identifier": "decline",
"label": "Decline",
"variant": "DANGER"
}
]
},
"outlets": [
{
"evaluationMethod": "button",
"identifier": "approve",
"title": "Approve",
"numOfResponders": 2
},
{
"evaluationMethod": "button",
"identifier": "decline",
"title": "Decline",
"numOfResponders": 1
}
],
"responders": {
"users": ["alice@example.com", "bob@example.com"]
}
}
}

Configuration

An input node is defined by a config object with "type": "INPUT" and the following fields:

FieldRequiredDescription
typeYesMust be "INPUT".
descriptionNoA short explanation shown to responders describing what they are responding to.
userInputsYesThe form responders fill in, plus the submit buttons. See user inputs below.
outletsYesThe branches the node can continue on, and how many responders each branch requires. See outlets below.
respondersNoThe users who are notified and allowed to respond. See responders below.
notificationsNoWhere Port sends notifications when the node is reached. See notifications below.

User inputs

userInputs defines two things:

  • properties - the form fields shown to responders. These use the same schema as self-service user inputs, so you can collect text, numbers, entities, and any other supported input type.
  • buttons - the submit buttons shown in the footer of the form. Each button records a different kind of response (for example, Approve or Decline).

Each button has the following fields:

FieldRequiredDescription
identifierYesA unique identifier for the button. Outlets reference this value.
labelYesThe text shown on the button.
variantYesThe button's visual style: PRIMARY, SECONDARY, or DANGER.
iconNoAn optional icon to display on the button.
Button identifiers must be unique

Each button's identifier must be unique within the node, and every outlet must reference a valid button identifier.

Outlets

The node stays in progress until one of its outlets is satisfied. Each outlet maps to a button and defines how many responders must press that button before the workflow continues down its path.

In the example above, the node continues on the approve path after 2 approvals, or on the decline path after a single decline.

Each outlet has the following fields:

FieldRequiredDescription
evaluationMethodYesHow the outlet is evaluated. Currently "button" is supported.
identifierYesMust match the identifier of one of the node's buttons.
titleNoA human-readable name for the outlet, shown in the graph.
numOfRespondersYesThe number of responses on this button required to continue down this path. Must be a positive integer.
statusLabelNoA label applied to the node run when this outlet is taken. Has a text field (supports JQ) and an optional variant of success or alert.
workflowStatusLabelNoSame as statusLabel, but applied to the entire workflow run.
How outlets are evaluated

Port tallies responses per button. After each response, it checks the outlets in the order they are defined and continues on the first outlet whose numOfResponders threshold has been reached. Outlet identifiers must be unique within the node.

Responders

responders defines who is notified and allowed to respond to the node. Responders are specified by users, a list of user emails:

{
"responders": {
"users": ["alice@example.com", "bob@example.com"]
}
}
One response per responder

Each responder can submit a response only once. Attempting to respond again returns an error.

Notifications

notifications controls where Port sends a notification when the node is reached. It is an array of targets, each of which is one of:

  • An email target, with a list of fields (each a label and value) to include in the notification.
  • A webhook target, used to notify an external system. It supports url, method (defaults to POST), and optional headers and body.
{
"notifications": [
{
"target": "email",
"fields": [
{ "label": "Service", "value": ".outputs.trigger.serviceName" }
]
},
{
"target": "webhook",
"url": "https://example.com/notify",
"method": "POST",
"body": { "message": "An input node is awaiting your response" }
}
]
}

Responders specified under responders.users are automatically notified by email, in addition to any targets you define here.

Connections

Like condition nodes, connections from an input node must specify which outlet they belong to, using sourceOutletIdentifier:

{
"connections": [
{
"sourceIdentifier": "inputNode",
"targetIdentifier": "production-deploy",
"sourceOutletIdentifier": "approve"
},
{
"sourceIdentifier": "inputNode",
"targetIdentifier": "sendSlack",
"sourceOutletIdentifier": "decline"
}
]
}

Each sourceOutletIdentifier must reference a valid outlet identifier on the node.

Outputs

An input node produces the following outputs, which subsequent nodes can reference through data flow:

  • selectedOutlet.identifier - the identifier of the outlet the node continued on (for example, approve).
  • responses - the list of submitted responses. Each response includes the button that was pressed (buttonIdentifier), the submitted form values (inputs), and submitter information (submitterInfo with submittedBy and createdAt).

For example, to branch on the chosen outlet in a downstream node:

{{ .outputs["inputNode"].selectedOutlet.identifier }}

To reference a value a responder submitted in the form:

{{ .outputs["inputNode"].responses[0].inputs.reason }}