Slack multi-instance (SLACK_INSTANCES)
One NanoClaw host can run several Slack apps in one workspace, each with
its own bot identity. There is nothing to install: the Slack adapter
(src/channels/slack.ts, installed by /add-slack) reads
SLACK_INSTANCES=<name>[,<name>…] from .env at load and registers one
additional bridge per listed name under the slack-<name> instance key,
built from that name's own token set through the same factory as the default
app. channelType stays slack — instance is a routing key; user ids,
formatting, container config, and the wiring-defaults declaration are shared
with the default Slack app. This document only records the conventions.
Configuration
Per named instance <name> (listed in SLACK_INSTANCES), create a separate
Slack app in the same workspace — same scopes, events, and App Home settings
as the default app (the /add-slack walkthrough lists them) — and store its
tokens in .env under the suffixed keys. <NAME> is the name uppercased
with dashes as underscores (gh-bot → GH_BOT):
SLACK_INSTANCES=dana
SLACK_BOT_TOKEN_DANA=xoxb-…
SLACK_APP_TOKEN_DANA=xapp-… # Socket Mode (omit for webhook delivery)
SLACK_SIGNING_SECRET_DANA=… # webhook delivery only
Registration is unconditional for every listed name, so a missing token set surfaces as the registry's "credentials missing, skipping" warning at boot rather than a silently absent bot.
Wire messaging groups to a named instance by setting the messaging group's
instance to slack-<name>.
Restart vs hot start
SLACK_INSTANCES is read once, at adapter load — after editing .env by
hand, restart the service (bash setup/lib/restart.sh) so the new instance
registers and connects. The exception is programmatic provisioning: flows
that create agents in-process (the slack-agent-flow skill) append the
instance and its tokens to .env and then hot-start the new adapter through
the registry's startChannelAdapter entry, so those instances come up
without a restart.
Validation
The channel payload ships the guard for all of this:
src/channels/slack-instances-registration.test.ts (installed by
/add-slack alongside the adapter) drives the registration loop against a
crafted .env and pins the shared wiring-defaults declaration and the
env-key suffix mapping:
pnpm exec vitest run src/channels/slack-instances-registration.test.ts
Remove
Remove SLACK_INSTANCES and any SLACK_*_<NAME> token lines from .env,
then restart the service. Messaging groups wired to a removed slack-<name>
instance stop resolving an adapter until rewired or deleted. (Adapter code is
untouched — the registration loop simply finds no names.)