Skip to main content

Bots and automations

Applies to: SimpleTwo 0.9.x · Checked: 20.09.2026

A bot in SimpleTwo is not an "integration on the side" but a participant of the conversation: it has a directory account, a display name, an @handle and membership in conversations. From which follows the thing that matters to an administrator: "who can write here" is answered by the member list, and taking access away is removing the bot from the conversation.

1. What a bot is​

PropertyHow it works
Accountcreated by the coordinator; visible in the directory, has no password — interactive sign-in as a bot is refused
Tokenissued by the messaging service; shown once, at creation or rotation
Rightsthe token's capability scopes plus conversation membership, not a console role
@handleset by the administrator (a person changes their own; a bot cannot)
Organisation badgea "system" bot is marked as belonging to the organisation, so it cannot be impersonated by an outside bot with a similar name
A bot has no console role, and that is not an omission

A console role is consulted only at interactive sign-in, and a bot cannot sign in. The role field used to exist on bots — it was stored, shown in the table and enforced nowhere: an operator saw "administrator" and believed they had granted something. The field is gone, passing a role is refused with an error, and what actually governs a bot is what is actually checked: scopes, the conversation list and membership.

2. Capability scopes​

ScopeWhat it allows
readread messages of conversations the bot is admitted to
sendsend messages
reactadd reactions
manage-convchange a conversation's membership

An empty set means full access, a legacy of the first bots. Grant explicit scopes: a bot that only needs to notify gets send and nothing else.

A bot also has a conversation allowlist. Empty means "wherever it is added"; filled, it is a hard boundary on top of membership.

3. Webhooks: how a bot learns about events​

If a bot has a webhook address, the messaging service delivers events there. Delivery is signed when a secret is set:

X-S2-Signature: t=<unix time>,v1=<hex>

The signature is HMAC-SHA256 over <t>.<request body>. The timestamp is inside the MAC, so a receiver only has to enforce freshness (5 minutes is the recommended window) to reject replays, and needs to keep no state.

Verify the signature, not the source address

Before the signature existed, the only proof of origin a receiver had was "it came from our network". A receiver that trusts an IP address will trust anything that reaches the same network.

The console has a webhook test button: it sends a probe delivery and shows what your side answered. That is the fastest way to tell "we are not sending" from "you are not receiving".

4. Lifecycle​

  • Create — AI & automation → Bots: name, display name, @handle, scopes, conversations, webhook address and secret. The token is shown once.
  • Rotate the token — the same action; empty fields keep current values.
  • Disable — the "disabled" switch. The bot stays in place and stops authenticating: that is what you want during an incident.
  • Delete — removes the account and the token.

5. Automations​

An automation is a trigger → a linear chain of steps, with optional human approval. Deliberately small: there are no branches and there will not be; two audiences are two automations.

Triggers:

KindFires when
mentionthe bot is mentioned in a conversation
keyworda word appears in a message
scheduleevery N minutes
webhookan external call arrives
a person appearing, being blocked or deleteddirectory changes

A trigger can be narrowed by context — only guests, say, or only one department. That is not branching; it is selecting which runs happen.

Steps: post a message, call a webhook, add a member, remove a member. Message text substitutes values from the run's context ({{body}}, {{sender}}, {{conv}}, and for directory events the fields of the person who appeared).

Approval. Any step can be gated: user:<name> or role:<role>. The run stops until an allowed person reacts — ✅ or 👍 approve, ❌ or 👎 refuse. Being able to refuse is mandatory: without it a queue of runs stuck forever grows silently.

An automation always speaks as a bot

Naming one is required. The engine used to post under a name that belonged to no account: such an "author" never appeared in the member list, and the room could not show that anything wrote into it. Now the author is a real participant, and revoking access is removing them from the conversation.

Runs and audit. The console has a run log (what fired, which step it is on, what it waits for) and a manual run button, which is the convenient way to test an automation without waiting for an event. Agent and bot actions are collected into an audit trail of their own.

The write to a direct chat step (post_direct) posts a message as the bot into its direct chat with a person. If there is no such chat yet, the step creates it. This is how the support bot greets new users (see below).

6. The first day: the welcome and the support bot​

Two messages meet a newcomer. Both are set up by buttons in the console, and both stay ordinary automations — you can edit their texts in the automations card.

The welcome channel — Settings → Welcome flow → Provision. The button creates the welcome bot, the "Welcome" channel and an automation that adds every new person to the channel and greets them there. Guests can get a channel of their own. The greeting is your text, with the placeholders {{mention}} (the person as a mention), {{display_name}} and {{user}}. By default it is the company's welcome only, without instructions about bugs — the support bot gives those.

If you never changed the greeting, the coordinator replaces the old default (with its paragraph on bugs and wishes) with the new one when it is upgraded. A greeting you edited stays as it is.

The channel is filled by invitation only: people who came before it was switched on are not in it. Who is missing? counts them, Fill the room now adds them.

The support bot's greeting — Settings → Support case, the block "The bot's greeting of newcomers". The support bot writes to every new person in a direct chat: how to report a bug or a wish right in that chat, where the app's "Report a problem" item is, and the simpletwo://report link that opens the form. Employees and guests get different texts.

  • The rules are written when the support case is provisioned, and by Save greeting — without re-provisioning, which rotates tokens. In the automations card they are support-greet and support-greet-guests.
  • The default case greets by default. Additional cases greet only when Greet new users is switched on: three bots greeting one newcomer are three answers to one question.
  • Switched-off rules stay in the automations card but do not fire.
  • Back to the default text restores the default. If you never changed the text, new versions of the default arrive by themselves.
  • People who came earlier get the greeting only by the button. Who has not been greeted? counts the people with no chat with the bot, Greet them now sends them the greeting. People who already have a chat with the bot are left alone.

Over the API: POST /admin/api/support/greeting (instance, enabled, greeting, guest_greeting, reset) and POST /admin/api/support/greeting/backfill (instance, dry_run).

Next​