Skip to content

Signal

Bridges Signal to the Workstacean bus via a WebSocket connection to a signal-cli REST API instance. Inbound messages become bus events; outbound bus messages are sent as Signal messages.

The plugin is disabled entirely if SIGNAL_URL or SIGNAL_NUMBER are not set.

VariableRequiredDescription
SIGNAL_URLYesBase URL of the signal-cli REST API (e.g. https://user:pass@signal.example.com)
SIGNAL_NUMBERYesPhone number registered with Signal (e.g. +15551234567)

Credentials can be embedded in the URL using https://user:pass@host format. If present, the plugin strips them from the URL and sends them as an Authorization: Basic header.

TopicDirectionDescription
message.inbound.signal.{sender}InboundMessage received from a Signal user
message.outbound.signal.{recipient}OutboundSend a Signal message to a recipient
{
sender: string; // Signal phone number of the sender
content: string; // Message text
channel: string; // Same as sender — used as reply target
}
{
content: string; // Message text to send
}

The plugin resolves the recipient from the outbound topic (message.outbound.signal.{recipient}) or from payload.channel on a reply.

Cron payloads that set channel: "signal" are delivered via Signal:

workspace/crons/daily-weather.yaml
topic: cron.daily-weather
payload:
content: "Tell the user today's weather for their location."
sender: "cron"
channel: "signal"

RouterPlugin routes the cron event to the agent, and the agent’s reply is published to message.outbound.signal.{sender}, which SignalPlugin delivers.