Slack
Start AGNT5 workflows automatically from Slack messages, mentions, and reactions using the Slack Events API.
Connect Slack to AGNT5 and your workflows will start automatically whenever a Slack event fires. Every delivery is signature-verified before any workflow runs.
Setup
1. Create the integration in Studio
- Go to Settings → Integrations and click Add Integration.
- Pick Slack.
- Studio walks you through creating the Slack app and choosing the target environment.
2. Copy the app credentials from Slack
Go to Basic Information → App Credentials and copy the following values
| Field | Used for |
|---|---|
| App ID | Identifying your Slack app |
| Client ID | Identifies your app during OAuth authorization; included in the redirect URL when requesting user permissions |
| Client Secret | Paired with Client ID to exchange an authorization code for an access token, keep this server-side and never expose it publicly |
| Signing Secret | AGNT5 webhook verification (required) |
Paste each value into the required fields in Studio when prompted.
3. Complete the setup in Studio
Paste the credentials into the required fields and save. Studio registers the webhook URL automatically.
Events
The event name your trigger matches is slack.<event_type>, where event_type is the value of the Slack event.type field inside the payload.
| Event | Full event name | Required scope |
|---|---|---|
app_mention | slack.app_mention | app_mentions:read |
message (channels) | slack.message | channels:history |
message (groups) | slack.message | groups:history |
message (DMs) | slack.message | im:history |
reaction_added | slack.reaction_added | reactions:read |
reaction_removed | slack.reaction_removed | reactions:read |
member_joined_channel | slack.member_joined_channel | channels:read |
A single workflow can subscribe to multiple event types at once by passing multiple event() calls in triggers.
Workflow examples
Logging messages and mentions
- Workflows receive the envelope as
**envelope. - Subscribe to both
slack.messageandslack.app_mentionto cover channels and mentions in one workflow. bodymay be a JSON string or a dict, so parse defensively.- Filter out bot messages (
bot_id,subtype) to avoid reply loops.
import json
from agnt5 import WorkflowContext, workflow
from agnt5.types import event
def _parse_body(envelope: dict) -> dict:
body = envelope.get("body", {})
if isinstance(body, str):
try:
body = json.loads(body)
except json.JSONDecodeError:
return {}
return body if isinstance(body, dict) else {}
@workflow(
name="slack_message_logger",
triggers=[event("slack.message"), event("slack.app_mention")],
)
async def slack_message_logger(ctx: WorkflowContext, **envelope) -> dict:
body = _parse_body(envelope)
slack_event = body.get("event", {})
# skip bot messages to avoid reply loops
if slack_event.get("bot_id") or slack_event.get("subtype"):
ctx.logger.info("Slack message skipped: bot or unsupported subtype")
return {"status": "skipped"}
user = slack_event.get("user", "unknown")
text = slack_event.get("text", "")
channel = slack_event.get("channel", "")
ctx.logger.info("Slack message from %s in %s: %s" % (user, channel, text[:200]))
# add your processing logic here, e.g. call an agent, look up data
return {"status": "logged", "user": user, "channel": channel, "text": text}Viewing triggered runs in Studio
After a Slack event fires, the run appears in Studio → Runs within seconds. Open it to inspect the envelope, extracted fields, and any reply output.
[screenshot: Studio Runs list showing a completed slack_message_logger run triggered by a slack.app_mention event, with the run detail open showing the event body and workflow output]
Envelope structure
Every Slack-triggered run receives this envelope as **envelope:
{
"_webhook": true,
"source": "slack",
"integration_id": "int_abc123",
"event_type": "slack.app_mention",
"timestamp": 1733337600,
"headers": { "x-slack-signature": "v0=…", "x-slack-request-timestamp": "…" },
"body": "{\"type\":\"event_callback\",\"event\":{\"type\":\"app_mention\",\"user\":\"U123\",\"text\":\"<@U456> hello\",\"channel\":\"C789\",\"ts\":\"…\"}}"
}body is the raw verified request body. Parse it with json.loads. Slack does not include an idempotency_key (see Delivery semantics).
Signature verification
- Uses
X-Slack-Signature(v0=<hex>) withX-Slack-Request-Timestamp. - 5-minute replay window enforced.
- Requests with an invalid or expired signature are rejected with
401.
Delivery semantics
- Slack retries up to 3 times on non-2xx responses.
- Retries are not deduplicated. Slack provides no stable per-delivery id.
- Make your workflow idempotent using an id from the event body (e.g.
event.client_msg_id).
Related
- Event sources overview
- Webhooks: trigger mechanism, signature verification, and delivery semantics
- Workflows: how to write and run workflows