Set up Slack
Follow Automatic Slack setup to create and install an app through Formation. You can also generate a manifest and connect an existing app with its App ID, bot token and signing secret. Use the agent’s app and account, not another agent’s credentials. Set a stable, publicly reachable HTTPSPUBLIC_URL before setup. Formation uses the
HTTP Events API, not Socket Mode. After installation, send a DM and invite the
app to its intended channels. A connected app does not automatically discover
and join every public channel.
Managed apps use /api/slack/events/{appID}. Manual apps use /slack/events.
Use the exact URL shown by the setup flow. Changing Formation’s hostname requires
updating the app’s stored event URL; managed apps provide Update Slack
configuration for this.
Permissions and connection health
The generated manifest includes the event subscriptions and bot scopes Formation needs. Existing apps may need updated scopes and a reinstall when capabilities change. Check permissions on a managed app checks the token’s live identity and granted scopes. Update Slack permissions updates the existing app and opens Slack approval for the same installation. Missingfiles:read prevents attachment fetches. Channel and DM names require
metadata scopes (channels:read, groups:read, im:read, mpim:read) as well
as user access. Valid scopes do not prove membership in a particular channel.
The dashboard resolves channel and participant names through the owning
installation, with cached names and stored IDs as fallbacks. A failed metadata
lookup does not hide conversation history.
Messages, threads and identity
Slack events route by(api_app_id, team_id) to one agent connector. The lookup
selects that installation’s signing secret; then Formation verifies the timestamped
HMAC. An unknown route and an invalid signature both receive 401. Timestamps
must fall within five minutes of Formation’s clock.
Being present in a channel does not mean every message addresses the agent.
Addressing decides whether it observes or engages.
Self-authored echoes are dropped; another participant’s bot flag is a message
signal, not a global classification of that participant as an agent or human.
Formation does not tell an agent that a peer is hosted by the same deployment.
Inbound Slack formatting is normalized for model context. Outbound canonical
Markdown is rendered to Slack’s format at delivery, with chunking as needed.
Formation conversation keys are internal identities and are never passed as Slack
channel IDs.
Attachments
Image attachments can be fetched for a turn when the selected model supports image input and authorization succeeds. If the image cannot be fetched or shown, the prompt reports that limitation instead of implying the agent saw it. For documents,list_documents and read_document read authorized PDF, DOCX and
UTF-8 TXT attachments, including eligible earlier uploads. See Document
reading for format coverage, pagination and limits.
Scanned PDFs and omitted document structures are not silently treated as read.
Attachment access uses the owning connector’s credentials, current audience
checks, URL/redirect restrictions and byte limits. A file URL in an event is not
permission to send a Slack token to an arbitrary host.
Delivery and troubleshooting
Ingress acknowledges accepted events promptly and runs work outside the HTTP request lifetime. PostgreSQL-backed event claims distinguish completed duplicates from in-flight work; transient claim failures return a retryable response. An in-memory dedupe set also exists as a fallback, not the production durability guarantee. Durable claims alone do not make all runtime configuration multi-replica ready. Slack sends have bounded recovery for explicitly rejected HTTP 429 responses. Ambiguous network outcomes are not blindly retried, and a partially delivered multi-part reply is not reported as fully delivered. See Slack delivery recovery. Formation uses best-effort reactions for working, done and failed states. Reactions can fail independently of a reply and are not delivery receipts. If an agent is silent, check the event URL, app permissions, channel membership, engagement verdict and run/delivery outcome in Observability. Implementation:internal/connector/slack
and internal/app/slack_ingress.go.