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
- The workflow reaches a
humanstep - Execution pauses — the run status becomes
paused - 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
- The answer is written to state
- 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 panel | Stored as | The form shows | The answer holds |
|---|---|---|---|
| Text | string | A text box | Text |
| Long text | textarea | A larger text box | Text |
| Number | number | A number box | A number |
| Yes / No | boolean | A checkbox | true or false |
email | An email box | An email address, trimmed | |
| Date | date | A date picker | A date, as YYYY-MM-DD |
| Phone | phone | A phone box | A phone number |
| Dropdown | choice, with its options | A list to pick from | One 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.
| Platform | Question posted | A reply answers |
|---|---|---|
| Telegram, Slack, Discord | Yes, from the API server or a worker | Yes |
| Only when the API server is running the channel's adapter | Yes | |
| Teams | No — Teams can't post first; answer in the app | Yes |
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 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, andlist_waitinglists 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 has | Value |
|---|---|
| Fields — answered on the canvas or in Chat | An object keyed by field name: {"decision": "approve", "feedback": "…", "priority": 2} |
| No fields — answered anywhere | The text itself: "approve" |
| Either — answered through the API | Whatever 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.
Creating Workflows
Workflows are built on the open canvas, from the Workflows screen.
A Team in a Workflow
Put a Team agent in a workflow's Agent step: picking it, what the step shows, the team inside the step's time and the run's cap, answering members' questions on the run page, and when a Parallel is the better choice.