For AI agents: the complete documentation index is available at https://a3s-lab.github.io/Flow/en/llms.txt, the full documentation bundle is available at https://a3s-lab.github.io/Flow/en/llms-full.txt, and this page is available as Markdown at https://a3s-lab.github.io/Flow/en/nodes/signal.md.

Wait for signal flow.signal

A signal node waits for one named external message. Use it when messages may arrive more than once, need queueing, and are delivered by an authenticated control plane or business service. The wait declaration is persisted before the worker is released. If a matching unconsumed signal arrived earlier, the oldest matching message can satisfy the wait immediately, which preserves arrival order across restarts.

Wait identity and message name

wait_id identifies this specific wait and must remain unchanged during replay. The graph node ID is usually a suitable source. signal_name is part of the published workflow contract, such as an approval result or a request to continue after missing information is supplied. Senders should include a stable message identity so the host can reject duplicate delivery. Payloads must be serializable and comply with size, authorization, and retention limits.

After a message is consumed, control leaves through received and payload contains the stored JSON value. A later wait needs a new stable identity. Two active nodes must not compete for the same wait ID. Choose a hook when an unaffiliated caller needs a one-time public URL and token. Signals have no public-token semantics by default and should enter through an authenticated application boundary.

Queue and race checks

Test both arrival orders, several messages with the same name, duplicate message identities, unrelated names, cancellation racing with receipt, runtime recovery, and an oversized payload. Operators need the signal name, arrival time, wait identity, and consumption state, while sensitive payload fields stay out of logs. A continuation boundary is rejected while earlier signals remain unconsumed, so a long-running loop must decide exactly which history segment owns each message. Define retention and dead-letter handling for signals that arrive after the relevant workflow has already ended.

Use it to wait for a named external message. It fits repeated messages that must queue and carry caller-owned idempotency identity.

Runtime behavior

The worker is released after the wait commits. The earliest unconsumed signal with the same name binds to wait_id, then exposes received and payload.

Node contract

Type
flow.signal
Role
Durable runtime command
Runtime binding
wait_for_signal
Durable identity
Graph node ID

Configuration properties

PropertyType and controlDefaultRules
wait_idWait IDstrStrInputsignalReplay-stable wait identity. The graph node ID is recommended.Required
signal_nameSignal namestrStrInputworkflow.signalDeclared signal contract accepted by this wait.Required

Ports

DirectionPort IDKindValue types
InputinIncontrolFlowControl
OutputreceivedReceivedcontrolFlowControl
OutputpayloadPayloaddataJsonValue

Node JSON example

The CLI creates the same structure from manifest defaults. Canvas position, title, and selection are presentation data.

workflow.json
{
  "position": {
    "x": 320,
    "y": 160
  },
  "id": "example-flow-signal",
  "data": {
    "wait_id": "signal",
    "signal_name": "workflow.signal",
    "type": "flow.signal"
  }
}

CLI usage

Inspect the installed manifest first, then create the node and validate the complete workflow. Every command emits JSON.

Terminal
a3s-flow node flow.signal --pretty
a3s-flow new flow.signal --id example-flow-signal --pretty
a3s-flow validate workflow.json --pretty
a3s-flow compile workflow.json --pretty
a3s-flow digest workflow.json --pretty

Skill usage

The package includes the a3s-flow Skill. It queries the CLI catalog before creating, validating, compiling, and digesting a workflow.

Prompt
Use $a3s-flow to add the "flow.signal" node to workflow.json, connect valid ports, and validate the result.

CLI usage · Skill usage

Operational notes

  • Keep wait_id stable for one wait.
  • Choose signal_name from the published signal contract.
  • Use a hook for one callback protected by a public token.