Getting started
Use the hosted dashboard
Running a new deployment or seeing no sign-in provider? Start with Register apps and enable signup. The current hosted rollout still needs provider registration and a real first signup.
- Open the Ever Async dashboard and sign in with an available provider. The first sign-in creates your initial tenant. Use the tenant menu to switch teams or Create tenant for a separate team.
- Open Connections. Members with the board role can Add Slack or Add Discord, using credentials for their own chat apps. Saving verifies the identity and starts the connection disabled.
- Copy the saved connection's callback URLs into the chat application's setup, then enable it. You can connect several Slack workspaces and Discord servers at the same time. Discord channel messages require Message Content Intent and the bot's channel permissions; without that intent it supports interactions only. See the connection guide for setup and shared-app URLs.
- To bring in task context, create the Ever Async integration in your Gauzy organization, then use Pair Gauzy in Connections. Choose which verified chat connections may use that pairing.
See Manage connections for fields, callback URLs, credential rotation, and tenant access. Gauzy requires the Ever Async integration plugin in the selected Gauzy deployment; see the Gauzy guide.
Run your own server
The steps below configure a dedicated installation from a local
everasync.toml: init → set the environment → serve → point Slack at it.
No separate queue or AI key is required. A self-hosted deployment can also
enable dashboard connection management with authenticated sessions and secure
connection storage; see Manage connections.
Prerequisites
-
A build of the
everasyncbinary — see Self-hosting for the source, Docker and compose paths. From source it is one command:cargo build --release # produces ./target/release/everasync -
A public HTTPS URL that reaches the server. Slack refuses plain HTTP and refuses to talk to
localhost. For local development a tunnel is enough (cloudflared tunnel --url http://localhost:8100, ngrok, tailscale funnel).
1. everasync init
everasync init
This writes a fully commented everasync.toml into the current directory
with every section present and the optional ones commented out. It refuses to
overwrite an existing file — pass --force if that is what you want.
Trim it down to the minimum you actually need:
[server]
bind = "0.0.0.0:8100"
[storage]
driver = "sqlite"
path = "everasync.db"
[channels.slack]
signing_secret_env = "SLACK_SIGNING_SECRET"
bot_token_env = "SLACK_BOT_TOKEN"
That is a complete, working configuration. Everything else has a default.
2. Set the environment variables
Look at the config again: it names SLACK_SIGNING_SECRET, it does not contain
it. Credentials in the static TOML configuration use *_env indirection: the
file stores the name of an environment variable, and its value lives in the
environment. Dashboard-managed connections store their credentials encrypted
on the server instead. See
the secret indirection rule.
Get the two Slack values from Slack setup, then:
export SLACK_SIGNING_SECRET=... # Basic Information → Signing Secret
export SLACK_BOT_TOKEN=xoxb-... # OAuth & Permissions → Bot User OAuth Token
If everasync.toml names a variable that is not set, startup fails with
config error: environment variable `SLACK_SIGNING_SECRET` is not set — not
with a server that quietly rejects every webhook.
3. everasync serve
everasync serve # reads ./everasync.toml
everasync serve --config /etc/everasync.toml
The server listens on [server] bind (default 0.0.0.0:8100) and exposes:
| Route | Purpose | Needs a credential? |
|---|---|---|
POST /ingress/{channel} | webhook intake, per channel plugin | never — the platform's own signature is the check |
GET /healthz | liveness — returns ok | never |
GET /api/v1/auth/mode | what, if anything, is being enforced | never |
GET /metrics | Prometheus counters | yes, viewer — once you turn auth on |
GET /api/v1/status | every registered plugin | viewer |
GET · PUT /api/v1/charter · /api/v1/policies/… | read / change behaviour | viewer · operator |
POST /api/v1/digest/send | deliver a digest to real people | board |
Check it locally before wiring Slack:
curl -s localhost:8100/healthz # → ok
curl -s localhost:8100/api/v1/status # → {"plugins":[{"id":"slack",...}]}
[auth] mode defaults to local_trusted: every caller is treated as a board
principal, which is why those two curls just work. That is correct on a
laptop and on a private network, and wrong the moment this port is reachable from
the internet — /api/v1 is writable, and one anonymous PUT can silence the bot
or rewrite your charter.
Turning it on is one config block, with three providers to choose from: static
API tokens (token), local password users (local), or browser SSO against
Slack, Discord, GitHub, Google and Ever Gauzy (oauth). Read
Security & authentication before you publish a hostname, and
Setting up SSO if you want sign-in buttons.
If status shows an empty plugins array, your [channels.slack] section is
missing or misspelled — a section that is absent silently disables its plugin.
os error 10013 on bindPorts 8080–8579 commonly sit inside a Hyper-V/WinNAT excluded port range,
which includes the default 8100. List them with
netsh interface ipv4 show excludedportrange protocol=tcp and pick a
[server] bind port outside the reserved ranges.
4. Point Slack at it
Create the Slack app from the manifest in Slack setup, which sets two URLs:
Event Subscriptions https://<your-host>/ingress/slack/events
/async slash command https://<your-host>/ingress/slack/commands
When Slack validates the events URL it sends a url_verification challenge.
The server must already be running — Ever Async echoes the challenge
automatically, and Slack only accepts the URL if it gets that echo back.
Then, in a channel you want covered:
/invite @EverAsync
/async status
Ever Async is per-channel opt-in: it only ever sees channels the bot is a
member of. /async status replying with the current policy confirms the whole
round trip — HTTPS ingress, signature verification, and the bot token.
5. See it work
Post this in that channel, from an account that is not the bot:
Hi, can I get some help?
Nothing happens publicly. About 150 seconds later you and only you see an ephemeral message explaining that the message does not yet say what you need. Reply in the thread with the detail before the window closes and the nudge is cancelled — self-correction always wins.
Now try the other path. Open a pull request on GitHub, add the GitHub connector, and post:
I finished the PR, can someone review it?
This time there is no nudge — there is a thread reply with the pull request, its title and its status. The message became actionable without anyone being told off.
Verify the whole install
everasync doctor
doctor loads the config, assembles every plugin exactly as serve does, then
health-checks each channel and connector concurrently and exits non-zero if any
check fails. Use it in CI and after every credential rotation — see
Operations.
Next
- Turn the sensitivity up or down per conversation → Policy
- Configure your team's guidance → The charter
- Resolve Jira tickets and Gauzy tasks too → Connectors
- Add an AI provider for the ambiguous middle → AI providers
- Require a login before anyone else can reach it → Security & authentication · Setting up SSO
- Swap SQLite for Postgres or MySQL →
Configuration →
[storage] - Every key in the file → Configuration