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
| Property | How it works |
|---|---|
| Account | created by the coordinator; visible in the directory, has no password — interactive sign-in as a bot is refused |
| Token | issued by the messaging service; shown once, at creation or rotation |
| Rights | the token's capability scopes plus conversation membership, not a console role |
@handle | set by the administrator (a person changes their own; a bot cannot) |
| Organisation badge | a "system" bot is marked as belonging to the organisation, so it cannot be impersonated by an outside bot with a similar name |
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
| Scope | What it allows |
|---|---|
read | read messages of conversations the bot is admitted to |
send | send messages |
react | add reactions |
manage-conv | change 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.
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:
| Kind | Fires when |
|---|---|
mention | the bot is mentioned in a conversation |
keyword | a word appears in a message |
schedule | every N minutes |
webhook | an external call arrives |
| a person appearing, being blocked or deleted | directory 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.
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-greetandsupport-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
- AI assistants and agents — the other side of bots: models, budgets, delegation
- API overview
- Assistants and bots — the same thing from the user's side