SynapseOrch 2.0 is a release candidate; the stable release is 1.9.3. How to try 2.0

Human Gates

A human gate is an orchestration step that pauses execution and waits for a human to provide input before continuing. This enables approval workflows, data collection, review processes, and any scenario where a human decision is required mid-pipeline.

The screens, step by step: Workflows, in the Guides.

How it works

  1. The workflow reaches a human step
  2. Execution pauses — the run status becomes paused
  3. Someone answers: on the run's page, on Home, on the workflow canvas, in Chat, in a messaging channel, through Synapse AI, over MCP, or through the API
  4. The answer is written to state
  5. Execution continues from the step after the gate

The paused state is checkpointed to the store, so the run survives a backend restart and resumes where it stopped. See Reattach and resume.

Configuring a human step

{
  "id": "step-review",
  "type": "human",
  "name": "Review Draft",
  "human_prompt": "Please review the draft and provide your feedback.\n\n{{ state.draft }}",
  "human_fields": [
    { "name": "decision", "type": "string", "label": "Decision" },
    { "name": "feedback", "type": "string", "label": "Feedback" },
    { "name": "priority", "type": "number", "label": "Priority" }
  ],
  "input_keys": ["draft"],
  "output_key": "review",
  "next_step_id": "step-process-feedback"
}

The prompt fills in {{ state.key }}, nested paths too ({{ state.review.feedback }}); the older single-brace {state.key} is read the same way. The value of the first input key that has one is shown to the person as context above the question, captioned with the key it came from — From draft.

Field types

Fields are optional. In the step panel each has a name, a type and a label:

Type in the panelStored asThe form showsThe answer holds
TextstringA text boxText
Long texttextareaA larger text boxText
NumbernumberA number boxA number
Yes / NobooleanA checkboxtrue or false
EmailemailAn email boxAn email address, trimmed
DatedateA date pickerA date, as YYYY-MM-DD
PhonephoneA phone boxA phone number
Dropdownchoice, with its optionsA list to pick fromOne of the options, as the step wrote it

The canvas and Chat both show the fields as a form, labelled with each field's label, and the answer arrives as an object keyed by each field's name. A Dropdown's options are typed in the panel, comma-separated. An answer to an Email, Date, Phone or Dropdown field must be one, or it is refused, naming the field, and the run keeps waiting; Text, Long text, Number and Yes / No are taken as they come. A field left blank is still an answer.

Messaging notification

Pick a channel in the panel's Notify messaging channel setting, human_channel_id in JSON, to ask the question in that messaging channel as well as in the app. When the run pauses, the prompt is posted as ⏸ <prompt> followed by "Reply here to answer."

It goes to the channel's notification chat, notify_chat_id, if one is set on the channel (the Channels screen has no field for it), and otherwise to the conversation somebody last wrote in on that channel. So someone must have messaged the bot there at least once, or a notification chat must be set; with neither, nothing is posted. Messaging must be enabled, and so must the channel.

A reply in that channel answers the newest run waiting on it and resumes the run, as Answer on the canvas would — also for a run a scale mode worker ran, and after a restart. The bot confirms with "✅ Answer received — resuming the workflow." While a run waits, the next message a workspace user sends the bot on that channel is taken as the answer rather than passed to the channel's agent. A visitor's message is an ordinary message, passed to the agent.

Whichever answer arrives first, from the channel or from the app, resumes the run; a later one is refused because the run is no longer waiting. Two answers that arrive at the same moment — a double-click, or the app and the channel together — resume it once too: one is applied and the other is dropped, even when both were acknowledged. A Human step inside a nested workflow asks and is answered the same way — and each question it asks is its own question, so an answer queued behind another never lands on the one after it.

Cancelling a waiting run. A cancelled run stops asking: the answer strip goes, and an answer sent to it is refused. The question is closed off in the run's timeline where it stood, so its wait stops counting against the clock. In the bell it reads cancelled, a notification that it was cancelled arrives — Weekly report cancelled, and reopening the run does not ask again.

PlatformQuestion postedA reply answers
Telegram, Slack, DiscordYes, from the API server or a workerYes
WhatsAppOnly when the API server is running the channel's adapterYes
TeamsNo — Teams can't post first; answer in the appYes

human_timeout_seconds (default 3600, or SYNAPSE_ORCH_HUMAN_TIMEOUT) appears as Timeout (seconds) when a channel is selected: how long a reply in the channel answers the question. After it, a reply there is refused — That question timed out — answer it from the app instead. — and the run waits for an answer in the app.

A gate waits indefinitely

There is no timer on the gate itself; the channel's timeout above only ends the channel's part. The run is checkpointed and sits there until somebody answers — days later, across restarts, is fine. That is usually what you want from an approval step, but it does mean a forgotten gate holds a run open rather than failing it. On Runs, runs waiting on a gate are under Needs you, and the waiting step reads Needs input.

Answering

A waiting run is answered where you read it. Each place shows the question, what it is about (From this run, or the state key it names), and the answer: the step's own fields when it declared any, else a box for your answer and Send answer. A step whose fields hold exactly one yes/no is an approval, answered with two buttons: the field's own label, and Decline.

On Home, Needs you holds the Weekly bean order run, waiting at its Sign off the order step. A note for the roaster is typed and Send the order pressed: the answer is sent and the run resumes.
  • On Home, Needs you lists every run waiting for a person, each answered in place.
  • From any page, the menu's Waiting on you row, shown while something waits, opens the same list in a drawer.
  • On the run's page, the question sits above the steps.
  • On the canvas, the waiting step glows, and its setup card holds the question: type and press Enter to send (Shift Enter for a new line).
  • In the bell, an item per question opens it.
  • In Chat, a run started from Chat shows the question in the conversation, with the form if the step has fields. Submit the form, or type your answer in the message box.
  • In a messaging channel, reply to the question the step posted — see Messaging notification.
  • Through Synapse AI, ask what waits on you: it shows the run's own question card, answered the same way.
  • Over MCP, a client calls answer_run, and list_waiting lists what waits — see Connect an AI client over MCP.
  • Through the API: POST /api/v1/orchestrations/runs/{run_id}/resume — see Workflows API — or, on the v2 API, POST /orchestrations/runs/{run_id}/resume.

On SynapseOrch Cloud, an approver, builder, admin or owner can answer; a viewer reads the question but can't answer it (An approver, builder or admin can answer this.). The Needs input email carries the question, with a link of its own for each person who may answer: it works once, for seven days, and asks you to confirm on the page. A single yes/no step's email offers Approve and Decline; any other offers Answer. To keep run content out of email, an admin turns on Email the link only under Settings → Notifications → For the workspace: the email then names the workflow and links to the question instead. See Notifications.

An answer has to say something. Send answer and Enter wait until there is text; blank space is nothing. A form whose fields are all left blank is still an answer. The API, MCP and the app refuse an empty answer with a 422, The answer is empty. Send text, or an object keyed by the question's field names., and the run keeps waiting. A blank reply in a messaging channel is an ordinary message, not an answer.

If two people answer at once, the second is told Someone else answered this question first. The run is carrying on with their answer., and the run carries on with the first answer. Chat shows the same refusal.

A Team step can ask several questions at once, one per member; each is answered on its own.

Using human responses in subsequent steps

The answer is written to the gate's output key, and always to human_response too. Its shape depends on where it was given:

The step hasValue
Fields — answered on the canvas or in ChatAn object keyed by field name: {"decision": "approve", "feedback": "…", "priority": 2}
No fields — answered anywhereThe text itself: "approve"
Either — answered through the APIWhatever the request's response held; for a step with no fields, {"response": "approve"} is stored as "approve"

Later steps see the answer only once it is given. Agent, LLM and Tool steps that run afterwards see it in their prompt automatically. Give the step its own output key — review here — and read one field as {{ state.review.feedback }} in a prompt, or branch on it with if_else or switch:

{
  "id": "step-check-decision",
  "type": "if_else",
  "if_condition": "str(state.review.decision).lower() == 'approve'",
  "if_true_step_id": "step-publish",
  "if_false_step_id": "step-revise"
}

For a step with no fields the condition would read str(state.review).lower() == 'approve'. If the state schema declares the answer's key as text, the editor and Synapse AI warn that a step with fields writes an object there. See Conditions and expressions for what a condition can use.

Multiple human gates

A single workflow can have multiple human gates. Each pause creates a checkpoint — the run_id is stable across resumes and can be stored for later retrieval.

A gate inside a Loop body or a Parallel branch asks each time the run reaches it. Once it is answered, the Loop or Parallel step carries on from there: the rest of that iteration and then the remaining iterations, or the rest of that branch and then the branches after it. Inside a loop, the answers are collected per iteration in the gate's output key.

On this page