Shipwright Harness

Slack Integration

The Shipwright agent communicates via Slack using the Bolt SDK in Socket Mode — no public HTTP endpoint needed. The agent handles DMs, @mentions, reactions, file attachments, and voice transcription. Cron jobs post their results to a configured Slack channel.

How it works

The agent connects to Slack via a persistent WebSocket (Socket Mode). Every incoming message arrives as a prompt; the agent runs Claude and posts the response back to the same thread.

Messages are prefixed with [Name]: where Name is the sender’s Slack display name, so the agent knows who it’s talking to. Cron job results are posted to a configured channel automatically.

Connecting a Slack app

Slack provisioning is automated via the /admin/provision flow. Follow these four steps:

Step 1: Open the provisioning form

Navigate to /admin/provision in the Shipwright admin UI. You’ll see a form with the following fields:

  • Agent — select which agent to configure
  • GitHub credentials — either a Personal Access Token (PAT) or a GitHub App installation for repo access
  • Anthropic API key (optional) — if you want the agent to use a custom API key
  • Claude Code OAuth token (optional) — if you want to enable Claude Code integration
  • Slack app configuration token — a xoxe.xoxp- token (see below)

Understanding the Slack app configuration token

A xoxe.xoxp- token is a Slack app configuration token — a personal token scoped to your Slack workspace that allows creating and configuring Slack apps via the API. To obtain one:

  1. Go to api.slack.com/apps
  2. Click Create New App and select From scratch (not from a manifest)
  3. Name your app and select your workspace
  4. Once created, go to App-Level Tokens in the left sidebar
  5. Click Generate Token and Scopes
  6. Name the token (e.g., “Shipwright Provisioning”)
  7. Add the admin scope (or all available scopes for maximum compatibility)
  8. Click Generate and copy the token (it starts with xoxe.xoxp-)

This token is used only once during provisioning — Shipwright calls the Slack API to create the actual bot app and does not store this token afterward. Delete the placeholder app you created above to retrieve the configuration token once provisioning completes.

Step 2: Shipwright creates the Slack app

After you submit the form with valid GitHub credentials and the Slack configuration token, Shipwright:

  1. Calls apps.manifest.create to create a new Slack bot app with the necessary permissions
  2. Automatically stores the following credentials in the agent’s environment:
    • SLACK_APP_ID — the app’s ID
    • SLACK_SIGNING_SECRET — used to verify incoming Slack requests
    • SLACK_CLIENT_ID — OAuth client ID
    • SLACK_CLIENT_SECRET — OAuth client secret

All of this happens automatically — no manual steps needed.

Step 3: Authorize the Slack app

After Step 2 completes, the provisioning form shows an Authorize Slack App → button. Click it to:

  1. Redirect to Slack’s OAuth approval page
  2. Approve the app to post to your workspace
  3. Redirect back to /admin/provision/complete

Shipwright automatically stores SLACK_BOT_TOKEN (the bot user OAuth token) in the agent’s environment. You do not need to copy it manually.

Step 4: Enable Socket Mode and generate the app token

This is the one remaining manual step:

  1. Go to api.slack.com/apps and select the app that was just created (it will have a similar name to your agent)
  2. In the left sidebar, go to Socket Mode
  3. Click the toggle to Enable Socket Mode
  4. A panel appears asking you to generate an app-level token
  5. Click Generate Token and Scopes
  6. Name the token (e.g., “Socket Mode Token”)
  7. Add the connections:write scope
  8. Click Generate and copy the token (it starts with xapp-)
  9. Return to the Shipwright admin UI and paste the xapp- token into the Socket Mode field
  10. Submit the form

Once submitted, the agent will connect to Slack via Socket Mode on its next startup.

Required Slack environment variables

VariableRequiredDescription
SLACK_BOT_TOKENyesSlack bot user OAuth token (xoxb-...)
SLACK_APP_TOKENyesSlack app-level token for Socket Mode (xapp-...)
SLACK_SIGNING_SECRETyesVerifies incoming Slack request signatures
SLACK_ADMIN_TOKENnoOptional admin-level token for privileged Slack operations
SLACK_ALERT_CHANNELnoChannel ID to post system alerts (e.g. startup errors)
SLACK_OWNER_USERnoSlack user ID of the agent owner, used for DM fallback

Interacting with the agent

Direct messages

Send the agent a DM to start a private conversation. The agent replies in the same thread. Each session maintains conversation continuity — successive messages in a thread resume the same Claude conversation.

@Shipwright What's the status of the current task queue?

Mentions

Mention the agent in any channel where it has been invited:

@Shipwright run /shipwright:dev-task

The agent picks up the mention and responds in a thread on the same message.

Reactions

The agent can also respond to reaction_added events. This is useful for triggering workflows from a thumbs-up or a custom emoji without sending a message.

Voice notes

Voice notes arrive pre-transcribed by Whisper STT as [voice transcript: <text>] in the prompt. The agent replies with a [speak:text] marker to deliver a spoken response — conversational, no bullet points, one to three sentences.

Voice support requires agent.voice.enabled=true in the Helm chart (see Deploying to Cloud) or a WHISPER_SERVICE_URL / GROQ_API_KEY in the agent environment.

Response markers

The agent embeds markers in its responses to trigger side effects. Markers are stripped from the visible message before posting:

MarkerEffect
[silent]Skip posting entirely (useful for cron jobs with nothing to report)
[upload:/path/to/file]Attach a file to the message
[react:emoji1,emoji2]Add emoji reactions to the agent’s reply
[speak:text]Synthesize speech and upload as audio
[plan:url]Post a plan link to the rendered planning artifact

Cron job notifications

Cron jobs are scheduled prompts that run on a recurring schedule and post results to Slack. Most crons are silent by default — they only post when there is something worth surfacing (a completed PR, a failing check, or an error).

The channel field on a cron job controls where results are posted. When user is set instead of channel, results are posted as a DM to that user.

To configure which channel receives cron results, set the channel on each cron job via the admin UI or the /agents/:id/crons/:cronId API, or set SLACK_ALERT_CHANNEL as the global fallback for system alerts.

Message format

Incoming Slack messages always arrive with the sender’s Slack display name prepended:

[Alice]: Please review the latest PR on the metrics service.

The agent uses this prefix to know who is making the request, which is especially useful in channels where multiple people may be interacting with the same agent.

Next steps

With Slack connected, the agent is fully operational as a 24/7 autonomous delivery system. Enable the opt-in cron jobs from the admin UI to automate review, patching, deployment, and maintenance — see The Agent for the full cron reference.