Summarize PRs in Slack

Reviewers open every PR already knowing what changed, why, and where to start reading.

  1. ongithub pr.opened
  2. slackpost heads-up in #engineering
  3. agentsummarize the diff
  4. slackreply in thread

Build it with your coding agent

Paste into any coding agent with the Terse skills installed. No skills yet? Install them in one command.

/terse-create build https://www.useterse.ai/use-cases/pr-summaries-in-slack.md

Review latency is mostly orientation cost: before anyone comments, someone has to work out what a PR is actually doing. This job pays that cost once, at open time. The moment a pull request opens, it posts a heads-up in the team channel, has an agent read the diff, and threads a summary under the heads-up — what changed, why it matters, and what reviewers should look at first.

How it works

  1. Trigger — a pull request opens in the target repo; PRs from bots are filtered out before the job runs.
  2. Heads-up — a deterministic tool call posts one line to the engineering channel: who opened what. Fixed channel, fixed format, no agent involved.
  3. SummarygenerateText runs with the GitHub skill scoped to the repo, so the agent can read the diff, the changed files, and recent commits.
  4. Thread reply — the summary posts as a threaded reply under the heads-up, keeping the channel to one line per PR.

Requirements

  • A Terse project (terse init) with the GitHub and Slack integrations connected (terse integrate connect github, then slack).
  • terse generate run after connecting, so Repos.* and SlackChannel.* exist as typed constants in src/terse.generated.ts.
  • A repo to watch and a channel to post to — the only two decisions this job needs.

The job

typescript
import { createJob, generateText, type GithubPROpenedTrigger } from "terse-sdk";
import {
  Triggers,
  Skills,
  Repos,
  SlackChannel,
  toolbox,
} from "../terse.generated";
 
createJob({
  name: "Summarize PR and notify Slack",
  triggers: [Triggers.github.onPROpened({ repo: Repos.MyOrg.MyRepo })],
  filter: async (event: GithubPROpenedTrigger) => {
    return !event.sender.login.includes("[bot]");
  },
  onTrigger: async (event: GithubPROpenedTrigger) => {
    // Deterministic: fixed channel, fixed opener — use toolbox, no agent needed
    const message = await toolbox.slack.sendMessage({
      channelId: SlackChannel.Engineering.channelId,
      message: `New PR from ${event.sender.login}: ${event.pullRequest.title}`,
      thread_ts: "",
      blocks: "",
    });
 
    // Agentic: only the summary needs judgment
    const summary = await generateText({
      prompt:
        `Summarize the changes in this PR. ` +
        `Focus on what changed, why it matters, and what reviewers should look at first. ` +
        `Keep it concise. Context: ${event.formatForAgentRunner()}`,
      skills: [Skills.github({ repos: [Repos.MyOrg.MyRepo] })],
    });
 
    // Deterministic: post the result back in thread
    await toolbox.slack.sendMessage({
      channelId: SlackChannel.Engineering.channelId,
      message: summary,
      thread_ts: message.message_ts,
      blocks: "",
    });
  },
});

Repos.MyOrg.MyRepo and SlackChannel.Engineering aren't strings you look up — they're typed constants generated from your connected workspace by terse generate, so a renamed channel is a compile error, not a silent misfire.

Make it yours

  • Scope by path. Only summarize PRs that touch src/ or a critical directory — add the check to the filter.
  • Route by team. Map CODEOWNERS entries to different channels and send each summary where its reviewers actually live.
  • Add risk flags. Extend the prompt to call out migrations, dependency bumps, and auth-adjacent changes explicitly.
  • Cover follow-up pushes. Add Triggers.github.onPRSynchronized() to re-summarize when new commits land on an open PR.

For coding agents

This page is a build template. To implement it in a Terse project:

  1. Satisfy the Requirements section above (init, connect, generate).
  2. Create src/jobs/pr-summaries-in-slack.ts with the job above and add import "./jobs/pr-summaries-in-slack" to src/terse.jobs.ts.
  3. The constants (Repos.*, SlackChannel.*) and trigger/skill factories must come from the user's own src/terse.generated.ts — verify every name there and substitute the user's real repo and channel. Never invent names.
  4. Ask the user which repo and channel to target, test with terse test run "Summarize PR and notify Slack" against a pinned sample event, then deploy with terse deploy after they confirm.