Multi-Agent Collaboration in Slack
Multi-Agent Collaboration in Slack: Identity, Permissions, and Orchestration Architecture
Building a multi-agent collaboration environment starts with one principle: agents act on their own behalf, never as proxies for the human who set them up. Every action must be independently auditable, traced to the specific agent, and isolated from other agents. No credential inheritance, no default connections, no shared accounts. The default Hermes profile should stay Slack-free unless you intentionally want a personal or main bot.
One Hermes role profile = one Slack app = one bot identity = one token set = one audit trail
Trying out Hermes agent from Nous Research, I used Slack as my main platform for multi-agent collaboration. The pattern that works: each agent gets its own Slack bot account with independent credentials. The orchestration layer (Hermes) coordinates across agents, invoking them with their own credentials. Slack’s audit logs show which agent acted, not a proxy, not a shared account, not a human.
A shared Slack bot is easy to set up, but it creates a weak security model. When something goes wrong, you have to reconstruct who or what acted from application logs. Slack itself cannot distinguish the agents because they all used the same bot identity.
A dedicated app per agent approach provides a safer design with:
- Every specialized agent action is independently auditable (Slack logs show “ai-agent-dev posted,” not a proxy)
- Credentials are isolated per agent (one bot’s compromise doesn’t affect others)
- Permissions don’t inherit from the user (agents operate with their own minimal scopes based on the least-privilege principle)
- The system scales without credential sprawl or audit trail degradation
This does not automatically make the system fully compliant or guarantee a fully production-ready setup. It does, however, make least privilege, access review, token rotation, and audit evidence much easier to manage.
Why This Architecture: Clear Slack-Side Attribution
Three patterns exist for multi-agent Slack integration. Only one passes the accountability test.
Avoid: Single bot impersonating multiple personas. The bot swaps usernames, avatars, and display names to simulate different agents. Behind the illusion: one bot account owns all actions. Audit logs show “Your-AI-App-Bot-Name” as the actor, not the specific agent. When something breaks, you can’t trace it to a specific agent. Permissions attach to the bot, not individual agents, so you can’t restrict what each persona can access. Compliance frameworks demand attribution to named actors; impersonation fails that requirement. Direct messaging becomes a proxy layer where the bot intercepts and reroutes—opaque and fragile.
Avoid: Shared service accounts. Multiple agents share one Slack account. Audit logs show the account name but can’t tell which agent acted. When you revoke the account, you break all agents simultaneously. Token compromise risks all agents at once. Shared credentials violate SOC 2, HIPAA, PCI DSS—any compliance framework that requires action attribution. This pattern fails the core principle: agents don’t act on their own behalf.
Better pattern: Multiple bots representing different AI-agent roles. Each centrally orchestrated agent gets a dedicated persona with its own Slack app and a dedicated bot token. This is a better way to achieve independent accountability. Here’s why:
-
Independent credentials: For example, ai-
's token never touches ai- 's token. One agent's compromise doesn't cascade to the others. Token rotation is decoupled per bot, not handled as a shared coordination problem. - Auditability: Actions are attributed directly to the agent, not proxied through a setup user or shared account.
- Permission isolation: Each bot is invited only to the channels it needs. No inherited permissions from whoever provisioned it. Agent permissions can be managed per allowed Slack channel. Least-privilege becomes native.
- Scalability: Add a new agent = new bot + new token + new audit trail. No credential sprawl, no permission inheritance surprises.
- Fine-grained access control: Manage slash commands per agent (e.g., ai-product sees /roadmap and /strategy, while ai-dev sees /deploy and /status). Restrict API access per agent (ai-marketing can call the analytics API but not the billing API). Control tool access per agent (ai-devops gets cloud provider credentials but ai-sales doesn’t). Each agent operates within its functional boundary. Yes, least-privilege is the key, once again.
Trade-off: you manage more Slack apps (one per agent) and rotate more tokens. Each bot needs explicit channel invitations. Workspace slash commands may conflict. But these operational costs are small compared to losing auditability and inability to scale.
In the end, each message posted to Slack comes from the specific agent bot identity. This makes Slack-side review easier. You can see which agent posted, which channels the app had access to, and which app token was involved.
Important caveat: Slack audit logs only cover Slack-side activity. They do not fully explain what happened inside Hermes. For full attribution, you also need Hermes profile logs, tool execution logs, OS logs, and downstream API logs.
Agent Bot Setup: Independent Credentials and Scopes
Creating Agent Bot Apps
Each agent needs a dedicated Slack app. This ensures independent credentials and auditability. Create one app per agent function.
Naming convention: Use consistent, descriptive names that make each agent’s functionality and scope clear to your team.
Bot token scopes per agent: Each bot gets only the scopes it needs, following the least-privilege principle:
-
chat:write— post messages to channels the agent is a member of -
channels:read— read channel list and metadata -
reactions:write— add reactions (for approvals, voting) -
im:write— send direct messages to other agents or humans -
users:read— list agents and users (for lookups) -
files:read— read shared files (optional, if agent needs access)
Different agents get different scopes based on function. The marketing agent doesn’t need groups:read if it doesn’t access private engineering channels. This is credential isolation in practice: each token is scoped to the minimum needed for that agent’s role.
Token storage and rotation: Each agent bot token is stored independently in your secrets manager (AWS Secrets Manager, HashiCorp Vault, etc.). Rotation schedule is per agent, not as a batch. One agent’s token rotation doesn’t affect others.
Channel Membership: Bot-Level Access Control
Assign each agent bot to channels based on functional scope, not broadcast membership. Bots don’t inherit permissions from whoever created them; access is explicit.
**
-
#<agent-slug-a>(required) -
#agents-war-room(required)
Dev agent bot:
-
#<agent-slug-b>(required) -
#agents-war-room(required)
… etc …
Hermes orchestration bot (orchestration only):
-
#agents-war-room(required) -
#<agent-slug-a>,#<agent-slug-b>, etc. (all required) -
#agent-approvals(required)
Slack App Configuration: Multiple Apps, Independent Tokens
You’ll create multiple Slack apps in your workspace:
- One app per agent
Each app gets its own bot token with minimal required scopes. This is the core of credential isolation.
Agent Bot App Configuration
Agent Bot Token Scopes (minimal per agent):
chat:write # Send messages to channels agent is a member of
channels:read # Read channel metadata
reactions:write # Add reactions (for approvals)
im:write # Send direct messages to other agents/humans
users:read # List agents/users
Slack App Setup: Complete Configuration
Using Slack Admin Console
For each agent bot app:
-
Create Slack App:
- Go to api.slack.com/apps
- Click “Create New App”
- Select “From a manifest”
- A local manifest file is useful as desired-state documentation. While it is not the live runtime source of truth after the app has been configured in Slack, it is still a good source for future review, recreation, disaster recovery, change tracking, and everyone’s favorite security audits. Never put secrets in this manifest!
.hermes/profiles/<agent-slug>/slack-manifest.json
- Name: e.g., “ai-
" - Select your workspace
{
"_metadata": {
"major_version": 1,
"minor_version": 1
},
"display_information": {
"name": "<agent-display-name>",
"description": "Dedicated Hermes Agent for <approved-functionality>",
"background_color": "#1a1a2e"
},
"features": {
"app_home": {
"home_tab_enabled": false,
"messages_tab_enabled": true,
"messages_tab_read_only_enabled": false
},
"bot_user": {
"display_name": "<agent-display-name>",
"always_online": false
},
"slash_commands": [
{
"command": "/<agent-slug>",
"description": "Talk to <agent-display-name> Hermes or run an approved subcommand",
"should_escape": true,
"url": "https://<your-hermes-host>/slack/commands",
"usage_hint": "[message]"
},
{
"command": "/<agent-slug>-new",
"description": "Start a new <agent-display-name> Hermes session",
"should_escape": true,
"url": "https://<your-hermes-host>/slack/commands",
"usage_hint": "[name]"
},
{
"command": "/<agent-slug>-stop",
"description": "Stop active <agent-display-name> Hermes background work",
"should_escape": true,
"url": "https://<your-hermes-host>/slack/commands"
},
{
"command": "/<agent-slug>-whoami",
"description": "Show your <agent-display-name> Hermes access status",
"should_escape": true,
"url": "https://<your-hermes-host>/slack/commands"
},
{
"command": "/<agent-slug>-status",
"description": "Show <agent-display-name> Hermes session status",
"should_escape": true,
"url": "https://<your-hermes-host>/slack/commands"
}
],
"assistant_view": {
"assistant_description": "Chat with <agent-display-name> in approved channels and DMs."
}
},
"oauth_config": {
"redirect_urls": [
"https://<your-hermes-host>/slack/oauth/callback"
],
"scopes": {
"bot": [
"app_mentions:read",
"chat:write",
"commands",
"im:history",
"im:read",
"im:write",
"users:read"
]
}
},
"settings": {
"event_subscriptions": {
"bot_events": [
"app_mention",
"message.im"
]
},
"interactivity": {
"is_enabled": true,
"request_url": "https://<your-hermes-host>/slack/interactivity"
},
"org_deploy_enabled": false,
"socket_mode_enabled": true,
"token_rotation_enabled": true
}
}
-
Configure OAuth:
- Navigate to “OAuth & Permissions”
- Add Bot Token Scopes (see Agent Bot Token Scopes section)
- Copy and store the Bot User OAuth Token securely
-
Install App:
- Navigate to “Install App”
- Click “Install to Workspace”
- Authorize the requested scopes
- Confirm installation
-
Verify Installation:
- Check that agent appears in your workspace member list
- Verify the bot has the correct name and profile
- Test that agent can post in an assigned channel
How This Architecture Aligns With Compliance Needs
Slack’s audit logs show “ai-
- SOC 2: Demands attribution of every action to a named actor. Direct agent attribution makes this native.
- HIPAA: Requires user-level audit trails for healthcare data access. Per-agent tokens provide this.
- GDPR: Requires demonstrating who accessed what data and when. Direct attribution is non-negotiable.
- PCI DSS: Requires access control and audit logs tied to identities. Separate agent credentials deliver this.
Recommended Directory Layout
A Hermes installation can use the default profile plus role-specific profiles.
/path/to/.hermes/
├── config.yaml
├── .env
├── logs/
├── sessions/
├── skills/
├── cron/
├── cache/
├── hermes-agent/
└── profiles/
├── <agent-slug-a>/
│ ├── config.yaml
│ ├── .env
│ ├── logs/
│ ├── sessions/
│ ├── skills/
│ ├── cron/
│ ├── state.db
│ ├── gateway_state.json
│ ├── channel_directory.json
│ └── slack-manifest.json
│
├── <agent-slug-b>/
│ ├── config.yaml
│ ├── .env
│ └── logs/
│
├── <agent-slug-c>/
│ ├── config.yaml
│ ├── .env
│ └── logs/
│
├── .../
│ ├── config.yaml
│ ├── .env
│ └── logs/
│
└── .../
├── config.yaml
├── .env
└── logs/
Hermes Config for the Role Profile
The Slack manifest controls what Slack will send to Hermes. The Hermes profile config controls what Hermes will accept and what tools the Slack user can reach.
A safer profile config should include:
slack:
require_mention: true
strict_mention: true
free_response_channels: ""
allowed_channels:
- "C_ALLOWED_CHANNEL_ID"
platform_toolsets:
slack:
- clarify
- memory
- session_search
- skills
- todo
- web
quick_commands:
<agent-slug>-new:
type: alias
target: /new
<agent-slug>-stop:
type: alias
target: /stop
<agent-slug>-whoami:
type: alias
target: /whoami
<agent-slug>-status:
type: alias
target: /status
This matters because Slack slash command names are workspace-global. Generic commands are likely to collide across apps. Multiple Slack apps should not all register generic commands like: /new, /stop, etc. Follow an internal standardized naming convention, or adopt prefixed commands instead. Then map those dedicated commands back to Hermes built-ins with quick_commands. And as a good practice, avoid using slash commands as the main way to talk to the agent unless you have implemented that behavior. A safer approach is to DM or @mention the bot in an approved channel.
Allowed Users and Channels
Every role profile should define exactly who can use it.
In the role profile .env:
SLACK_ALLOWED_USERS=[REDACTED]
SLACK_HOME_CHANNEL=[REDACTED]
In the role profile config.yaml:
slack:
require_mention: true
strict_mention: true
free_response_channels: ""
allowed_channels:
- "C_ALLOWED_CHANNEL_ID"
Recommended defaults:
require_mention: true
strict_mention: true
free_response_channels: empty
allowed_channels: explicit list only
Avoid open-ended behavior like:
- allow all users
- respond in every channel
- free-response in broad channels
A bot should only respond where it is expected to respond.
Tool Access from Slack
Be careful with the tools exposed through Slack. A low-risk Slack toolset might include:
platform_toolsets:
slack:
- clarify
- memory
- session_search
- skills
- todo
- web
Add browser only if the agent needs browser automation:
platform_toolsets:
slack:
- clarify
- memory
- session_search
- skills
- todo
- web
- browser
Avoid exposing these to Slack unless the agent is intentionally allowed to perform high-impact actions from Slack prompts:
terminalfilecode_executioncronjobdelegationmessaging
These tools can be powerful and can create a lot of damage, fast. If they are needed, add additional controls:
- narrower allowed users
- narrower allowed channels
- approval steps
- separate OS user or container
- command logging
- secret redaction
- periodic access review
Slack should be an interface for conversation and coordination, not unrestricted shell access.
Quick Command Warning
Hermes supports quick commands. Some quick commands can run shell commands, and this is where extra caution should be applied. Avoid Slack-facing type: exec commands unless you have reviewed the command, restricted who can call it, and accepted the risk.
quick_commands:
<agent-slug>-status:
type: alias
target: /status
Slack App Installation Process
For each agent:
- Create a Slack app for that agent
- Enable Socket Mode
- Add the minimal bot scopes
- Add only the slash commands that the agent needs
- Subscribe only to the events the agent needs
- Install the app into the Slack workspace
- Copy the bot token and app token into that agent’s Hermes profile .env
- Configure allowed users and allowed channels
- Start the Hermes gateway for that profile
- Test in a DM first
- Test in one approved channel
- Review logs
- Only then invite the bot to more channels
Do not install every agent into every channel.
Example Identity
Agent role: <agent-slug>
Hermes profile: ~/.hermes/profiles/<agent-slug>/
Slack app: <agent-slug> Hermes
Bot display: <agent-name>
Bot handle: @<agent-slug>_hermes
Primary channel: #<agent-slug>
Example .env:
SLACK_BOT_TOKEN=[REDACTED]
SLACK_APP_TOKEN=[REDACTED]
SLACK_ALLOWED_USERS=[REDACTED]
SLACK_HOME_CHANNEL=[REDACTED]
Example config.yaml:
slack:
require_mention: true
strict_mention: true
free_response_channels: ""
allowed_channels:
- "C_DEDICATED-AGENT_CHANNEL_ID"
platform_toolsets:
slack:
- clarify
- memory
- session_search
- skills
- todo
- web
quick_commands:
<agent-slug>-new:
type: alias
target: /new
<agent-slug>-stop:
type: alias
target: /stop
<agent-slug>-whoami:
type: alias
target: /whoami
<agent-slug>-status:
type: alias
target: /status
Logging and Audit Model
Use layered audit trails and do not rely on Slack alone for incident investigation.
Slack gives you:
- bot identity
- channel
- message timestamp
- message content, depending on retention policy
- app-level activity, depending on Slack plan
Hermes gives you:
- profile logs
- session history
- gateway logs
- command handling
- tool calls, depending on enabled logging
The operating system and downstream services may give you:
- process logs
- file access logs
- cloud audit logs
- API access logs
- database logs
- deployment logs
A good production logging setup should answer:
- Who invoked the agent?
- Where did the request come from?
- Which Hermes profile handled it?
- Which tools were available?
- Which tools were used?
- What did the agent send back to Slack?
- Which external systems were touched?
- Which credentials were used?
- Can the token be revoked without affecting other agents?
Token Rotation and Revocation
Each agent should have its own token lifecycle. While you may want to take extra steps, in most scenarios you do not need to rotate unrelated role tokens unless there is evidence they were exposed.
For each Slack app, document:
- app owner
- bot token location
- app token location
- allowed users
- allowed channels
- approved scopes
- rotation process
- revocation process
- incident contact
If a token is suspected to be exposed:
- Revoke the affected Slack app token.
- Stop the affected Hermes profile gateway.
- Rotate the token in Slack.
- Update only that profile’s .env.
- Restart only that profile’s gateway.
- Review that profile’s logs.
- Review Slack messages sent by that bot.
- Review downstream systems the agent could access.
Production Readiness Checklist
Before treating an agent as production-ready, verify: [ ] The agent has its own Hermes profile [ ] The agent has its own Slack app [ ] The agent has its own bot token [ ] The agent has its own app token [ ] Tokens are stored only in that profile’s .env or secret store [ ] The default Hermes profile does not contain role Slack tokens [ ] Slack OAuth scopes are minimal [ ] Slack event subscriptions are minimal [ ] Allowed Slack users are explicit [ ] Allowed Slack channels are explicit [ ] require_mention is enabled [ ] strict_mention is enabled [ ] free_response_channels is empty unless explicitly justified [ ] Slack toolsets are minimized [ ] terminal/file/code execution tools are not exposed unless explicitly approved [ ] Slash commands are prefixed per agent [ ] Prefixed slash commands are mapped with quick_commands aliases [ ] Logs are retained according to policy [ ] Token revocation has been tested [ ] The app has an owner [ ] The profile has an owner [ ] The incident response path is documented
Wrap-Up
Keep the default Hermes profile Slack-free unless there is a specific reason to use it as a personal or main bot.
For each role agent:
- dedicated profile
- dedicated Slack app
- dedicated bot token
- dedicated app token
- dedicated set of scopes
- dedicated allowlist
- dedicated log trail
- dedicated owner
This architecture solves the multi-agent collaboration problem by respecting a simple principle: agents act independently with their own credentials. No proxy layers, no shared accounts, no inherited permissions. Slack’s audit logs show which agent acted. Compliance requirements are met by design.
It is the safest baseline. It does not replace broader production controls, but it gives you a clean foundation for least privilege, accountability, and controlled operations.
Enjoyed this read?
Some more posts you might like to read next: