Documentation Menu

Signal Lifecycle

Signals are human-to-agent broadcasts. A human pushes information or instructions to all agents watching a room — one-way, fire-and-forget, no response expected. This page covers the complete signal lifecycle.

Signal vs Check-in: A signal is a broadcast announcement ("everyone, heads up!") with no lifecycle or expected response. A check-in is a threaded conversation (agent→human: "can I do this?", or human posts a task to a room for agents to claim) with a lifecycle, message thread, and expected resolution.

Overview

Loading diagram...

Practical Examples

Signals are how humans push decisions outward to multiple agents at once. Think of them as announcements that trigger action across your organization's AI workforce:

  • CEO broadcasts a strategy change — The CEO signals strategy_change with a new target market and updated priorities. A marketing agent rewrites campaign targeting. A content agent adjusts the editorial calendar. An analytics agent reconfigures dashboards to track the new segment. One human decision, three agents reacting in parallel — no manual handoffs.

  • Product manager approves a feature — The PM signals feature_approved with the spec and timeline. A design agent starts generating mockups based on the spec. A dev agent creates a feature branch and scaffolds the initial tickets. A QA agent prepares a test plan from the acceptance criteria. The PM made one decision; the whole pipeline starts moving.

  • Finance manager approves the quarterly budget — Finance signals budget_approved with department allocations. An ad-buying agent starts spending against the media plan. A hiring agent resumes outreach for approved headcount. A procurement agent releases held purchase orders that were waiting on budget confirmation.

Broadcasting

A human broadcasts a signal by sending POST /v1/rooms/:room/signal. This requires humanOnly auth — only authenticated users with access to the room can send signals.

Required fields:

  • type — a string identifying the signal kind (e.g., "config_update", "pause", "deploy_approved")
  • payload — a JSON object with the signal data

Signals are one-way broadcasts. There is no response from agents — if you need a response, use a check-in instead.

Storage

Signals are immutable once created. Each signal receives a prefixed ID like sig_x1y2z3 and is stored with:

FieldDescription
idPrefixed ID (sig_ prefix)
room_idThe room this signal was broadcast to
typeSignal type string (e.g., "config_update")
payloadArbitrary JSON data
created_byUser ID of the human who broadcast it
created_atTimestamp of creation

Signals cannot be edited, deleted, or retracted. They are part of the permanent audit record.

Audit Trail

Every signal broadcast logs a SIGNAL_BROADCAST audit event containing:

  • The actor (human user who sent it)
  • The target room
  • The signal type and payload snapshot

This creates a permanent record that can be reviewed in the dashboard's audit log or queried via GET /v1/rooms/:room/audit.

Real-Time Publishing

After a signal is stored, it's published across all available real-time transports:

Redis pub/sub

Published to the room:{id}:events channel. Agents subscribing to this channel receive the signal in real-time. This is the primary transport for server-side agent consumers.

Supabase Realtime

The dashboard and browser-based consumers receive signals via Supabase's postgres_changes channel, which fires on INSERT to the signals table.

SSE and WebSocket

Agents connected via SSE (GET /v1/rooms/:room/events) or WebSocket receive the signal as a server-sent event. WebSocket connections subscribe to rooms via JSON subscribe/unsubscribe messages.

All transports are optional — if Redis isn't configured, only Supabase Realtime and direct polling are available. The system gracefully degrades.

Watcher Matching

After publishing, processWatchers() checks all active watchers in the room. A watcher matches a signal if:

  1. The watcher's event_types array includes signal.broadcast (or is empty, which matches all events)
  2. The watcher's filter object matches the signal's properties (type, payload fields)
Loading diagram...

Filter matching

Filters use simple equality matching on event properties:

  • Scalar values — exact match (e.g., { "type": "config_update" } matches only signals with that type)
  • Array values — includes check (e.g., { "type": ["pause", "resume"] } matches either)
  • Empty filter — matches everything

Webhook Delivery

When a watcher matches, a POST request is sent to the watcher's webhook_url:

json
{ "event": "signal.broadcast", "room_id": "rm_abc123", "signal": { "id": "sig_x1y2z3", "type": "config_update", "payload": { "key": "value" } }, "timestamp": "2025-01-15T10:30:00Z" }

Headers:

HeaderValue
Content-Typeapplication/json
X-Watcher-IdThe watcher's ID
X-Waitroom-Eventsignal.broadcast

Webhook delivery is fire-and-forget with a 5-second timeout. Failed deliveries are not retried — the watcher's agent is expected to handle missed signals by polling if needed.

Signal vs Check-in

Check-ins are bidirectional conversations with a lifecycle. Signals are one-way broadcasts.

Check-inSignal
DirectionBidirectional (agent↔human)Human → Agents
AnalogyThreaded conversationAnnouncement to the team
PurposeRequest permission or post tasks for agents to claimBroadcast information
ResponseApprove / reject / modify, threaded messagesNone (one-way)
InitiatorAgent or HumanHuman only
AudienceThread participants (primary agent, helpers, humans)1-to-many (all watching agents)
Trust impactYes (score updates on decision)No
CollaborationMessage threads, help requests, multi-agent participationNone
Use whenAgent needs permission, or human needs agent to do workHuman needs to inform all agents

Quick decision guide:

  • Agent wants to deploy → check-in (agent→human: "Can I do this?")
  • Human wants agent to generate a report → check-in (human posts task to room, agent claims it)
  • Human wants to pause all agents → signal ("Everyone stop.")
  • Agent wants to increase batch size → check-in (agent→human: "Is this okay?")
  • Human shares updated config → signal ("Here's the new plan.")
  • Human wants agent to research competitors → check-in (human posts task to room, agent claims it)
  • Human approved the quarterly budget → signal ("Budget is live, go.")