# Draft Outreach to Open Source Contributors

Yes. An agent ranks a project's contributors from 90 days of merged pull requests and saves a note citing their own work in your Notion CRM for you to send.

[Run this on Rush](https://cloud.getrush.ai/run/draft-outreach-to-contributors/notion/).

## What the agent does

The run reads a public repository and needs none of yours. Backstage, `backstage/backstage`, is a Yarn monorepo with `packages/` and `plugins/` at the root, and it merges pull requests as single squashed commits whose subject ends with the pull request number, such as `fix: ... (#36208)`. That makes its history a clean record of merged work: one commit per merged pull request, with the author's name on it.

The agent clones the repository with `git clone --shallow-since` set 90 days back and runs `git log --format='%an|%s'` to count merged pull requests per author. It drops automation before ranking: `renovate[bot]` and `dependabot[bot]` dependency bumps (the repository has `renovate.json5` and `dependabot.yml` under `.github/`) and the release commits that the `sync_version-packages.yml` workflow opens. It takes the ten authors with the most merged pull requests and maps each one to a GitHub profile through a pull request's public page in its browser.

For each person it picks two recent merged pull requests and reads what they changed: the paths touched under `plugins/` or `packages/`, and the `.changeset/` file the pull request added, which names each package and whether the change was a patch or a minor. It also checks `OWNERS.md`, which lists the core maintainers and each project area's maintainers, so the note can say when someone maintains the catalog or auth area rather than contributing once.

It then reads the schema of the Notion database you named and adds one row per person with their public profile URL, the two pull request links and a two-sentence note that cites what they built. It fills only existing properties. When all ten rows are written it messages you in Slack, through your own sign-in, so you can approve them. It contacts no contributor.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Clone https://github.com/backstage/backstage with git clone --shallow-since set 90 days ago. Count merged pull requests per author from git log, leaving out renovate[bot], dependabot[bot] and release commits. For the ten most active authors, find their public GitHub profile and two recent merged pull requests, and read each pull request's changed paths and its .changeset entry. Note when OWNERS.md lists them as a maintainer. Read the schema of the Notion database named below and add one row per person with the profile URL, both pull request links and a two-sentence note that cites their work. Fill only existing properties. Do not collect email addresses. Message me in Slack when done.\n\nNotion database: Backstage contributors",
  "connections": [
    "notion",
    "slack"
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is ten rows in Notion, one per contributor: their profile link, two merged pull requests you can click through, and a note specific enough that the person recognises their own work, for example a scaffolder action they added or a catalog processor they fixed. Your Slack direct messages hold the agent's message, sent as you, with the list. The session's `result` and the webhook's `data.result` carry the ranking it used, so you can see who was eleventh and why.

The transcript at `GET /o/{org}/sessions/{id}/messages` keeps the exact `git log` command and its output, which is the evidence for the ranking, and every Notion call the agent made. A reviewer can rerun the count from that command and confirm the bots were left out.

Before sending, a person checks that each cited pull request is the contributor's own work and not a co-authored change, that the note does not read as a recruiting or sales template, and that the channel you use is one the person has made public for contact, such as the email on their GitHub profile or a link on their site.

## Run it on every first Monday of the month

Contributor activity changes month to month. A scheduled job on your server can call `POST /o/{org}/sessions` with this request once a month, using the month as the `Idempotency-Key` so a retried job does not start a second run. Change the database name in `input` if you keep one database per month.

To cover several projects, start one run per repository. A key runs at most its `max_concurrent` sessions at once, 4 by default, and answers `429` above that, so queue the rest. A webhook on the key tells your job when each run is done.

## Why run it on Rush?

Counting merged work from git history, filtering out bots and reading each pull request is mechanical but slow, and it is the part people skip, which is why most contributor outreach reads like a template. On Rush the agent has a full clone and a browser in its own sandbox, runs the real `git log`, and keeps the output, so the ranking is something you can check rather than a list someone typed.

The run reaches only what the request names: Notion and your Slack sign-in. Tokens stay outside the sandbox, and the record of every command and page stays with the session. When a contributor asks how you found them, you can point to their own merged pull requests.

## Frequently asked questions

### Why count merged pull requests rather than commits?

Backstage squashes each pull request into one commit with the number in the subject, so here they are the same thing. On a project that merges with merge commits, change the prompt to count `git log --merges` or ask the agent to read the pull request list instead.

### Will it scrape contributors' email addresses?

The prompt says not to. Commits carry author emails, and in Backstage every commit also has a `Signed-off-by` line for the project's DCO, but those were given to sign work, not to receive outreach. The row holds a public profile link instead.

### Can it rank by area instead of the whole repository?

Yes. Add a path to the log, such as `git log -- plugins/catalog-backend`, and the ranking covers only that area. `OWNERS.md` names each area's maintainers, which helps if you want to reach the people who review a plugin, not only those who change it.

### Does it message the contributors?

No. It writes drafts into Notion and messages only you. A person reads each note and decides whether to send it.
