Once per Formation instance
- Configure
MESH_AGENT_MASTER_KEYand a stable, publicly reachable HTTPSPUBLIC_URL. Automatic setup requires an HTTPS origin without a path. Formation uses HTTP Events API delivery; no Socket Mode app token is needed. - In Slack’s Your Apps page, find Your App Configuration Tokens and generate a configuration token for the intended workspace. The Slack account must have permission to create apps. Workspace app-approval policies still apply.
- In Formation Settings → Slack app provisioning, paste the refresh token. Formation rotates it immediately, stores the resulting access/refresh pair encrypted, and refreshes it while the server runs. This credential belongs to a Slack user and workspace; it is not a universal Slack administrator key.
PUT /api/management/slack-provisioning with the refresh token,
which is write-only and retry-safe, plus a redacted status read and a
disconnect (capability slack.provisioning; see the
operator API). Either way the settings page and the status
report the connection’s health: ok, refresh_failing (Slack refused the last
refresh; the current access token keeps working until it expires and Formation keeps
retrying) or expired (setup fails until a refresh succeeds or a new refresh
token is connected), with Slack’s error code and when it happened.
The first version supports one current provisioning workspace per Formation instance. Replacing that connection changes the workspace used for new setup. Existing bot installations continue working. To update an app created in a previous workspace, reconnect provisioning for that workspace.
Creating an agent
- Name the agent and use instance model defaults or configure a supported model provider, then complete memory setup.
- Describe what the agent should do, then generate or write its profile. Review and edit that profile before creating its picture. Formation selects a recommended model from the current image catalog; another model or a PNG/JPEG upload remains available. Profile-driven pictures use the editable profile shown on this screen.
- Choose Slack and select Create Slack app. Formation creates the app, saves its credentials, registers a signed events URL, configures permissions and OAuth, and attempts to upload the picture.
- Select Install in Slack and approve the installation. Slack may require workspace-admin approval. Formation exchanges the authorization code on the server, validates the workspace and granted permissions, saves the bot credential, and activates the connection.
- Open the app in Slack and send a test message. Invite it to channels where it should participate.
/images/models and /images; generation uses the agent’s saved provider credential and may incur provider charges. A failed generation does not block manual editing or upload.
Automatic picture updates may follow profile generation or a saved profile change.
Uploaded pictures and pictures saved before provenance tracking are preserved;
choose Generate picture explicitly to replace them. Automatic generation never
runs on every keystroke. Only this agent’s name and the submitted editable profile
are sent for the picture; Formation does not add memories, conversations, connected
accounts, or secrets.
A wizard draft URL survives reload. Provisioning progress is stored on the server, so refreshing or resuming a draft does not create another Slack app. Credentials are never persisted in browser storage.
Delegated setup from a hosted console
A hosted control plane can run steps 3–4 for a console user who has no Formation session, once the instance has a provisioning grant (above). The management capabilities document advertisesslack.delegated_setup with a live
capability_status entry that is ready only while a working grant is
connected and PUBLIC_URL is valid; otherwise its reason says what is
missing (provisioning_not_configured, provisioning_expired, …). It requests a single-use, ten-minute delegation for one agent with its
management credential, and the user’s browser follows the returned link to
Slack and back to the console. The OAuth state is still single use, expires
after ten minutes, and is bound to the browser that opened the link (by a
host-only cookie for that attempt, not a session); the workspace, app, bot user
and scopes are checked exactly as above. Cookies are never shared across domains
and no administrator session is created. Each agent keeps its own Slack app and
bot user. See the operator API for the contract and outcome codes.
Readiness reports connected only after Slack has delivered a signed request to
the install (the events URL verification for an automatically created app, or
the first signed event); a saved, auth-checked credential alone is
credentials_saved. The first accepted human message and first delivered reply
are recorded as timestamps for first-conversation proof, never with content.
Recovery and maintenance
- Creation outcome uncertain: Formation will not retry app creation blindly. Inspect the apps in Slack and recover that app using the manual connection option. The creation intent remains blocked rather than risking duplicates. Automated orphan reconciliation/deletion is not implemented.
- Configuration failure: resume setup against the saved app ID. Rate-limit errors expose Slack’s retry delay; retry after that interval.
- Picture upload failure: installation remains available. Download the avatar and upload it through Slack’s app settings, or retry Sync profile picture.
- Expired/cancelled OAuth: return to the saved setup and start a new installation attempt. OAuth state is single-use, user-bound, bound to the dashboard session (or, for delegated setup, to the browser that opened the delegation link), and expires after ten minutes.
- Saved installation awaiting activation: use Activate connection. The bot credential has already been saved; another OAuth approval is unnecessary.
- Changed hostname or configuration: open the connection’s Manage automatic Slack setup and picture link and select Update Slack configuration. This updates the existing app’s event and OAuth callback URLs using the current
PUBLIC_URL. - Changed avatar: use Sync profile picture on each managed Slack connection. Uploading/generating a new Formation avatar marks app icons pending; it does not silently publish the new picture to every connected app.
- Revoked or expired provisioning grant: the settings page (and the management status) shows
refresh_failingorexpiredwith Slack’s error code. Reconnect it in Settings, or have the control plane connect a new refresh token. Disconnecting provisioning removes its Formation credential; it does not uninstall existing apps or revoke their bot tokens.
Implementation and verification
Migration0042 adds durable Slack app intents, OAuth attempts and bounded PNG avatar storage. App client/signing credentials and OAuth bot credentials are encrypted with the existing secret store. Pending URL verification checks Slack’s timestamped HMAC before the app is installed; active events must also match the recorded app and workspace before entering the existing ingress.
Migration 20261021023239 records avatar provenance and a monotonically increasing
revision. Existing rows become unknown, which automatic updates preserve.
Uploads become uploaded; generated pictures become generated; provisioning
fallbacks become default. Conditional database writes prevent an old generation
from overwriting an upload or a newer picture, including after client cancellation.
The profile and picture API contract
defines the live catalog recommendation, edited-profile input, avatar state,
provenance, revision checks, and recovery responses for programmatic callers.
Automated checks cover encrypted persistence, concurrent token rotation, interrupted/ambiguous app creation, safe retries, pending signed challenges, OAuth session/workspace/scope validation and replay prevention. Browser coverage uses the real Go server and PostgreSQL with local Slack/OpenRouter fakes, and exercises both manual and automatic onboarding, identity generation, reload/resume, OAuth activation, configuration repair and expired authorization.
Automated tests use local provider fakes; they do not certify your live Slack
workspace or model account. Validate app creation, icon upload, URL verification,
workspace approval and a real DM when configuring a deployment. A manual icon
upload remains available when automatic upload fails.
This implementation does not include manager-app enrollment, unattended child-app installation, public-channel discovery/joining, uninstall/revocation event handling, automatic orphan cleanup, a dedicated provisioning audit UI, or bulk hostname repair.
Troubleshooting the configuration connection
An expired access token on Slack’s App Configuration Tokens page does not require pasting that access token into Formation. Formation uses the refresh token to obtain a new pair throughtooling.tokens.rotate.
If connecting returns Slack: invalid_arguments on an older build, upgrade to
the fix that sends rotation requests as application/x-www-form-urlencoded.
Slack’s live endpoint ignores JSON rotation bodies and reports a missing
refresh_token, even though its reference lists JSON support. A rejected request
of this kind does not rotate the token; retry with the refresh token after upgrading.
If Slack instead returns invalid_refresh_token, generate a new configuration
token pair in Slack and paste its refresh token.
Unexpected provisioning failures (HTTP 5xx responses) now reach the configured
error tracker with component admin.api, the route pattern, and a classified
error code, including slack_invalid_arguments. Tokens, request bodies, URLs,
and raw provider/database errors are excluded. Expected OAuth and setup-state
conflicts are not reported as failures.