signal-cli-rest-api bridge, no cloud bot token needed.
Quick Start
1
Run the bridge
Signal links a device through the signal-cli-rest-api bridge. Start it with Docker in
native mode.2
Link your device
Open the bridge link URL, then scan the QR from Signal → Settings → Linked Devices → Link New Device.
3
Start the bot
Point the bot at your linked account and the bridge.Message your linked Signal number and the agent replies.
No token needed — Signal links a device via the local bridge. The
token constructor argument exists only for adapter-wiring parity and is unused.How It Works
Signal is poll-based: the bot fetches inbound envelopes from the bridge, routes text to the agent, and sends the reply back through the bridge. The adapter talks HTTP/JSON to these bridge endpoints:
Inbound liveness. A delivered envelope refreshes the Signal channel’s
last_activity for the shared Channel Supervision health monitor. Successfully-empty polls do not refresh it, so a silently half-open bridge (returns [] forever without raising) trips stale-socket after stale_after seconds and the supervisor reconnects — instead of the bot going quietly deaf.
Configuration
Signal needs an account and a bridge URL. Configure it with YAML, environment variables, or the Python SDK.- YAML
- Environment
- Python SDK
Config keys
Constructor parameters
Capabilities & Limits
Signal declares honest capabilities so shared engines degrade correctly.Built-in Commands
Every Signal channel ships these commands out of the box.
Register custom commands:
DM Allowlist
Restrict who can DM the bot withallowed_users — phone numbers are normalised to digits so formatting never blocks a match.
What’s Not Supported Yet
This release ships text messaging. The following are intentionally not wired:Troubleshooting
ValueError: Signal account is required
ValueError: Signal account is required
The account is empty. Set it via the constructor,
channels.signal.account, or the SIGNAL_ACCOUNT environment variable before calling start().ImportError: aiohttp is required
ImportError: aiohttp is required
The Signal adapter uses
aiohttp (lazy-imported). Install it:No messages arrive
No messages arrive
Confirm the bridge is linked and reachable. Check
GET /v1/accounts returns your number, and lower poll_interval (minimum 0.2s) for faster pickup. Verify the bridge runs in native or json-rpc mode so /v1/receive returns envelopes.Bot reports HEALTHY but hasn't received a message in hours
Bot reports HEALTHY but hasn't received a message in hours
The
signal-cli-rest-api bridge can go silently half-open — the HTTP call succeeds but the bridge returns [] forever. The gateway health monitor treats time since the last delivered envelope as the liveness signal (empty polls don’t count), so the channel will trip stale-socket after stale_after seconds (default 120s) and the supervisor will reconnect automatically. Confirm via GET /health that last_activity for the Signal channel is advancing on real inbound messages, and consider lowering stale_after on very-chatty accounts or raising it on quiet ones. See Channel Supervision → Proactive Health Monitoring.Bridge unreachable on probe
Bridge unreachable on probe
probe() calls GET /v1/accounts. A non-200 means the bridge is down or the URL is wrong. Ensure bridge_url matches the Docker port mapping (default http://localhost:8080).Best Practices
Keep the bridge private
Keep the bridge private
The
signal-cli-rest-api bridge holds your linked device. Run it on localhost or a private network — never expose port 8080 to the public internet.Use the allowlist for DMs
Use the allowlist for DMs
Set
allowed_users so only trusted numbers can start a conversation. Numbers normalise to digits, so any formatting works.Tune the poll interval
Tune the poll interval
poll_interval trades latency for load. Keep the default 1.0s for most bots; lower it toward 0.2s for snappier replies, raise it to reduce bridge traffic.Expect plain text
Expect plain text
Signal has no message editing and this release is text-only. Design replies as self-contained plain-text messages rather than relying on edits or rich media.
Standalone scheduled delivery (no gateway)
You do not need a running Signal Bot process to deliver a scheduled brief to Signal. PointSIGNAL_ACCOUNT at your linked sender number (and, if the bridge is not on http://localhost:8080, set SIGNAL_BRIDGE_URL). From OS cron / CI, praisonai schedule tick will POST to {SIGNAL_BRIDGE_URL}/v2/send using an explicit deliver: signal:<recipient> target or SIGNAL_HOME_CHANNEL. The bridge must be reachable from wherever the tick fires. See Out-of-process delivery.
Related
WhatsApp Bot
The closest sibling — linked-device / local-bridge model
Channels Gateway
Run Signal alongside Telegram, Discord, Slack, and more
Messaging Bots
All supported messaging platforms
Bot Gateway
Multi-channel gateway architecture
Self-healing gateway channels — how Signal integrates with the health monitor

