GraphQL Activities
One activity, graphql.subscribe, opens a GraphQL subscription and feeds each payload the
server pushes into the running workflow as an event.
It speaks the graphql-transport-ws protocol, so it works with graphql-ws, Apollo Server v3+ and
Hasura. For one-off queries and mutations there is no GraphQL activity — post them with
http.request, which is all a GraphQL query over HTTP is.
Setup
No configuration and no secret-store integration: authentication is whatever headers the server
expects, passed in headers on the WebSocket handshake.
headers are visibleUnlike providers that take a *_secret_key, a token placed in headers passes through workflow
context and history in plaintext. Keep that in mind for long-lived credentials.
The worker needs the gql package with WebSocket transport.
Defaults
86400 s (1 day) timeout, 1 attempt, heartbeating every 20 s against a 60 s timeout.
graphql.subscribe
Connects, starts the subscription, and relays every payload the server pushes as a workflow event
that wait_for receives. It runs until the activity is cancelled.
Input
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
endpoint | str | yes | — | WebSocket endpoint, e.g. wss://api.example.com/graphql |
subscription | str | yes | — | The GraphQL subscription document |
variables | dict | no | null | Variables bound to the subscription |
headers | dict[str, str] | no | null | Handshake headers, typically Authorization |
relay_topic | str | no | "default" | Event topic the workflow listens on |
relay_event_type | str | no | null | event_type stamped on each relayed event |
target_workflow_id | str | no | current workflow | Workflow the events are delivered to |
Output
| Field | Type | Description |
|---|---|---|
stopped | bool | Always true |
The payloads themselves arrive as events, not in the output.
Relayed event data
Each event's data is the subscription payload as the server sent it — the object under the
subscription's root field.
Example
Adapted from the provider's integration test:
- activity:
type: graphql.subscribe
name: start_subscription
async_mode: true
input_data:
endpoint: "wss://api.example.com/graphql"
subscription: |
subscription OnPriceTick($symbol: String!) {
priceTick(symbol: $symbol) { symbol price ts }
}
variables:
symbol: "{{ symbol }}"
headers:
Authorization: "Bearer {{ api_token }}"
relay_topic: graphql.msg
relay_event_type: graphql_payload
target_workflow_id: "{{ __sys_info__['workflow_id'] }}"
retry_policy:
heartbeat_interval_sec: 0.5
heartbeat_timeout_sec: 5
- wait_for:
event_source_topic: graphql.msg
event_type: graphql_payload
timeout_sec: 300
output_name: tick
- transform:
output_data:
- price: "{{ tick['data']['priceTick']['price'] }}"
Without async_mode: true (or a parallel branch) this activity blocks the workflow for a full day.
Unlike rabbit.receive, it does not default to async mode.
Errors inside the subscriber are logged and end the activity successfully with
stopped: true — a dead feed is not reported as a failure, and with max_attempts: 1 there is no
retry. If the subscription must stay up, have the workflow notice the absence of events (a
wait_for timeout) rather than relying on the activity to fail.
Payloads pushed while the connection is down are never replayed. Do not use a GraphQL subscription as the sole transport for events you cannot afford to miss.
On the Temporal runtime each relayed payload is a workflow signal and a history entry, and the engine retains at most 1000 unmatched events per topic.