---
title: Approved senders for message channels (who can auto-start a session)
---

# Approved senders for message channels (who can auto-start a session)

## What it is

Omniscio can **automatically start an AI session or run an automation
when a message arrives** on a connected messaging channel — a text (SMS), a Slack
message, or a Telegram message. That's powerful, but it means whoever can message you
could, in principle, kick off a paid AI session (via an automation you set up or a
workflow trigger).

The **Approved senders** list closes that gap. For each of these three channels you
keep a small allowlist of who is allowed to auto-start work:

- **SMS** — phone numbers
- **Slack** — Slack user IDs
- **Telegram** — Telegram sender IDs / usernames

An inbound message from an unapproved sender still **runs your free rules** — archiving
spam, forwarding a code to your email, showing a notification, an AI spam-check — and
still **arrives in your inbox as normal.** What an unapproved sender **cannot** do is
drive the _paid_ parts: auto-starting or continuing an AI (Claude) session, auto-replying
a text straight back to the sender, or firing a workflow. Only a sender on that channel's
list can do those.

## Where to find it

Settings → Connections → Channels → open **SMS**, **Slack**, or **Telegram**. When the
channel is turned on, an **Approved senders** card appears. It shows:

- the people currently allowed (as removable chips), and
- an **Add** box to type a new phone number / ID.

When the list is empty the card explains that no one can auto-start a session yet and
invites you to add senders you trust.

## How it behaves

### The most important rule: empty means nobody

The list is **fail-closed**: if a channel's Approved senders list is **empty, nobody
can auto-start a session on that channel.** This is on by default and deliberate —
so an unknown texter or a stranger in a Slack channel can never spin up a paid AI run
before you've said who you trust. To let a sender through, you add them to the list.

> This is the opposite of the older **Email Inbound** "Approved Senders" box, where an
> empty list means "allow anyone" (because email intake has a separate secret-token
> gate). For SMS/Slack/Telegram there is no such token, so empty = allow no one.

### How you'll know it's working (the heads-up note)

Because "empty = nobody," turning this on can pause an inbound auto-start you were
relying on. So you're never left guessing: the first time a message from an unapproved
sender **actually would have started a paid session, reply, or workflow** — and only if
you have automations turned on — Omniscio drops **one** note in your Inbox, e.g. _"An SMS
message was blocked from starting a session because the sender isn't on your
approved-senders list."_ It names an example sender so you can copy the ID straight into
the Approved senders box if you trust them. You get one note per channel, not one per
message, so it never floods your Inbox.

Note: if an unapproved sender's message only triggered your **free** rules (a spam-archive,
a code-forward), nothing paid was blocked — so **no note appears**, and those rules simply
run.

### What it does NOT do

- It does **not** hide or delete messages, and it does **not** disable your free rules.
  A blocked sender's message still shows up in your inbox, and your free automations
  (archive / forward / notify / AI spam-check) still run — only the _paid_ parts (an AI
  session spawn, an auto-reply to the sender, or a workflow) are gated.
- It is **not** a security wall. A sender's phone number / Slack ID can be spoofed, so
  treat the list as a convenience-and-cost guard (stop surprise paid runs), not as
  authentication.
- It does **not** affect email (that has its own Approved Senders + prescreen), nor
  read-only channels like RSS, nor webhooks (which use their own secret token).

## For agents

### Under the hood

- The gate lives at the one place every inbound message passes through:
  `dispatchInboundMessage` in `src/main/services/automation/legacy/dispatch-inbound-message.ts`.
  For an unapproved sender on a gated channel it does NOT return early — it runs both legs
  with the paid work suppressed: `processMessage(msg, { paidActionsAllowed: false })` and
  `evaluateMessageWorkflows(msg, { paidSpawnAllowed: false })`. Free actions + AI conditions
  run; only the sender-gated actions and workflow runs are skipped.
- The gated ACTIONS are a shared constant, `SENDER_GATED_ACTION_TYPES` in
  `src/shared/message-sender-gate.ts` (`cli_session`, `cli_send_to_session`, `auto_respond`
  — a paid session spawn or a reply to the sender). The legacy `executeAction` skips them
  when `ctx.paidActionsAllowed === false`; every other action runs. The blocked-sender note
  fires only when one of these — or a matched workflow — was actually suppressed.
- The decision is a pure function, `isMessageSenderAllowed`
  (`src/main/services/automation/legacy/message-sender-policy.ts`): empty list → deny; SMS
  numbers are compared in canonical E.164 form, other IDs case-insensitively.
- The gated channel list is shared (`src/shared/message-sender-gate.ts`,
  `SENDER_GATED_CHANNELS = ['sms','slack','telegram']`) so the enforcement and the
  Settings UI never drift.
- The setting is `messageInboundApprovedSenders` (a per-channel map) in
  `src/shared/types/settings/channels-settings.ts`.
- Full invariants + rationale:
  `.claude/memory/contracts/inbound-sender-allowlist-contract.md`.

This closed the security-sweep findings (inbound
SMS/Slack/Telegram messages and workflow message-triggers reaching a billable spawn
with no sender allowlist).

## Related

Email intake is a separate system with its own sender list, described on the [Email inbound prescreen](email-inbound-prescreen.md) page. The inbox a blocked sender's message still lands in is the [Inbox overview](inbox-overview.md), and the automations a message can trigger are on the [Automations and auto-replies](automations-and-auto-replies.md) page.
