Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Slack By James Joyner IV · · 10 min read

Scaffolding a Bolt App With AI: The Fast-Junior Workflow

Use AI to scaffold a Slack Bolt app fast — boilerplate, event handlers, manifest — with a disciplined review checklist before it touches a real workspace.

  • #slack
  • #chatops
  • #bolt
  • #ai

I used to spend the first two hours of every new Slack project doing the same boring thing: copy a Bolt skeleton from an old repo, rip out the parts that didn’t apply, rename everything, and rebuild the app manifest by hand. It’s mechanical work, and it’s exactly the work I now hand to AI. A good model can stamp out a clean Bolt scaffold faster than I can find the old repo.

But I want to be precise about the mental model, because it’s load-bearing for the rest of this post. AI here is a fast junior engineer. It produces a lot of plausible code very quickly. It also makes the same mistakes a confident junior makes — over-broad scopes, a hard-coded secret it “just used for testing,” an event handler that ack’s late. So the workflow is two halves: let it scaffold fast, then review it like a senior before it ever points at a real workspace.

What “scaffold it” actually means

When I ask a model to scaffold a Bolt app, I’m asking for four artifacts: the app entry point with the right Bolt setup, a couple of representative event/command handlers, the app_manifest describing scopes and subscriptions, and a .env.example that documents every secret without containing one. I give it the requirements in plain English and let it draft.

Here’s a typical generated skeleton (Bolt for JavaScript, Socket Mode for local dev):

const { App } = require('@slack/bolt');

const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  appToken: process.env.SLACK_APP_TOKEN,   // Socket Mode app-level token
  signingSecret: process.env.SLACK_SIGNING_SECRET,
  socketMode: true,
});

// Slash command: /deploy-status <service>
app.command('/deploy-status', async ({ command, ack, respond }) => {
  await ack();                              // ack within 3s or Slack errors
  const service = command.text.trim() || 'all';
  await respond({
    response_type: 'ephemeral',
    text: `Fetching deploy status for *${service}*…`,
  });
});

// React to app mentions
app.event('app_mention', async ({ event, say }) => {
  await say({ thread_ts: event.ts, text: `Hi <@${event.user}>, how can I help?` });
});

app.error(async (error) => { console.error(error); });

(async () => {
  await app.start();
  console.log('⚡️ Bolt app running');
})();

That’s a solid starting point. Note the await ack() happening immediately — Slack requires acknowledgement within three seconds or it shows the user an error and retries. A model usually gets this right, but it’s the first thing I check, because a late ack is invisible in a quick demo and miserable in production.

Pro Tip: Ask the model to default respond and say to ephemeral and threaded replies. The worst first impression a new bot can make is shouting non-threaded messages into a busy channel during testing.

Generating the app manifest

The manifest is where scope discipline lives, and it’s where AI most needs supervision. Models love to request broad scopes “to be safe.” That’s backwards — every extra scope is attack surface and a harder install review for whoever approves the app. Here’s a generated manifest, trimmed to least privilege:

display_information:
  name: Deploy Status Bot
  description: Reports deploy status to on-call engineers
features:
  bot_user:
    display_name: deploy-status
    always_online: true
  slash_commands:
    - command: /deploy-status
      description: Show deploy status for a service
      usage_hint: "[service]"
oauth_config:
  scopes:
    bot:
      - commands          # required for the slash command
      - app_mentions:read # required for app_mention events
      - chat:write        # required to respond
settings:
  event_subscriptions:
    bot_events:
      - app_mention
  socket_mode_enabled: true
  org_deploy_enabled: false

When I review this I read every single scope and ask: does the code actually use it? If the manifest lists channels:history but no handler reads channel history, it comes out. The AI’s first draft is a proposal, not a decision.

The review checklist that keeps it safe

This is the part I never skip. Before a scaffolded app touches a real workspace, it goes through a fixed checklist:

  • No secrets in code. Tokens, signing secrets, and app tokens come from the environment. I grep the diff for anything that looks like xoxb-, xapp-, or a hex secret. The model should never have been handed a real one in the first place — never paste live tokens into a prompt — and it should never emit one either.
  • Least-privilege scopes. Every scope in the manifest maps to a line of code that needs it. Unused scopes get deleted.
  • Acks are immediate. Every command, action, and view handler calls ack() before any slow work.
  • Signatures verified. If the app runs over HTTP rather than Socket Mode, request signatures are verified — I don’t trust generated verification code without reading it line by line.
  • Errors don’t leak. No stack traces or internal hostnames posted back into Slack.
  • Idempotent event handling. Slack retries deliveries; a handler that posts a message must tolerate being called twice.

I run the generated diff through an automated pass at /dashboard/code-review/ to catch the obvious misses, then read it myself. The automated pass is the junior checking the junior; the merge decision is still mine.

Where the different tools fit

For raw scaffolding speed I lean on an AI-native editor — Cursor and GitHub Copilot are both excellent at filling in handler boilerplate as you type. For the manifest and the architectural “what scopes do I actually need” reasoning, I’ll have a back-and-forth with Claude instead, because it explains its choices and I can push back on them. Either way the output lands in a branch and goes through the checklist above before it ships.

If you want a head start on the prompts, I keep reusable scaffolding and review prompts in /prompts/, with the polished bundles in /prompt-packs/. And the broader /categories/slack/ collection covers the surrounding pieces — alerting copy, signature verification, the rest of a real ChatOps stack.

Wrapping up

Scaffolding a Bolt app is the perfect job for AI: high-volume, pattern-heavy, and tedious enough that you’d rather not do it by hand. Let the fast junior generate the entry point, the handlers, and the manifest in minutes. Then put on your senior hat and run the checklist — no secrets, least privilege, immediate acks, verified signatures, no leaked errors, idempotent handlers — before a single message reaches a real workspace.

The speed is real and worth taking. The review is what makes it safe. Keep both halves and you ship genuinely good Slack apps faster than you used to ship sloppy ones.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.