This is Part IV of the series AI & The Translator. Part I covers the architecture. Part II covers the zero-dollar build. Part III covers the system prompts. This part locks the front door.
The system works. OpenClaw scrapes the open web. The leads land in Slack. Claude reads them and briefs you over coffee.
But the pipe that connects OpenClaw to your Slack workspace is the weakest link. If that bot token leaks, what can the attacker do?
The answer depends entirely on what permissions you gave the bot. A professional agency requires Identity and Access Management. We will apply the Principle of Least Privilege: the bot will have permission to write to the channels we invite it to, but it will have zero permission to read your messages, access your files, or see your admin settings.
Step 1: Building a “deaf” bot
Location: api.slack.com
We are creating a specific identity for the research assistant, our scout (aka the bot).
- Create App: Go to Your Apps → Create New App → From Scratch.
- Name:
OpenClaw_Scout. - Workspace: Select your workspace.
- Permissions (the critical step):
- Go to OAuth & Permissions in the sidebar.
- Scroll down to Bot Token Scopes.
- Add ONLY this scope:
chat:write. - DO NOT ADD:
channels:read,groups:read,files:read, orusers:read. - Why? If this token is compromised, the attacker can post messages, but they cannot exfiltrate your client data or read your internal strategy discussions.
- Install: Click Install to Workspace.
- The Key: Copy the Bot User OAuth Token (starts with
xoxb-).Store this as an environment variable on your bot's device.On Windows: System Properties → Advanced → Environment Variables → New, with the nameSLACK_BOT_TOKENand the token as the value.On Mac: addexport SLACK_BOT_TOKEN=xoxb-your-tokento your~/.zshrcfile.
Step 2: The agent configuration
Location: The clean laptop running OpenClaw
We update your local agent to use this specific identity. Instead of an open pipe, it now authenticates as the restricted bot.
This script requires Python 3.8+. If you are installing Python on Windows, check “Add Python to PATH” during setup. Then open a terminal and run: pip install slack-sdk
import os
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
# Load the restricted token from your environment variable
client = WebClient(token=os.environ.get("SLACK_BOT_TOKEN"))
def report_lead(lead_data):
"""
Posts a structured job lead to the ops channel.
The bot can ONLY write. It cannot read channel history, files, or user profiles.
"""
try:
blocks = [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"*NEW LEAD: {lead_data['role']}*"
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": f"*Org:* {lead_data['org']}"
},
{
"type": "mrkdwn",
"text": f"*Deadline:* {lead_data['deadline']}"
},
{
"type": "mrkdwn",
"text": f"*Source:* {lead_data['source']}"
},
{
"type": "mrkdwn",
"text": f"*Risk:* {lead_data['risk_score']}"
}
]
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "View Source"
},
"url": lead_data['link']
}
]
}
]
# Post to the restricted channel
# The bot MUST be invited to this channel first
result = client.chat_postMessage(
channel="C12345678", # Your #ops-incoming ID
blocks=blocks,
text=f"New Lead: {lead_data['role']}"
)
except SlackApiError as e:
print(f"Error posting to Slack: {e.response['error']}")
Step 3: A manual invite
Location: Slack workspace
This is the “air gap” within the software. Because we did not give the bot chat:write.public (which lets it post anywhere), it is effectively in a cage. It cannot enter a room unless a human opens the door.
- Create a private channel:
#ops-incoming. - Do not invite the bot anywhere else!
- Go to
#ops-incomingand type:/invite @OpenClaw_Scout.
Now the bot exists only in that room. If it tries to post to any other channel, the API will return a channel_not_found error. You have compartmentalized the risk.
Step 4: After delivery
The bot has posted the raw leads. Now what?
Claude in Slack — your Intelligence Officer from Part III — reads the channel natively. It does not use the bot’s token. It does not need the bot’s permissions. Claude accesses Slack through its own integration, with its own authorization.
When you say “brief me,” Claude processes what the bot posted and delivers your morning brief. No additional wiring. No middleware. The bot posts; Claude filters per your brief and reads to you.
Two separate systems. Two separate permission sets. Neither one can impersonate the other.
The security audit
Here is what each component can and cannot do:
| Component | Permissions | Risk profile |
|---|---|---|
| OpenClaw Bot | chat:write (restricted) | Zero read access. Cannot see client files or chat history. |
| #ops-incoming | Private channel | Quarantined. The only place the bot is allowed to exist. |
| Claude in Slack | Slack integration (separate auth) | Reads channel content via its own token. Cannot post as the bot. |
| You | Admin | Gatekeeper. Must manually invite the bot to activate the pipe. |
You have built a one-way valve. Information flows into your secure environment from the public web, but the mechanism that brings it in has no ability to see what is already there.
