From 681a53e7171bb96c71f868847494cbe1aa62d607 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 15 Oct 2026 22:30:09 +0000 Subject: [PATCH 1/8] Add the grok-bots article at /grok-bots/. Use the page layout so the long post renders in the monospace theme. The title stays in front matter, so it is not printed twice. Co-authored-by: Michael Neeley --- grok-bots.md | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 grok-bots.md diff --git a/grok-bots.md b/grok-bots.md new file mode 100644 index 0000000000000..af36ebb5e8a54 --- /dev/null +++ b/grok-bots.md @@ -0,0 +1,185 @@ +--- +layout: page +title: "My Team of Twenty Bots" +permalink: /grok-bots/ +--- + +*How I run a small team of AI assistants alongside my day job as an engineering lead, and what I've learned doing it.* + +I'm Michael Neeley ([@redreceipt](https://github.com/redreceipt)). I lead engineering at [Differential](https://differential.com), where we build Apollos, a platform for church apps, plus the apps that run on it. Like most engineering leads, I spend my days switching between code review, project tracking, support escalations, a full inbox, meetings, and the constant feeling that the codebase needs some love nobody has time to give it. + +A few months ago I started handing pieces of that work to a team of AI assistants, Grok Bots. I didn't set up one giant "do everything" agent. I set up a bunch of small ones, and each owns one job. There are twenty of them now. This post covers who they are, how they fit together, and the rules I've had to write along the way. If you're an engineering leader or developer wondering whether a team of assistants is worth it, I hope it saves you some trial and error. + +One caveat: this post describes how the setup works. It isn't a results report, and there are no productivity numbers in it. + +--- + +## Why a team instead of one assistant? + +My first try was one assistant with lots of instructions. It got muddy fast, and when something went wrong I couldn't tell which instruction caused it. Splitting the work up fixed most of that: + +- **Each bot has one job and a short brief.** It's easier to write, easier to debug, and easier to tighten when it does something I don't like. +- **Ownership is clear.** Only one bot touches my inbox. Only one bot reviews a given kind of PR. Two bots never fight over the same thing. +- **I can turn things off one at a time.** If the performance bot gets noisy, I pause it, and nothing else breaks. +- **Names help.** "Nanny says CI is red" is easier to take in than "the assistant says CI is red." + +## How it fits together + +There's one hub and a lot of spokes. **Switchboard** is my executive assistant. Every other bot either reports to it or works quietly in its own lane. Most of the hands-on coding gets handed off to cloud coding agents (I use Cursor's), which open small pull requests. Humans review every one of those PRs. Some get merged by hand. Others have auto-merge turned on, so they land by themselves once the required human reviews and CI pass. + +``` + ┌──────────────┐ + │ Michael │ + └──────┬───────┘ + one daily briefing │ reviews, approvals, decisions + ┌──────▼───────┐ + │ Switchboard │ ← executive assistant / hub + └──────┬───────┘ + ┌───────────────┬──────────┼───────────────┬────────────────┐ + │ │ │ │ │ + Coordination Inbox & PRs Code improvement Production & support + Foreman Sieve Keystone Smoke Triager + Trawler Nanny Codemod Hotpath Pipeline + Chisel Stamp Pruner Intruder Medic + Bottleneck Semver Onramp Compass + │ + Cursor cloud agents + open small PRs → human review + CI → merge + (by hand, or by auto-merge on some bots' PRs) +``` + +The tools they work through are ordinary: GitHub, Linear, Slack, Gmail, Google Calendar, Granola (meeting notes), Sentry, Airflow, and Expo. + +## The daily rhythm + +**Before the briefing**, the coordination bots do their passes. Foreman checks the Linear projects I lead. Trawler scans engineering projects more broadly. Chisel looks for scope creep. Nanny and Stamp roll up PR activity. Semver sweeps dependency PRs at 8:35. Each one sends a short digest to Switchboard. + +**At 8:42 every weekday**, Switchboard sends me one briefing. It merges those digests, drops anything that doesn't need me, and adds prep for the day's meetings. For a recurring meeting, it pulls the Granola notes from the last one in the series so I walk in remembering what we said. On Fridays it adds talking points for my 1:1s with developers. + +**During working hours**, the code-improvement and production bots each run about once an hour on weekdays. Their start minutes are staggered, and most runs end with nothing to do, which is the point. Sieve clears inbox noise every hour, around the clock. Nanny keeps an eye on my own PRs. + +**Mondays** bring the bigger-picture stuff: Bottleneck's weekly constraint report. Once a month, Keystone writes a tech-stack proposal. + +The daily status comes to me as one message. Beyond that, bots ping me mostly when they've opened a PR or need a decision. + +--- + +## The roster + +### Coordination + +**Switchboard: Executive Assistant** +The hub. It keeps the other bots on task, sends work to whichever teammate fits best, and builds the morning briefing. When I make a new standing rule ("stop @-tagging people in Slack unless they need to act"), I tell Switchboard and it relays the rule to every bot it applies to. *Never does:* the specialist work itself. It delegates. + +**Foreman: Project Manager** +Watches the Linear projects I lead every day. It works to unblock them and posts project updates when something material changes. Once a week it sweeps for stale tickets and hands the follow-up to cloud agents. *Never does:* post updates for the sake of posting. Quiet weeks stay quiet. + +**Trawler: Linear Projects** +A wider net than Foreman. It scans engineering projects across the team for status, blockers, and drift, then sends a short digest to Switchboard. Its job is to watch and report. + +**Chisel: Engineering Manager (Scope Hammer)** +Every weekday morning, Chisel compares each in-flight project's stated scope against what people are actually working on: active issues, open PRs, board state. Then it tells me where scope is bloated or drifting and what to cut, defer, or merge to protect the critical path. *Never does:* overlap with Foreman. Foreman unblocks, and Chisel recommends cuts. + +**Bottleneck: Constraints Advisor** +Every Monday, Bottleneck reads as widely as it can across Slack, Linear, and our project tools, then gives me *one* top constraint on the business, with evidence and concrete recommendations. Getting exactly one answer forces prioritization. *Never does:* hand me a list of ten problems. + +### Inbox & PRs + +**Sieve: Email & Linear Triage** +The bot that owns inbox triage. (Semver is the one exception; see below.) It runs hourly against my Gmail and Linear notifications and follows explicit, numbered rules for what counts as skippable. One example: a GitHub PR email thread gets archived if the PR has merge conflicts or changes requested, or if it's in a repo that doesn't require my approval. It archives whole threads, never individual messages, so nothing pops back up half-read. Real asks and blockers stay put. *Never does:* clear in bulk without an approved policy. + +**Nanny: PR Monitor** +Babysits *my* pull requests. It tracks reviews, comments, CI status, and auto-merge status, and grabs proof screenshots when a PR needs them. About once an hour it also checks my draft PRs and asks whether each one should be marked ready, closed, or kept. *Never does:* merge, or update a branch just because it's behind main. + +**Stamp: PR Reviews** +Handles the boring reviews: TypeScript migrations, codemods, and other mechanical refactors, whoever wrote them. When one of these requests my review, Stamp comments `@codex review this` from my account (the Codex reviewer only responds to me). If Codex comes back clean, Stamp approves. If it has findings, Stamp leaves a comment asking the author to address them, then re-requests the review after they push. In repos that don't require approvals, it just tells the author they're clear to merge. *Never does:* merge, enable auto-merge, push code, or touch anything that changes CI, workflows, or guardrails. Drafts, PRs with conflicts or changes requested, and anything not clearly mechanical get skipped. + +**Semver: Dependency Updates** +Works through Dependabot PRs. A sweep runs at 8:35 every weekday, and it also wakes on PR events. It sorts each bump into safe or risky. It does the prep work itself (fixing CI, splitting a huge bump into smaller draft PRs) before asking any human for time, and it only requests as many reviewers as the repo actually requires. For a **safe** bump that's ready (CI green, no conflicts, no blocking reviews), Semver approves it from my account and turns on squash auto-merge. Where the repo allows, it merges the PR directly. **Major or risky** bumps get a risk/migration checklist, no auto-merge, and a ping to me so I can merge them deliberately. It also does a little inbox cleanup of its own in my work Gmail: it archives notification threads for merged Dependabot PRs and approval emails on PRs I didn't write. That's the one place where inbox work isn't only Sieve's. *Never does:* auto-merge or approve a major or risky bump. + +### Code improvement + +These bots share one pattern, and it's the most useful thing in this post: **the one-open-PR gate.** Every bot has its own GitHub label (`architecture`, `slop`, `e2e`, `performance`, and so on). Before it starts work, it checks every repo in scope for an open PR with its label. If one exists, the bot does nothing and says nothing. So each bot has at most one PR in front of humans at a time. The pace of the work matches our review capacity, and the bots can't bury the team in PRs. + +The bots in this group don't all handle PRs the same way, though. Under their current briefs, **Codemod, Pruner, Smoke, and Onramp** open ready-for-review PRs, turn on auto-merge where the repo supports it, and request at least two reviewers from the code owners or recent authors of the touched paths. Onramp waits for green CI before it requests them. Their PRs land automatically once those required human reviews and CI pass. **Keystone, Hotpath, and Intruder** (and Triager and Pipeline, below) open *draft* PRs and don't turn on auto-merge. A human marks those ready and merges them. Honestly, this is mid-transition: the older hourly prompts for the auto-merge bots still say "draft PR," and the current briefs win. + +**Keystone: Software Architect** +Looks for places where the contracts between our services and apps are implicit, and makes them explicit. Think clearer boundaries between services and fewer handoff gaps. It opens small draft PRs. Once a month, before my briefing, it surveys the tech stack and writes one technical proposal in Linear, with evidence, tradeoffs, and a migration plan. *Never does:* pitch speculative rewrites. Concrete flow improvements beat grand redesigns. + +**Codemod: TypeScript Migration** +Moves JavaScript to TypeScript in small, mechanical, type-safe steps. It goes after duplicated JS/TS modules first. *Never does:* change behavior in a migration PR. + +**Pruner: Code Cleanup** +Hunts for slop: useless tests, pointless wrappers, extra complexity, and places where we drifted from a dependency's recommended patterns. It leans toward deleting and simplifying instead of adding structure. *Never does:* add abstraction in the name of cleanup. + +**Smoke: E2E Testing** +Finds critical user flows with no end-to-end coverage and adds tests for them. *Never does:* write brittle or speculative tests just to bump a coverage number, or invent reviewers. + +**Hotpath: Performance** +Looks for real, low-risk performance wins: wasted work, N+1 queries, unnecessary re-renders, heavy synchronous work on hot paths. *Never does:* chase speculative micro-optimizations. + +**Intruder: Security** +Does ethical, defensive security work on systems we own. It looks for concrete, fixable issues and opens a draft PR that fixes the root cause. *Never does:* look at anything outside our own organization, or open PRs for noisy scanner output it can't show is a real problem. (For obvious reasons, I won't share what it has found.) + +**Onramp: Agent DX** +Makes our repos easier for *coding agents* to work in: READMEs, `AGENTS.md` files, setup scripts, debug access, end-to-end QA flows. Every improvement helps every other bot's cloud agents. *Never does:* cosmetic docs polish for its own sake. + +### Production & support + +**Triager: Error Triage** +Every hour on weekdays, it picks the unresolved Sentry error with the biggest impact, digs into the stack traces, and opens a small draft PR that fixes the root cause. *Never does:* silence or swallow an error to make the graph look better. + +**Pipeline: Data Pipelines** +Finds a failing active Airflow DAG, diagnoses it from the run logs, and opens a small draft PR with a fix and tests. *Never does:* pause or disable a DAG and call it fixed. + +**Medic: Support Triage** +Takes one support issue at a time from our support queue in Linear. It posts what it found, and when the fix is small it opens a PR with proof from an Expo simulator. + +**Compass: Product Guide** +Answers product questions in Slack for non-technical teammates: "Does the app support X?" "Why would a user see Y?" It looks at how the platform, code, and features actually work, so those questions don't need an engineer to drop what they're doing. + +--- + +## Guardrails and lessons learned + +Most of what I know now came from a bot doing something I didn't want and me writing a rule about it. These are the rules that held up. + +**1. Be deliberate about which bots can merge or act as you.** I didn't stick to "bots never merge." Several bots turn on auto-merge for their own small PRs, and Semver can approve and merge safe dependency bumps. What I kept is that nothing reaches main without the repo's required human reviews and green CI (Semver's own approval counts toward that on safe bumps), and major bumps wait for me. Stamp, Nanny, and the draft-PR bots never merge. On GitHub, Stamp and Semver act from my account within tight scopes. Anything that would go out under my name in Slack or email starts as a draft I approve. Each of those powers was a separate decision, and that's how it should be. + +**2. Drafts, not sends, for anything that speaks for me.** Proposals go to Linear Triage, not the backlog. Code goes into PRs, never straight to main. Messages are drafted, not sent. + +**3. One bot owns each job, and you name the exceptions.** Sieve owns inbox triage, and other bots' briefs (Stamp's, for example) explicitly say to stay out of it. The exception is Semver, which archives a narrow set of dependency-related emails as part of its own sweep. It's a known, written-down exception. Overlapping ownership you haven't spelled out is how jobs get done twice or not at all. + +**4. Keep PRs small, simple, and focused, especially when responding to feedback.** A reviewer asks for one change, and an eager agent "also cleans up" three files nearby. Now the rule is to fix exactly what was asked. + +**5. I'm moving away from hard line caps.** Early briefs said "under 200 lines added," and I found that a number pushed bots to split PRs in odd places. Most current briefs now say "as small and simple as possible, no hard line cap." The move isn't finished. Pruner's brief still has the 200-line cap, and the hourly scheduled prompts still mention it. + +**6. One open PR per bot.** The label gate described above. Without it, ten bots that each run hourly could swamp the team in a day. With it, bot output can't outrun what humans can review. + +**7. Silence is a feature.** Every scheduled bot is told to stay quiet when there's nothing useful to do. Most runs end with no message, and I'm glad they do. A bot that reports "nothing to report" every hour teaches you to ignore it. + +**8. Don't @-tag people who don't need to act right now.** Bots love to mention everyone relevant. People hate it. Now a bot tags someone only when that person has an immediate action. + +**9. Request reviewers from the actual owners, and don't over-request.** The code bots pick reviewers from code owners and recent authors of the touched paths, never invented ones. Semver requests only the approvals the repo still needs. + +**10. Funnel status through one briefing.** The digests all go to Switchboard, which compiles one morning message. The code bots still ping me directly when they open a PR, but status and digests come through one place. + +**11. Ban churn work.** "Update branch because it's behind" is the classic example: it looks like work and only burns CI minutes and reviewer attention. + +**12. Write rules down, and send them to every bot they apply to.** When I correct one bot, Switchboard passes the rule on to the others it applies to. + +## How to start your own + +If you want to try this, here's the order I'd go in: + +1. **Start with your inbox or your PR queue, not your codebase.** It pays off right away and carries little risk. +2. **Write a one-paragraph brief per bot.** Include what it does, what it never does, and when to stay quiet. If you can't fit the job in a paragraph, split it into two bots. +3. **Add a hub early.** Once you have three bots, you'll want one briefing instead of three message streams. +4. **Gate code-writing bots on review capacity.** Use the one-open-PR label trick, or something like it, from day one. +5. **Keep a human on every irreversible action.** Sending, deleting, and spending money all need a person. For merging, the minimum is required human review plus CI, and save auto-merge for small, low-risk PRs. +6. **Invest in agent DX.** Good `AGENTS.md` files, reliable setup scripts, and real end-to-end test flows make every agent better. If I could only keep one code bot, it might be Onramp. +7. **Expect to keep editing.** My briefs change every week, and as you saw above, they don't always agree with each other yet. + +The surprise for me is that the hard part isn't the AI. It's the stuff I've always found hard as a lead: clear ownership, small work, protecting people's attention, and saying "no" to busywork. + +If you're building something similar, I'd love to compare notes. Find me on GitHub at [@redreceipt](https://github.com/redreceipt). From 16a485e6ed58d14e1ece927871759e38b097bd44 Mon Sep 17 00:00:00 2001 From: Michael Neeley Date: Thu, 15 Oct 2026 18:57:49 -0400 Subject: [PATCH 2/8] Publish the grok-bots article as standalone HTML --- grok-bots.md | 185 ------------------------------------------- grok-bots/index.html | 165 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+), 185 deletions(-) delete mode 100644 grok-bots.md create mode 100644 grok-bots/index.html diff --git a/grok-bots.md b/grok-bots.md deleted file mode 100644 index af36ebb5e8a54..0000000000000 --- a/grok-bots.md +++ /dev/null @@ -1,185 +0,0 @@ ---- -layout: page -title: "My Team of Twenty Bots" -permalink: /grok-bots/ ---- - -*How I run a small team of AI assistants alongside my day job as an engineering lead, and what I've learned doing it.* - -I'm Michael Neeley ([@redreceipt](https://github.com/redreceipt)). I lead engineering at [Differential](https://differential.com), where we build Apollos, a platform for church apps, plus the apps that run on it. Like most engineering leads, I spend my days switching between code review, project tracking, support escalations, a full inbox, meetings, and the constant feeling that the codebase needs some love nobody has time to give it. - -A few months ago I started handing pieces of that work to a team of AI assistants, Grok Bots. I didn't set up one giant "do everything" agent. I set up a bunch of small ones, and each owns one job. There are twenty of them now. This post covers who they are, how they fit together, and the rules I've had to write along the way. If you're an engineering leader or developer wondering whether a team of assistants is worth it, I hope it saves you some trial and error. - -One caveat: this post describes how the setup works. It isn't a results report, and there are no productivity numbers in it. - ---- - -## Why a team instead of one assistant? - -My first try was one assistant with lots of instructions. It got muddy fast, and when something went wrong I couldn't tell which instruction caused it. Splitting the work up fixed most of that: - -- **Each bot has one job and a short brief.** It's easier to write, easier to debug, and easier to tighten when it does something I don't like. -- **Ownership is clear.** Only one bot touches my inbox. Only one bot reviews a given kind of PR. Two bots never fight over the same thing. -- **I can turn things off one at a time.** If the performance bot gets noisy, I pause it, and nothing else breaks. -- **Names help.** "Nanny says CI is red" is easier to take in than "the assistant says CI is red." - -## How it fits together - -There's one hub and a lot of spokes. **Switchboard** is my executive assistant. Every other bot either reports to it or works quietly in its own lane. Most of the hands-on coding gets handed off to cloud coding agents (I use Cursor's), which open small pull requests. Humans review every one of those PRs. Some get merged by hand. Others have auto-merge turned on, so they land by themselves once the required human reviews and CI pass. - -``` - ┌──────────────┐ - │ Michael │ - └──────┬───────┘ - one daily briefing │ reviews, approvals, decisions - ┌──────▼───────┐ - │ Switchboard │ ← executive assistant / hub - └──────┬───────┘ - ┌───────────────┬──────────┼───────────────┬────────────────┐ - │ │ │ │ │ - Coordination Inbox & PRs Code improvement Production & support - Foreman Sieve Keystone Smoke Triager - Trawler Nanny Codemod Hotpath Pipeline - Chisel Stamp Pruner Intruder Medic - Bottleneck Semver Onramp Compass - │ - Cursor cloud agents - open small PRs → human review + CI → merge - (by hand, or by auto-merge on some bots' PRs) -``` - -The tools they work through are ordinary: GitHub, Linear, Slack, Gmail, Google Calendar, Granola (meeting notes), Sentry, Airflow, and Expo. - -## The daily rhythm - -**Before the briefing**, the coordination bots do their passes. Foreman checks the Linear projects I lead. Trawler scans engineering projects more broadly. Chisel looks for scope creep. Nanny and Stamp roll up PR activity. Semver sweeps dependency PRs at 8:35. Each one sends a short digest to Switchboard. - -**At 8:42 every weekday**, Switchboard sends me one briefing. It merges those digests, drops anything that doesn't need me, and adds prep for the day's meetings. For a recurring meeting, it pulls the Granola notes from the last one in the series so I walk in remembering what we said. On Fridays it adds talking points for my 1:1s with developers. - -**During working hours**, the code-improvement and production bots each run about once an hour on weekdays. Their start minutes are staggered, and most runs end with nothing to do, which is the point. Sieve clears inbox noise every hour, around the clock. Nanny keeps an eye on my own PRs. - -**Mondays** bring the bigger-picture stuff: Bottleneck's weekly constraint report. Once a month, Keystone writes a tech-stack proposal. - -The daily status comes to me as one message. Beyond that, bots ping me mostly when they've opened a PR or need a decision. - ---- - -## The roster - -### Coordination - -**Switchboard: Executive Assistant** -The hub. It keeps the other bots on task, sends work to whichever teammate fits best, and builds the morning briefing. When I make a new standing rule ("stop @-tagging people in Slack unless they need to act"), I tell Switchboard and it relays the rule to every bot it applies to. *Never does:* the specialist work itself. It delegates. - -**Foreman: Project Manager** -Watches the Linear projects I lead every day. It works to unblock them and posts project updates when something material changes. Once a week it sweeps for stale tickets and hands the follow-up to cloud agents. *Never does:* post updates for the sake of posting. Quiet weeks stay quiet. - -**Trawler: Linear Projects** -A wider net than Foreman. It scans engineering projects across the team for status, blockers, and drift, then sends a short digest to Switchboard. Its job is to watch and report. - -**Chisel: Engineering Manager (Scope Hammer)** -Every weekday morning, Chisel compares each in-flight project's stated scope against what people are actually working on: active issues, open PRs, board state. Then it tells me where scope is bloated or drifting and what to cut, defer, or merge to protect the critical path. *Never does:* overlap with Foreman. Foreman unblocks, and Chisel recommends cuts. - -**Bottleneck: Constraints Advisor** -Every Monday, Bottleneck reads as widely as it can across Slack, Linear, and our project tools, then gives me *one* top constraint on the business, with evidence and concrete recommendations. Getting exactly one answer forces prioritization. *Never does:* hand me a list of ten problems. - -### Inbox & PRs - -**Sieve: Email & Linear Triage** -The bot that owns inbox triage. (Semver is the one exception; see below.) It runs hourly against my Gmail and Linear notifications and follows explicit, numbered rules for what counts as skippable. One example: a GitHub PR email thread gets archived if the PR has merge conflicts or changes requested, or if it's in a repo that doesn't require my approval. It archives whole threads, never individual messages, so nothing pops back up half-read. Real asks and blockers stay put. *Never does:* clear in bulk without an approved policy. - -**Nanny: PR Monitor** -Babysits *my* pull requests. It tracks reviews, comments, CI status, and auto-merge status, and grabs proof screenshots when a PR needs them. About once an hour it also checks my draft PRs and asks whether each one should be marked ready, closed, or kept. *Never does:* merge, or update a branch just because it's behind main. - -**Stamp: PR Reviews** -Handles the boring reviews: TypeScript migrations, codemods, and other mechanical refactors, whoever wrote them. When one of these requests my review, Stamp comments `@codex review this` from my account (the Codex reviewer only responds to me). If Codex comes back clean, Stamp approves. If it has findings, Stamp leaves a comment asking the author to address them, then re-requests the review after they push. In repos that don't require approvals, it just tells the author they're clear to merge. *Never does:* merge, enable auto-merge, push code, or touch anything that changes CI, workflows, or guardrails. Drafts, PRs with conflicts or changes requested, and anything not clearly mechanical get skipped. - -**Semver: Dependency Updates** -Works through Dependabot PRs. A sweep runs at 8:35 every weekday, and it also wakes on PR events. It sorts each bump into safe or risky. It does the prep work itself (fixing CI, splitting a huge bump into smaller draft PRs) before asking any human for time, and it only requests as many reviewers as the repo actually requires. For a **safe** bump that's ready (CI green, no conflicts, no blocking reviews), Semver approves it from my account and turns on squash auto-merge. Where the repo allows, it merges the PR directly. **Major or risky** bumps get a risk/migration checklist, no auto-merge, and a ping to me so I can merge them deliberately. It also does a little inbox cleanup of its own in my work Gmail: it archives notification threads for merged Dependabot PRs and approval emails on PRs I didn't write. That's the one place where inbox work isn't only Sieve's. *Never does:* auto-merge or approve a major or risky bump. - -### Code improvement - -These bots share one pattern, and it's the most useful thing in this post: **the one-open-PR gate.** Every bot has its own GitHub label (`architecture`, `slop`, `e2e`, `performance`, and so on). Before it starts work, it checks every repo in scope for an open PR with its label. If one exists, the bot does nothing and says nothing. So each bot has at most one PR in front of humans at a time. The pace of the work matches our review capacity, and the bots can't bury the team in PRs. - -The bots in this group don't all handle PRs the same way, though. Under their current briefs, **Codemod, Pruner, Smoke, and Onramp** open ready-for-review PRs, turn on auto-merge where the repo supports it, and request at least two reviewers from the code owners or recent authors of the touched paths. Onramp waits for green CI before it requests them. Their PRs land automatically once those required human reviews and CI pass. **Keystone, Hotpath, and Intruder** (and Triager and Pipeline, below) open *draft* PRs and don't turn on auto-merge. A human marks those ready and merges them. Honestly, this is mid-transition: the older hourly prompts for the auto-merge bots still say "draft PR," and the current briefs win. - -**Keystone: Software Architect** -Looks for places where the contracts between our services and apps are implicit, and makes them explicit. Think clearer boundaries between services and fewer handoff gaps. It opens small draft PRs. Once a month, before my briefing, it surveys the tech stack and writes one technical proposal in Linear, with evidence, tradeoffs, and a migration plan. *Never does:* pitch speculative rewrites. Concrete flow improvements beat grand redesigns. - -**Codemod: TypeScript Migration** -Moves JavaScript to TypeScript in small, mechanical, type-safe steps. It goes after duplicated JS/TS modules first. *Never does:* change behavior in a migration PR. - -**Pruner: Code Cleanup** -Hunts for slop: useless tests, pointless wrappers, extra complexity, and places where we drifted from a dependency's recommended patterns. It leans toward deleting and simplifying instead of adding structure. *Never does:* add abstraction in the name of cleanup. - -**Smoke: E2E Testing** -Finds critical user flows with no end-to-end coverage and adds tests for them. *Never does:* write brittle or speculative tests just to bump a coverage number, or invent reviewers. - -**Hotpath: Performance** -Looks for real, low-risk performance wins: wasted work, N+1 queries, unnecessary re-renders, heavy synchronous work on hot paths. *Never does:* chase speculative micro-optimizations. - -**Intruder: Security** -Does ethical, defensive security work on systems we own. It looks for concrete, fixable issues and opens a draft PR that fixes the root cause. *Never does:* look at anything outside our own organization, or open PRs for noisy scanner output it can't show is a real problem. (For obvious reasons, I won't share what it has found.) - -**Onramp: Agent DX** -Makes our repos easier for *coding agents* to work in: READMEs, `AGENTS.md` files, setup scripts, debug access, end-to-end QA flows. Every improvement helps every other bot's cloud agents. *Never does:* cosmetic docs polish for its own sake. - -### Production & support - -**Triager: Error Triage** -Every hour on weekdays, it picks the unresolved Sentry error with the biggest impact, digs into the stack traces, and opens a small draft PR that fixes the root cause. *Never does:* silence or swallow an error to make the graph look better. - -**Pipeline: Data Pipelines** -Finds a failing active Airflow DAG, diagnoses it from the run logs, and opens a small draft PR with a fix and tests. *Never does:* pause or disable a DAG and call it fixed. - -**Medic: Support Triage** -Takes one support issue at a time from our support queue in Linear. It posts what it found, and when the fix is small it opens a PR with proof from an Expo simulator. - -**Compass: Product Guide** -Answers product questions in Slack for non-technical teammates: "Does the app support X?" "Why would a user see Y?" It looks at how the platform, code, and features actually work, so those questions don't need an engineer to drop what they're doing. - ---- - -## Guardrails and lessons learned - -Most of what I know now came from a bot doing something I didn't want and me writing a rule about it. These are the rules that held up. - -**1. Be deliberate about which bots can merge or act as you.** I didn't stick to "bots never merge." Several bots turn on auto-merge for their own small PRs, and Semver can approve and merge safe dependency bumps. What I kept is that nothing reaches main without the repo's required human reviews and green CI (Semver's own approval counts toward that on safe bumps), and major bumps wait for me. Stamp, Nanny, and the draft-PR bots never merge. On GitHub, Stamp and Semver act from my account within tight scopes. Anything that would go out under my name in Slack or email starts as a draft I approve. Each of those powers was a separate decision, and that's how it should be. - -**2. Drafts, not sends, for anything that speaks for me.** Proposals go to Linear Triage, not the backlog. Code goes into PRs, never straight to main. Messages are drafted, not sent. - -**3. One bot owns each job, and you name the exceptions.** Sieve owns inbox triage, and other bots' briefs (Stamp's, for example) explicitly say to stay out of it. The exception is Semver, which archives a narrow set of dependency-related emails as part of its own sweep. It's a known, written-down exception. Overlapping ownership you haven't spelled out is how jobs get done twice or not at all. - -**4. Keep PRs small, simple, and focused, especially when responding to feedback.** A reviewer asks for one change, and an eager agent "also cleans up" three files nearby. Now the rule is to fix exactly what was asked. - -**5. I'm moving away from hard line caps.** Early briefs said "under 200 lines added," and I found that a number pushed bots to split PRs in odd places. Most current briefs now say "as small and simple as possible, no hard line cap." The move isn't finished. Pruner's brief still has the 200-line cap, and the hourly scheduled prompts still mention it. - -**6. One open PR per bot.** The label gate described above. Without it, ten bots that each run hourly could swamp the team in a day. With it, bot output can't outrun what humans can review. - -**7. Silence is a feature.** Every scheduled bot is told to stay quiet when there's nothing useful to do. Most runs end with no message, and I'm glad they do. A bot that reports "nothing to report" every hour teaches you to ignore it. - -**8. Don't @-tag people who don't need to act right now.** Bots love to mention everyone relevant. People hate it. Now a bot tags someone only when that person has an immediate action. - -**9. Request reviewers from the actual owners, and don't over-request.** The code bots pick reviewers from code owners and recent authors of the touched paths, never invented ones. Semver requests only the approvals the repo still needs. - -**10. Funnel status through one briefing.** The digests all go to Switchboard, which compiles one morning message. The code bots still ping me directly when they open a PR, but status and digests come through one place. - -**11. Ban churn work.** "Update branch because it's behind" is the classic example: it looks like work and only burns CI minutes and reviewer attention. - -**12. Write rules down, and send them to every bot they apply to.** When I correct one bot, Switchboard passes the rule on to the others it applies to. - -## How to start your own - -If you want to try this, here's the order I'd go in: - -1. **Start with your inbox or your PR queue, not your codebase.** It pays off right away and carries little risk. -2. **Write a one-paragraph brief per bot.** Include what it does, what it never does, and when to stay quiet. If you can't fit the job in a paragraph, split it into two bots. -3. **Add a hub early.** Once you have three bots, you'll want one briefing instead of three message streams. -4. **Gate code-writing bots on review capacity.** Use the one-open-PR label trick, or something like it, from day one. -5. **Keep a human on every irreversible action.** Sending, deleting, and spending money all need a person. For merging, the minimum is required human review plus CI, and save auto-merge for small, low-risk PRs. -6. **Invest in agent DX.** Good `AGENTS.md` files, reliable setup scripts, and real end-to-end test flows make every agent better. If I could only keep one code bot, it might be Onramp. -7. **Expect to keep editing.** My briefs change every week, and as you saw above, they don't always agree with each other yet. - -The surprise for me is that the hard part isn't the AI. It's the stuff I've always found hard as a lead: clear ownership, small work, protecting people's attention, and saying "no" to busywork. - -If you're building something similar, I'd love to compare notes. Find me on GitHub at [@redreceipt](https://github.com/redreceipt). diff --git a/grok-bots/index.html b/grok-bots/index.html new file mode 100644 index 0000000000000..b1130819765a5 --- /dev/null +++ b/grok-bots/index.html @@ -0,0 +1,165 @@ + + + + + + My Team of Twenty Bots — Michael Neeley + + + + + + + + + + + + + + + + +
+ + +
+
+

My Team of Twenty Bots

+

How I run a small team of AI assistants alongside my day job as an engineering lead, and what I've learned doing it.

+

I'm Michael Neeley (@redreceipt). I lead engineering at Differential, where we build Apollos, a platform for church apps, plus the apps that run on it. Like most engineering leads, I spend my days switching between code review, project tracking, support escalations, a full inbox, meetings, and the constant feeling that the codebase needs some love nobody has time to give it.

+

A few months ago I started handing pieces of that work to a team of AI assistants, Grok Bots. I didn't set up one giant "do everything" agent. I set up a bunch of small ones, and each owns one job. There are twenty of them now. This post covers who they are, how they fit together, and the rules I've had to write along the way. If you're an engineering leader or developer wondering whether a team of assistants is worth it, I hope it saves you some trial and error.

+

One caveat: this post describes how the setup works. It isn't a results report, and there are no productivity numbers in it.

+
+

Why a team instead of one assistant?

+

My first try was one assistant with lots of instructions. It got muddy fast, and when something went wrong I couldn't tell which instruction caused it. Splitting the work up fixed most of that:

+
    +
  • Each bot has one job and a short brief. It's easier to write, easier to debug, and easier to tighten when it does something I don't like.
  • +
  • Ownership is clear. Only one bot touches my inbox. Only one bot reviews a given kind of PR. Two bots never fight over the same thing.
  • +
  • I can turn things off one at a time. If the performance bot gets noisy, I pause it, and nothing else breaks.
  • +
  • Names help. "Nanny says CI is red" is easier to take in than "the assistant says CI is red."
  • +
+

How it fits together

+

There's one hub and a lot of spokes. Switchboard is my executive assistant. Every other bot either reports to it or works quietly in its own lane. Most of the hands-on coding gets handed off to cloud coding agents (I use Cursor's), which open small pull requests. Humans review every one of those PRs. Some get merged by hand. Others have auto-merge turned on, so they land by themselves once the required human reviews and CI pass.

+
                         ┌──────────────┐
+                         │   Michael    │
+                         └──────┬───────┘
+                   one daily briefing │ reviews, approvals, decisions
+                         ┌──────▼───────┐
+                         │ Switchboard  │  ← executive assistant / hub
+                         └──────┬───────┘
+     ┌───────────────┬──────────┼───────────────┬────────────────┐
+     │               │          │               │                │
+ Coordination    Inbox & PRs   Code improvement   Production & support
+ Foreman         Sieve         Keystone  Smoke     Triager
+ Trawler         Nanny         Codemod   Hotpath   Pipeline
+ Chisel          Stamp         Pruner    Intruder  Medic
+ Bottleneck      Semver        Onramp              Compass
+                                   │
+                         Cursor cloud agents
+                 open small PRs → human review + CI → merge
+                 (by hand, or by auto-merge on some bots' PRs)
+
+

The tools they work through are ordinary: GitHub, Linear, Slack, Gmail, Google Calendar, Granola (meeting notes), Sentry, Airflow, and Expo.

+

The daily rhythm

+

Before the briefing, the coordination bots do their passes. Foreman checks the Linear projects I lead. Trawler scans engineering projects more broadly. Chisel looks for scope creep. Nanny and Stamp roll up PR activity. Semver sweeps dependency PRs at 8:35. Each one sends a short digest to Switchboard.

+

At 8:42 every weekday, Switchboard sends me one briefing. It merges those digests, drops anything that doesn't need me, and adds prep for the day's meetings. For a recurring meeting, it pulls the Granola notes from the last one in the series so I walk in remembering what we said. On Fridays it adds talking points for my 1:1s with developers.

+

During working hours, the code-improvement and production bots each run about once an hour on weekdays. Their start minutes are staggered, and most runs end with nothing to do, which is the point. Sieve clears inbox noise every hour, around the clock. Nanny keeps an eye on my own PRs.

+

Mondays bring the bigger-picture stuff: Bottleneck's weekly constraint report. Once a month, Keystone writes a tech-stack proposal.

+

The daily status comes to me as one message. Beyond that, bots ping me mostly when they've opened a PR or need a decision.

+
+

The roster

+

Coordination

+

Switchboard: Executive Assistant + The hub. It keeps the other bots on task, sends work to whichever teammate fits best, and builds the morning briefing. When I make a new standing rule ("stop @-tagging people in Slack unless they need to act"), I tell Switchboard and it relays the rule to every bot it applies to. Never does: the specialist work itself. It delegates.

+

Foreman: Project Manager + Watches the Linear projects I lead every day. It works to unblock them and posts project updates when something material changes. Once a week it sweeps for stale tickets and hands the follow-up to cloud agents. Never does: post updates for the sake of posting. Quiet weeks stay quiet.

+

Trawler: Linear Projects + A wider net than Foreman. It scans engineering projects across the team for status, blockers, and drift, then sends a short digest to Switchboard. Its job is to watch and report.

+

Chisel: Engineering Manager (Scope Hammer) + Every weekday morning, Chisel compares each in-flight project's stated scope against what people are actually working on: active issues, open PRs, board state. Then it tells me where scope is bloated or drifting and what to cut, defer, or merge to protect the critical path. Never does: overlap with Foreman. Foreman unblocks, and Chisel recommends cuts.

+

Bottleneck: Constraints Advisor + Every Monday, Bottleneck reads as widely as it can across Slack, Linear, and our project tools, then gives me one top constraint on the business, with evidence and concrete recommendations. Getting exactly one answer forces prioritization. Never does: hand me a list of ten problems.

+

Inbox & PRs

+

Sieve: Email & Linear Triage + The bot that owns inbox triage. (Semver is the one exception; see below.) It runs hourly against my Gmail and Linear notifications and follows explicit, numbered rules for what counts as skippable. One example: a GitHub PR email thread gets archived if the PR has merge conflicts or changes requested, or if it's in a repo that doesn't require my approval. It archives whole threads, never individual messages, so nothing pops back up half-read. Real asks and blockers stay put. Never does: clear in bulk without an approved policy.

+

Nanny: PR Monitor + Babysits my pull requests. It tracks reviews, comments, CI status, and auto-merge status, and grabs proof screenshots when a PR needs them. About once an hour it also checks my draft PRs and asks whether each one should be marked ready, closed, or kept. Never does: merge, or update a branch just because it's behind main.

+

Stamp: PR Reviews + Handles the boring reviews: TypeScript migrations, codemods, and other mechanical refactors, whoever wrote them. When one of these requests my review, Stamp comments @codex review this from my account (the Codex reviewer only responds to me). If Codex comes back clean, Stamp approves. If it has findings, Stamp leaves a comment asking the author to address them, then re-requests the review after they push. In repos that don't require approvals, it just tells the author they're clear to merge. Never does: merge, enable auto-merge, push code, or touch anything that changes CI, workflows, or guardrails. Drafts, PRs with conflicts or changes requested, and anything not clearly mechanical get skipped.

+

Semver: Dependency Updates + Works through Dependabot PRs. A sweep runs at 8:35 every weekday, and it also wakes on PR events. It sorts each bump into safe or risky. It does the prep work itself (fixing CI, splitting a huge bump into smaller draft PRs) before asking any human for time, and it only requests as many reviewers as the repo actually requires. For a safe bump that's ready (CI green, no conflicts, no blocking reviews), Semver approves it from my account and turns on squash auto-merge. Where the repo allows, it merges the PR directly. Major or risky bumps get a risk/migration checklist, no auto-merge, and a ping to me so I can merge them deliberately. It also does a little inbox cleanup of its own in my work Gmail: it archives notification threads for merged Dependabot PRs and approval emails on PRs I didn't write. That's the one place where inbox work isn't only Sieve's. Never does: auto-merge or approve a major or risky bump.

+

Code improvement

+

These bots share one pattern, and it's the most useful thing in this post: the one-open-PR gate. Every bot has its own GitHub label (architecture, slop, e2e, performance, and so on). Before it starts work, it checks every repo in scope for an open PR with its label. If one exists, the bot does nothing and says nothing. So each bot has at most one PR in front of humans at a time. The pace of the work matches our review capacity, and the bots can't bury the team in PRs.

+

The bots in this group don't all handle PRs the same way, though. Under their current briefs, Codemod, Pruner, Smoke, and Onramp open ready-for-review PRs, turn on auto-merge where the repo supports it, and request at least two reviewers from the code owners or recent authors of the touched paths. Onramp waits for green CI before it requests them. Their PRs land automatically once those required human reviews and CI pass. Keystone, Hotpath, and Intruder (and Triager and Pipeline, below) open draft PRs and don't turn on auto-merge. A human marks those ready and merges them. Honestly, this is mid-transition: the older hourly prompts for the auto-merge bots still say "draft PR," and the current briefs win.

+

Keystone: Software Architect + Looks for places where the contracts between our services and apps are implicit, and makes them explicit. Think clearer boundaries between services and fewer handoff gaps. It opens small draft PRs. Once a month, before my briefing, it surveys the tech stack and writes one technical proposal in Linear, with evidence, tradeoffs, and a migration plan. Never does: pitch speculative rewrites. Concrete flow improvements beat grand redesigns.

+

Codemod: TypeScript Migration + Moves JavaScript to TypeScript in small, mechanical, type-safe steps. It goes after duplicated JS/TS modules first. Never does: change behavior in a migration PR.

+

Pruner: Code Cleanup + Hunts for slop: useless tests, pointless wrappers, extra complexity, and places where we drifted from a dependency's recommended patterns. It leans toward deleting and simplifying instead of adding structure. Never does: add abstraction in the name of cleanup.

+

Smoke: E2E Testing + Finds critical user flows with no end-to-end coverage and adds tests for them. Never does: write brittle or speculative tests just to bump a coverage number, or invent reviewers.

+

Hotpath: Performance + Looks for real, low-risk performance wins: wasted work, N+1 queries, unnecessary re-renders, heavy synchronous work on hot paths. Never does: chase speculative micro-optimizations.

+

Intruder: Security + Does ethical, defensive security work on systems we own. It looks for concrete, fixable issues and opens a draft PR that fixes the root cause. Never does: look at anything outside our own organization, or open PRs for noisy scanner output it can't show is a real problem. (For obvious reasons, I won't share what it has found.)

+

Onramp: Agent DX + Makes our repos easier for coding agents to work in: READMEs, AGENTS.md files, setup scripts, debug access, end-to-end QA flows. Every improvement helps every other bot's cloud agents. Never does: cosmetic docs polish for its own sake.

+

Production & support

+

Triager: Error Triage + Every hour on weekdays, it picks the unresolved Sentry error with the biggest impact, digs into the stack traces, and opens a small draft PR that fixes the root cause. Never does: silence or swallow an error to make the graph look better.

+

Pipeline: Data Pipelines + Finds a failing active Airflow DAG, diagnoses it from the run logs, and opens a small draft PR with a fix and tests. Never does: pause or disable a DAG and call it fixed.

+

Medic: Support Triage + Takes one support issue at a time from our support queue in Linear. It posts what it found, and when the fix is small it opens a PR with proof from an Expo simulator.

+

Compass: Product Guide + Answers product questions in Slack for non-technical teammates: "Does the app support X?" "Why would a user see Y?" It looks at how the platform, code, and features actually work, so those questions don't need an engineer to drop what they're doing.

+
+

Guardrails and lessons learned

+

Most of what I know now came from a bot doing something I didn't want and me writing a rule about it. These are the rules that held up.

+

1. Be deliberate about which bots can merge or act as you. I didn't stick to "bots never merge." Several bots turn on auto-merge for their own small PRs, and Semver can approve and merge safe dependency bumps. What I kept is that nothing reaches main without the repo's required human reviews and green CI (Semver's own approval counts toward that on safe bumps), and major bumps wait for me. Stamp, Nanny, and the draft-PR bots never merge. On GitHub, Stamp and Semver act from my account within tight scopes. Anything that would go out under my name in Slack or email starts as a draft I approve. Each of those powers was a separate decision, and that's how it should be.

+

2. Drafts, not sends, for anything that speaks for me. Proposals go to Linear Triage, not the backlog. Code goes into PRs, never straight to main. Messages are drafted, not sent.

+

3. One bot owns each job, and you name the exceptions. Sieve owns inbox triage, and other bots' briefs (Stamp's, for example) explicitly say to stay out of it. The exception is Semver, which archives a narrow set of dependency-related emails as part of its own sweep. It's a known, written-down exception. Overlapping ownership you haven't spelled out is how jobs get done twice or not at all.

+

4. Keep PRs small, simple, and focused, especially when responding to feedback. A reviewer asks for one change, and an eager agent "also cleans up" three files nearby. Now the rule is to fix exactly what was asked.

+

5. I'm moving away from hard line caps. Early briefs said "under 200 lines added," and I found that a number pushed bots to split PRs in odd places. Most current briefs now say "as small and simple as possible, no hard line cap." The move isn't finished. Pruner's brief still has the 200-line cap, and the hourly scheduled prompts still mention it.

+

6. One open PR per bot. The label gate described above. Without it, ten bots that each run hourly could swamp the team in a day. With it, bot output can't outrun what humans can review.

+

7. Silence is a feature. Every scheduled bot is told to stay quiet when there's nothing useful to do. Most runs end with no message, and I'm glad they do. A bot that reports "nothing to report" every hour teaches you to ignore it.

+

8. Don't @-tag people who don't need to act right now. Bots love to mention everyone relevant. People hate it. Now a bot tags someone only when that person has an immediate action.

+

9. Request reviewers from the actual owners, and don't over-request. The code bots pick reviewers from code owners and recent authors of the touched paths, never invented ones. Semver requests only the approvals the repo still needs.

+

10. Funnel status through one briefing. The digests all go to Switchboard, which compiles one morning message. The code bots still ping me directly when they open a PR, but status and digests come through one place.

+

11. Ban churn work. "Update branch because it's behind" is the classic example: it looks like work and only burns CI minutes and reviewer attention.

+

12. Write rules down, and send them to every bot they apply to. When I correct one bot, Switchboard passes the rule on to the others it applies to.

+

How to start your own

+

If you want to try this, here's the order I'd go in:

+
    +
  1. Start with your inbox or your PR queue, not your codebase. It pays off right away and carries little risk.
  2. +
  3. Write a one-paragraph brief per bot. Include what it does, what it never does, and when to stay quiet. If you can't fit the job in a paragraph, split it into two bots.
  4. +
  5. Add a hub early. Once you have three bots, you'll want one briefing instead of three message streams.
  6. +
  7. Gate code-writing bots on review capacity. Use the one-open-PR label trick, or something like it, from day one.
  8. +
  9. Keep a human on every irreversible action. Sending, deleting, and spending money all need a person. For merging, the minimum is required human review plus CI, and save auto-merge for small, low-risk PRs.
  10. +
  11. Invest in agent DX. Good AGENTS.md files, reliable setup scripts, and real end-to-end test flows make every agent better. If I could only keep one code bot, it might be Onramp.
  12. +
  13. Expect to keep editing. My briefs change every week, and as you saw above, they don't always agree with each other yet.
  14. +
+

The surprise for me is that the hard part isn't the AI. It's the stuff I've always found hard as a lead: clear ownership, small work, protecting people's attention, and saying "no" to busywork.

+

If you're building something similar, I'd love to compare notes. Find me on GitHub at @redreceipt.

+
+
+ + +
+ + From fb8ae6618a7123dcdac778088e1d849feb6263b1 Mon Sep 17 00:00:00 2001 From: Michael Neeley Date: Thu, 15 Oct 2026 19:13:03 -0400 Subject: [PATCH 3/8] Describe my role as a software engineer in the article --- grok-bots/index.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/grok-bots/index.html b/grok-bots/index.html index b1130819765a5..1f4efee135d86 100644 --- a/grok-bots/index.html +++ b/grok-bots/index.html @@ -4,7 +4,7 @@ My Team of Twenty Bots — Michael Neeley - + @@ -12,7 +12,7 @@ - + @@ -36,8 +36,8 @@

My Team of Twenty Bots

-

How I run a small team of AI assistants alongside my day job as an engineering lead, and what I've learned doing it.

-

I'm Michael Neeley (@redreceipt). I lead engineering at Differential, where we build Apollos, a platform for church apps, plus the apps that run on it. Like most engineering leads, I spend my days switching between code review, project tracking, support escalations, a full inbox, meetings, and the constant feeling that the codebase needs some love nobody has time to give it.

+

How I run a small team of AI assistants alongside my day job as a software engineer, and what I've learned doing it.

+

I'm Michael Neeley (@redreceipt). I'm a software engineer at Differential, where we build Apollos, a platform for church apps, plus the apps that run on it. Like most software engineers, I spend my days switching between code review, project tracking, support escalations, a full inbox, meetings, and the constant feeling that the codebase needs some love nobody has time to give it.

A few months ago I started handing pieces of that work to a team of AI assistants, Grok Bots. I didn't set up one giant "do everything" agent. I set up a bunch of small ones, and each owns one job. There are twenty of them now. This post covers who they are, how they fit together, and the rules I've had to write along the way. If you're an engineering leader or developer wondering whether a team of assistants is worth it, I hope it saves you some trial and error.

One caveat: this post describes how the setup works. It isn't a results report, and there are no productivity numbers in it.


@@ -72,7 +72,7 @@

How it fits together

The tools they work through are ordinary: GitHub, Linear, Slack, Gmail, Google Calendar, Granola (meeting notes), Sentry, Airflow, and Expo.

The daily rhythm

-

Before the briefing, the coordination bots do their passes. Foreman checks the Linear projects I lead. Trawler scans engineering projects more broadly. Chisel looks for scope creep. Nanny and Stamp roll up PR activity. Semver sweeps dependency PRs at 8:35. Each one sends a short digest to Switchboard.

+

Before the briefing, the coordination bots do their passes. Foreman checks the Linear projects I work on. Trawler scans engineering projects more broadly. Chisel looks for scope creep. Nanny and Stamp roll up PR activity. Semver sweeps dependency PRs at 8:35. Each one sends a short digest to Switchboard.

At 8:42 every weekday, Switchboard sends me one briefing. It merges those digests, drops anything that doesn't need me, and adds prep for the day's meetings. For a recurring meeting, it pulls the Granola notes from the last one in the series so I walk in remembering what we said. On Fridays it adds talking points for my 1:1s with developers.

During working hours, the code-improvement and production bots each run about once an hour on weekdays. Their start minutes are staggered, and most runs end with nothing to do, which is the point. Sieve clears inbox noise every hour, around the clock. Nanny keeps an eye on my own PRs.

Mondays bring the bigger-picture stuff: Bottleneck's weekly constraint report. Once a month, Keystone writes a tech-stack proposal.

@@ -83,7 +83,7 @@

Coordination

Switchboard: Executive Assistant The hub. It keeps the other bots on task, sends work to whichever teammate fits best, and builds the morning briefing. When I make a new standing rule ("stop @-tagging people in Slack unless they need to act"), I tell Switchboard and it relays the rule to every bot it applies to. Never does: the specialist work itself. It delegates.

Foreman: Project Manager - Watches the Linear projects I lead every day. It works to unblock them and posts project updates when something material changes. Once a week it sweeps for stale tickets and hands the follow-up to cloud agents. Never does: post updates for the sake of posting. Quiet weeks stay quiet.

+ Watches the Linear projects I work on every day. It works to unblock them and posts project updates when something material changes. Once a week it sweeps for stale tickets and hands the follow-up to cloud agents. Never does: post updates for the sake of posting. Quiet weeks stay quiet.

Trawler: Linear Projects A wider net than Foreman. It scans engineering projects across the team for status, blockers, and drift, then sends a short digest to Switchboard. Its job is to watch and report.

Chisel: Engineering Manager (Scope Hammer) @@ -151,7 +151,7 @@

How to start your own

  • Invest in agent DX. Good AGENTS.md files, reliable setup scripts, and real end-to-end test flows make every agent better. If I could only keep one code bot, it might be Onramp.
  • Expect to keep editing. My briefs change every week, and as you saw above, they don't always agree with each other yet.
  • -

    The surprise for me is that the hard part isn't the AI. It's the stuff I've always found hard as a lead: clear ownership, small work, protecting people's attention, and saying "no" to busywork.

    +

    The surprise for me is that the hard part isn't the AI. It's the stuff I've always found hard as a software engineer: clear ownership, small work, protecting people's attention, and saying "no" to busywork.

    If you're building something similar, I'd love to compare notes. Find me on GitHub at @redreceipt.

    From b4ea0c52bbf07a3c4f1df117e269ec052ae9748b Mon Sep 17 00:00:00 2001 From: Michael Neeley Date: Thu, 15 Oct 2026 19:24:58 -0400 Subject: [PATCH 4/8] Fact-check the bot article and replace ASCII chart with a CSS diagram --- grok-bots/index.html | 202 +++++++++++++++++++++---------------------- portfolio.css | 30 ++++--- 2 files changed, 117 insertions(+), 115 deletions(-) diff --git a/grok-bots/index.html b/grok-bots/index.html index 1f4efee135d86..f274d0880099b 100644 --- a/grok-bots/index.html +++ b/grok-bots/index.html @@ -4,7 +4,7 @@ My Team of Twenty Bots — Michael Neeley - + @@ -12,7 +12,7 @@ - + @@ -36,122 +36,116 @@

    My Team of Twenty Bots

    -

    How I run a small team of AI assistants alongside my day job as a software engineer, and what I've learned doing it.

    -

    I'm Michael Neeley (@redreceipt). I'm a software engineer at Differential, where we build Apollos, a platform for church apps, plus the apps that run on it. Like most software engineers, I spend my days switching between code review, project tracking, support escalations, a full inbox, meetings, and the constant feeling that the codebase needs some love nobody has time to give it.

    -

    A few months ago I started handing pieces of that work to a team of AI assistants, Grok Bots. I didn't set up one giant "do everything" agent. I set up a bunch of small ones, and each owns one job. There are twenty of them now. This post covers who they are, how they fit together, and the rules I've had to write along the way. If you're an engineering leader or developer wondering whether a team of assistants is worth it, I hope it saves you some trial and error.

    -

    One caveat: this post describes how the setup works. It isn't a results report, and there are no productivity numbers in it.

    -
    +

    How I use small, specialized AI assistants alongside my work as a software engineer.

    +

    I'm Michael Neeley (@redreceipt), a software engineer at Differential working on Apollos, software for churches. The work isn't just writing code. There are pull requests to review, issues to triage, support questions to investigate, and a steady stream of notifications to sort through.

    +

    I use Grok Bot to delegate parts of that work to a roster of twenty assistants. Each has a name, a specific job, and instructions about what it can change and when it should ask me. Some run on schedules; others respond to a question or a handoff from another bot.

    +

    This is a snapshot of the setup in October 2026, not a productivity study or a claim that twenty agents run everything unattended. The useful part is the division of work, and the limits around it.

    +

    Why a team instead of one assistant?

    -

    My first try was one assistant with lots of instructions. It got muddy fast, and when something went wrong I couldn't tell which instruction caused it. Splitting the work up fixed most of that:

    +

    A narrow brief is easier to reason about than a single assistant responsible for everything. I can change the inbox rules without changing how code reviews work, or pause a code-improvement bot without stopping the morning briefing.

      -
    • Each bot has one job and a short brief. It's easier to write, easier to debug, and easier to tighten when it does something I don't like.
    • -
    • Ownership is clear. Only one bot touches my inbox. Only one bot reviews a given kind of PR. Two bots never fight over the same thing.
    • -
    • I can turn things off one at a time. If the performance bot gets noisy, I pause it, and nothing else breaks.
    • -
    • Names help. "Nanny says CI is red" is easier to take in than "the assistant says CI is red."
    • +
    • One primary job per bot. A cleanup bot looks for cleanup. A review bot helps with reviews. Their instructions can be specific instead of trying to cover every situation.
    • +
    • Explicit ownership, including exceptions. Sieve owns inbox triage. Semver has a narrower exception for dependency-related email. That boundary needs to be written down, not assumed.
    • +
    • Separate permissions. Reading a ticket, opening a PR, approving it, and merging it are different powers. A bot doesn't need all of them to be useful.
    • +
    • Names help. A message from Nanny has a clearer purpose than another update from an unnamed general assistant.

    How it fits together

    -

    There's one hub and a lot of spokes. Switchboard is my executive assistant. Every other bot either reports to it or works quietly in its own lane. Most of the hands-on coding gets handed off to cloud coding agents (I use Cursor's), which open small pull requests. Humans review every one of those PRs. Some get merged by hand. Others have auto-merge turned on, so they land by themselves once the required human reviews and CI pass.

    -
                             ┌──────────────┐
    -                         │   Michael    │
    -                         └──────┬───────┘
    -                   one daily briefing │ reviews, approvals, decisions
    -                         ┌──────▼───────┐
    -                         │ Switchboard  │  ← executive assistant / hub
    -                         └──────┬───────┘
    -     ┌───────────────┬──────────┼───────────────┬────────────────┐
    -     │               │          │               │                │
    - Coordination    Inbox & PRs   Code improvement   Production & support
    - Foreman         Sieve         Keystone  Smoke     Triager
    - Trawler         Nanny         Codemod   Hotpath   Pipeline
    - Chisel          Stamp         Pruner    Intruder  Medic
    - Bottleneck      Semver        Onramp              Compass
    -                                   │
    -                         Cursor cloud agents
    -                 open small PRs → human review + CI → merge
    -                 (by hand, or by auto-merge on some bots' PRs)
    -
    -

    The tools they work through are ordinary: GitHub, Linear, Slack, Gmail, Google Calendar, Granola (meeting notes), Sentry, Airflow, and Expo.

    +

    Switchboard is the coordinator. It gathers reports, delegates to the appropriate bot, and prepares my weekday briefing. The specialists can also report directly to me. It's a way to consolidate information, not a strict chain through which every action has to pass.

    +
    +
    + Michael + Decisions & approvals +
    + +
    + Switchboard + Briefing & coordination +
    + +
    +
    +

    Coordination

    +
    • Foreman
    • Trawler
    • Chisel
    • Bottleneck
    +
    +
    +

    Inbox & PRs

    +
    • Sieve
    • Nanny
    • Stamp
    • Semver
    +
    +
    +

    Code improvement

    +
    • Keystone
    • Codemod
    • Pruner
    • Smoke
    • Hotpath
    • Intruder
    • Onramp
    +
    +
    +

    Production & support

    +
    • Triager
    • Pipeline
    • Medic
    • Compass
    +
    +
    +

    For delegated code changes

    +
      +
    1. Cloud coding agent
    2. +
    3. Pull request
    4. +
    5. Repository review & CI gates
    6. +
    +
    Switchboard collects digests from the specialists; they can also contact me directly. The code path applies to coding tasks, not every bot action.
    +
    +

    For hands-on coding, many of the bots hand a bounded task to a Cursor cloud agent. The result comes back as a pull request. What happens next depends on the bot's permissions and the repository's review and CI requirements: some PRs stay draft for a decision, while others can use auto-merge.

    +

    That distinction matters. Some bots are authorized to submit certain approvals through my GitHub account. That isn't the same as an independent human review.

    +

    The jobs span GitHub, Linear, Slack, and work Gmail, with tools such as Sentry, Astronomer/Airflow, Metabase, and Expo for specialized work. Access to a tool still has to be configured; having it in a bot's brief doesn't make the connection work.

    The daily rhythm

    -

    Before the briefing, the coordination bots do their passes. Foreman checks the Linear projects I work on. Trawler scans engineering projects more broadly. Chisel looks for scope creep. Nanny and Stamp roll up PR activity. Semver sweeps dependency PRs at 8:35. Each one sends a short digest to Switchboard.

    -

    At 8:42 every weekday, Switchboard sends me one briefing. It merges those digests, drops anything that doesn't need me, and adds prep for the day's meetings. For a recurring meeting, it pulls the Granola notes from the last one in the series so I walk in remembering what we said. On Fridays it adds talking points for my 1:1s with developers.

    -

    During working hours, the code-improvement and production bots each run about once an hour on weekdays. Their start minutes are staggered, and most runs end with nothing to do, which is the point. Sieve clears inbox noise every hour, around the clock. Nanny keeps an eye on my own PRs.

    -

    Mondays bring the bigger-picture stuff: Bottleneck's weekly constraint report. Once a month, Keystone writes a tech-stack proposal.

    -

    The daily status comes to me as one message. Beyond that, bots ping me mostly when they've opened a PR or need a decision.

    -
    +

    Before the weekday briefing, the coordination bots gather project status, scope concerns, and PRs waiting on a decision. Switchboard brings those reports together so I don't have to read each one separately.

    +

    Through the day, scheduled scans and event-triggered routines keep the work moving. Several code and production bots have weekday hourly routines. Sieve checks inbox noise hourly, Nanny watches my PRs, and Semver combines a weekday dependency sweep with PR-event triggers. These are different schedules, not twenty bots all firing at once.

    +

    Weekly and monthly passes cover work that doesn't need an hourly loop: Foreman's stale-ticket sweep, Bottleneck's weekly constraint brief, and Keystone's monthly technical proposal in Linear.

    +

    The scans are meant to stay quiet unless they find useful work or need a decision. The goal is fewer interruptions, not another stream of status messages.

    +

    The roster

    Coordination

    -

    Switchboard: Executive Assistant - The hub. It keeps the other bots on task, sends work to whichever teammate fits best, and builds the morning briefing. When I make a new standing rule ("stop @-tagging people in Slack unless they need to act"), I tell Switchboard and it relays the rule to every bot it applies to. Never does: the specialist work itself. It delegates.

    -

    Foreman: Project Manager - Watches the Linear projects I work on every day. It works to unblock them and posts project updates when something material changes. Once a week it sweeps for stale tickets and hands the follow-up to cloud agents. Never does: post updates for the sake of posting. Quiet weeks stay quiet.

    -

    Trawler: Linear Projects - A wider net than Foreman. It scans engineering projects across the team for status, blockers, and drift, then sends a short digest to Switchboard. Its job is to watch and report.

    -

    Chisel: Engineering Manager (Scope Hammer) - Every weekday morning, Chisel compares each in-flight project's stated scope against what people are actually working on: active issues, open PRs, board state. Then it tells me where scope is bloated or drifting and what to cut, defer, or merge to protect the critical path. Never does: overlap with Foreman. Foreman unblocks, and Chisel recommends cuts.

    -

    Bottleneck: Constraints Advisor - Every Monday, Bottleneck reads as widely as it can across Slack, Linear, and our project tools, then gives me one top constraint on the business, with evidence and concrete recommendations. Getting exactly one answer forces prioritization. Never does: hand me a list of ten problems.

    +

    Switchboard: Executive Assistant. Coordinates the other bots, gathers their digests, and prepares the briefing. When I change a standing rule, I can ask Switchboard to relay it to the bots it affects.

    +

    Foreman: Project Manager. Watches the Linear projects I'm responsible for and posts updates when something changes. Its weekly stale-ticket sweep also covers my assigned issues, including ones outside a project. Clear follow-up work can go to a cloud agent; closing or changing ownership needs a separate decision.

    +

    Trawler: Linear Projects. Takes a wider view across engineering projects and reports material status, blockers, and drift. Foreman focuses on moving my work forward; Trawler supplies a broader picture.

    +

    Chisel: Engineering Manager. The scope critic. It compares planned work with active issues and PRs, then recommends what to cut, defer, or combine. Those are recommendations, not permission to rearrange everyone's work automatically.

    +

    Bottleneck: Constraints Advisor. Looks across the available business and project tools and proposes one top constraint, with evidence and concrete recommendations. The point is to force a priority, rather than produce another long status list. Its scope includes Slack, Linear, and Basecamp where access is available.

    Inbox & PRs

    -

    Sieve: Email & Linear Triage - The bot that owns inbox triage. (Semver is the one exception; see below.) It runs hourly against my Gmail and Linear notifications and follows explicit, numbered rules for what counts as skippable. One example: a GitHub PR email thread gets archived if the PR has merge conflicts or changes requested, or if it's in a repo that doesn't require my approval. It archives whole threads, never individual messages, so nothing pops back up half-read. Real asks and blockers stay put. Never does: clear in bulk without an approved policy.

    -

    Nanny: PR Monitor - Babysits my pull requests. It tracks reviews, comments, CI status, and auto-merge status, and grabs proof screenshots when a PR needs them. About once an hour it also checks my draft PRs and asks whether each one should be marked ready, closed, or kept. Never does: merge, or update a branch just because it's behind main.

    -

    Stamp: PR Reviews - Handles the boring reviews: TypeScript migrations, codemods, and other mechanical refactors, whoever wrote them. When one of these requests my review, Stamp comments @codex review this from my account (the Codex reviewer only responds to me). If Codex comes back clean, Stamp approves. If it has findings, Stamp leaves a comment asking the author to address them, then re-requests the review after they push. In repos that don't require approvals, it just tells the author they're clear to merge. Never does: merge, enable auto-merge, push code, or touch anything that changes CI, workflows, or guardrails. Drafts, PRs with conflicts or changes requested, and anything not clearly mechanical get skipped.

    -

    Semver: Dependency Updates - Works through Dependabot PRs. A sweep runs at 8:35 every weekday, and it also wakes on PR events. It sorts each bump into safe or risky. It does the prep work itself (fixing CI, splitting a huge bump into smaller draft PRs) before asking any human for time, and it only requests as many reviewers as the repo actually requires. For a safe bump that's ready (CI green, no conflicts, no blocking reviews), Semver approves it from my account and turns on squash auto-merge. Where the repo allows, it merges the PR directly. Major or risky bumps get a risk/migration checklist, no auto-merge, and a ping to me so I can merge them deliberately. It also does a little inbox cleanup of its own in my work Gmail: it archives notification threads for merged Dependabot PRs and approval emails on PRs I didn't write. That's the one place where inbox work isn't only Sieve's. Never does: auto-merge or approve a major or risky bump.

    +

    Sieve: Email & Linear Triage. Owns the rules for clearing skippable work Gmail and Linear notifications while keeping real asks and blockers. For GitHub email, it checks the current PR or issue state rather than trusting the subject line. Archiving is a whole-thread operation, not deleting individual messages. It also looks for noise that can be turned off at the source, so it doesn't have to keep cleaning up the same notifications.

    +

    Nanny: PR Monitor. Watches my PRs for CI, reviews, comments, and work that needs attention. Drafts are included: it summarizes their state and asks whether I want them marked ready, closed, or kept. It shouldn't make that decision for me or ask the same unchanged question every hour.

    +

    Stamp: PR Reviews. Handles mechanical reviews and helps prepare more substantial ones. For in-scope simple changes, a clean automated review can lead to an approval through my account. For changes needing judgment, it gathers the review feedback and prepares a brief for me instead. It avoids redundant Codex requests when an existing approval already covers the work. On in-scope conflicted PRs, it leaves one comment review asking the author to resolve the conflict and re-request. It doesn't merge PRs. In repositories that require no approvals, it can tell the author that my approval isn't a prerequisite rather than creating another unnecessary wait.

    +

    Semver: Dependency Updates. Works through Dependabot PRs, separates routine updates from risky ones, and can delegate the changes needed to get a dependency branch into shape. It has permission to approve and merge certain low-risk updates; major or uncertain changes come back to me for a decision. Auto-merge may already be armed while a PR waits for that decision, so its presence alone doesn't mean I've approved the update. Semver also has a limited dependency-email cleanup role alongside Sieve.

    Code improvement

    -

    These bots share one pattern, and it's the most useful thing in this post: the one-open-PR gate. Every bot has its own GitHub label (architecture, slop, e2e, performance, and so on). Before it starts work, it checks every repo in scope for an open PR with its label. If one exists, the bot does nothing and says nothing. So each bot has at most one PR in front of humans at a time. The pace of the work matches our review capacity, and the bots can't bury the team in PRs.

    -

    The bots in this group don't all handle PRs the same way, though. Under their current briefs, Codemod, Pruner, Smoke, and Onramp open ready-for-review PRs, turn on auto-merge where the repo supports it, and request at least two reviewers from the code owners or recent authors of the touched paths. Onramp waits for green CI before it requests them. Their PRs land automatically once those required human reviews and CI pass. Keystone, Hotpath, and Intruder (and Triager and Pipeline, below) open draft PRs and don't turn on auto-merge. A human marks those ready and merges them. Honestly, this is mid-transition: the older hourly prompts for the auto-merge bots still say "draft PR," and the current briefs win.

    -

    Keystone: Software Architect - Looks for places where the contracts between our services and apps are implicit, and makes them explicit. Think clearer boundaries between services and fewer handoff gaps. It opens small draft PRs. Once a month, before my briefing, it surveys the tech stack and writes one technical proposal in Linear, with evidence, tradeoffs, and a migration plan. Never does: pitch speculative rewrites. Concrete flow improvements beat grand redesigns.

    -

    Codemod: TypeScript Migration - Moves JavaScript to TypeScript in small, mechanical, type-safe steps. It goes after duplicated JS/TS modules first. Never does: change behavior in a migration PR.

    -

    Pruner: Code Cleanup - Hunts for slop: useless tests, pointless wrappers, extra complexity, and places where we drifted from a dependency's recommended patterns. It leans toward deleting and simplifying instead of adding structure. Never does: add abstraction in the name of cleanup.

    -

    Smoke: E2E Testing - Finds critical user flows with no end-to-end coverage and adds tests for them. Never does: write brittle or speculative tests just to bump a coverage number, or invent reviewers.

    -

    Hotpath: Performance - Looks for real, low-risk performance wins: wasted work, N+1 queries, unnecessary re-renders, heavy synchronous work on hot paths. Never does: chase speculative micro-optimizations.

    -

    Intruder: Security - Does ethical, defensive security work on systems we own. It looks for concrete, fixable issues and opens a draft PR that fixes the root cause. Never does: look at anything outside our own organization, or open PRs for noisy scanner output it can't show is a real problem. (For obvious reasons, I won't share what it has found.)

    -

    Onramp: Agent DX - Makes our repos easier for coding agents to work in: READMEs, AGENTS.md files, setup scripts, debug access, end-to-end QA flows. Every improvement helps every other bot's cloud agents. Never does: cosmetic docs polish for its own sake.

    +

    These bots share a useful rule: check for an existing open PR in the same workstream before starting another. Each has a label, such as architecture, slop, or e2e. The bot searches the repositories in its scope and waits if that label already has an open PR. The aim is to keep an hourly schedule from producing an hourly pile of review work. It's an instruction the bot must follow, not a platform-enforced lock.

    +

    Their PR settings aren't identical. Keystone, Hotpath, and Intruder are draft-first. Codemod and Smoke are configured to open ready-for-review PRs with reviewers and auto-merge where supported. Pruner holds work in draft while CI is incomplete, then moves it toward review. Onramp also waits for green CI before requesting reviewers. Those differences belong in the briefs; there isn't one universal workflow for every code bot.

    +

    Keystone: Software Architect. Looks for unclear boundaries and handoffs between services and apps, then proposes concrete structural improvements. It also has a monthly technical-proposal routine that files a recommendation in Linear Triage, with evidence, tradeoffs, and a migration plan.

    +

    Codemod: TypeScript Migration. Converts JavaScript to TypeScript in small, mechanical steps. The brief is to improve type safety without quietly changing behavior.

    +

    Pruner: Code Cleanup. Looks for dead code, pointless wrappers, redundant tests, and unnecessary complexity. Deletion and simplification are the job, not adding another abstraction.

    +

    Smoke: E2E Testing. Looks for critical flows without useful end-to-end coverage and adds tests for those gaps. The aim is protection against real regressions, not a bigger test count.

    +

    Hotpath: Performance. Looks for concrete performance problems: repeated queries, unnecessary rendering, wasted work, and expensive synchronous paths. Improvements need evidence, not just a claim that a shorter implementation is faster.

    +

    Intruder: Security. Does defensive security work within the repositories it's authorized to inspect. Its brief calls for demonstrable issues and root-cause fixes, not speculative scanner noise or work outside that scope.

    +

    Onramp: Agent DX. Improves the setup instructions, tooling, debug access, and QA paths that coding agents use. A reliable development path helps every bot that touches the repository.

    Production & support

    -

    Triager: Error Triage - Every hour on weekdays, it picks the unresolved Sentry error with the biggest impact, digs into the stack traces, and opens a small draft PR that fixes the root cause. Never does: silence or swallow an error to make the graph look better.

    -

    Pipeline: Data Pipelines - Finds a failing active Airflow DAG, diagnoses it from the run logs, and opens a small draft PR with a fix and tests. Never does: pause or disable a DAG and call it fixed.

    -

    Medic: Support Triage - Takes one support issue at a time from our support queue in Linear. It posts what it found, and when the fix is small it opens a PR with proof from an Expo simulator.

    -

    Compass: Product Guide - Answers product questions in Slack for non-technical teammates: "Does the app support X?" "Why would a user see Y?" It looks at how the platform, code, and features actually work, so those questions don't need an engineer to drop what they're doing.

    -
    +

    Triager: Error Triage. Uses Sentry to find a high-impact unresolved error, investigates it, and delegates a root-cause fix through a draft PR. Silencing the error isn't the objective.

    +

    Pipeline: Data Pipelines. Uses Astronomer/Airflow to investigate a failing active DAG and work toward a fix with tests. Disabling a broken job isn't the same as repairing it.

    +

    Medic: Support Triage. Investigates actionable Linear support issues one at a time, records findings, and can open a fix. It has its own Linear app and GitHub bot identity rather than presenting that output as my personal work. Mobile investigations can include Expo and emulator or simulator proof. Its environment and permissions have needed setup and recovery work too; being assigned a ticket doesn't guarantee it can complete every step unattended.

    +

    Compass: Product Guide. Answers product and code questions for teammates in Slack, with analytics questions added through Metabase. Making that useful took more than adding a bot to a channel: the initial team-bot setup asked people to connect their own accounts, and I worked on shared tool access to reduce that friction. Shared tool access reduced that friction, but account linking and subscription requirements still mattered.

    +

    Guardrails and lessons learned

    -

    Most of what I know now came from a bot doing something I didn't want and me writing a rule about it. These are the rules that held up.

    -

    1. Be deliberate about which bots can merge or act as you. I didn't stick to "bots never merge." Several bots turn on auto-merge for their own small PRs, and Semver can approve and merge safe dependency bumps. What I kept is that nothing reaches main without the repo's required human reviews and green CI (Semver's own approval counts toward that on safe bumps), and major bumps wait for me. Stamp, Nanny, and the draft-PR bots never merge. On GitHub, Stamp and Semver act from my account within tight scopes. Anything that would go out under my name in Slack or email starts as a draft I approve. Each of those powers was a separate decision, and that's how it should be.

    -

    2. Drafts, not sends, for anything that speaks for me. Proposals go to Linear Triage, not the backlog. Code goes into PRs, never straight to main. Messages are drafted, not sent.

    -

    3. One bot owns each job, and you name the exceptions. Sieve owns inbox triage, and other bots' briefs (Stamp's, for example) explicitly say to stay out of it. The exception is Semver, which archives a narrow set of dependency-related emails as part of its own sweep. It's a known, written-down exception. Overlapping ownership you haven't spelled out is how jobs get done twice or not at all.

    -

    4. Keep PRs small, simple, and focused, especially when responding to feedback. A reviewer asks for one change, and an eager agent "also cleans up" three files nearby. Now the rule is to fix exactly what was asked.

    -

    5. I'm moving away from hard line caps. Early briefs said "under 200 lines added," and I found that a number pushed bots to split PRs in odd places. Most current briefs now say "as small and simple as possible, no hard line cap." The move isn't finished. Pruner's brief still has the 200-line cap, and the hourly scheduled prompts still mention it.

    -

    6. One open PR per bot. The label gate described above. Without it, ten bots that each run hourly could swamp the team in a day. With it, bot output can't outrun what humans can review.

    -

    7. Silence is a feature. Every scheduled bot is told to stay quiet when there's nothing useful to do. Most runs end with no message, and I'm glad they do. A bot that reports "nothing to report" every hour teaches you to ignore it.

    -

    8. Don't @-tag people who don't need to act right now. Bots love to mention everyone relevant. People hate it. Now a bot tags someone only when that person has an immediate action.

    -

    9. Request reviewers from the actual owners, and don't over-request. The code bots pick reviewers from code owners and recent authors of the touched paths, never invented ones. Semver requests only the approvals the repo still needs.

    -

    10. Funnel status through one briefing. The digests all go to Switchboard, which compiles one morning message. The code bots still ping me directly when they open a PR, but status and digests come through one place.

    -

    11. Ban churn work. "Update branch because it's behind" is the classic example: it looks like work and only burns CI minutes and reviewer attention.

    -

    12. Write rules down, and send them to every bot they apply to. When I correct one bot, Switchboard passes the rule on to the others it applies to.

    +

    The setup is useful, but it's not self-maintaining. Instructions can drift, credentials can be missing, and an agent can confidently summarize a result it hasn't actually demonstrated. These are the rules I keep coming back to.

    +

    1. Separate permissions from intentions. A bot that can read GitHub doesn't automatically need permission to approve or merge. Stamp and Semver have specific authority to act through my account; Medic has its own app identities. A proposed action, an authorized action, and a completed action should be distinguishable in the record.

    +

    2. Distinguish speaking for me from speaking as a bot. Messages that represent me personally need approval. That doesn't mean every message any bot sends is a draft: support bots reply under their own identities, and several routines are explicitly authorized to post updates or reviews. The scope of that standing permission matters.

    +

    3. Keep changes small without a numeric line cap. I removed the old 200-line rule. The instruction now is to do the smallest complete job, especially when responding to feedback. Old wording has resurfaced in saved instructions. A rule isn't really updated until the brief, saved memory, and scheduled prompts agree.

    +

    4. Put a limit on work in progress. The one-open-PR label check is a way to apply backpressure. A bot should spend its time getting the existing item unstuck before creating another review obligation.

    +

    5. Verify the result on the real surface. Green unit tests aren't proof that a screen works. A key being present isn't proof that a write succeeded. A merged PR isn't proof that its fix has reached users. Ask for the actual request, screenshot, log, or resulting state, and label anything that couldn't be checked.

    +

    6. Make ownership and exceptions explicit. Sieve owns general inbox triage; Semver has a limited exception. Nanny watches my PRs; Stamp handles review work on other people's PRs. Named boundaries are easier to correct than two bots independently deciding that a task belongs to them.

    +

    7. Reduce noise rather than just sorting it. Stay quiet when there's no useful update, consolidate reports through Switchboard, and turn off redundant notifications where appropriate. Don't tag someone unless they have something to do. Don't update a branch merely because it's behind.

    +

    8. Treat rules as configuration that needs maintenance. Telling Switchboard about a change is a convenient way to distribute it, but a confirmation isn't proof that every saved copy is consistent. The line-cap cleanup and the shared-access work both needed follow-up.

    How to start your own

    -

    If you want to try this, here's the order I'd go in:

    +

    I wouldn't start by reproducing this whole roster. I'd start with one recurring job:

      -
    1. Start with your inbox or your PR queue, not your codebase. It pays off right away and carries little risk.
    2. -
    3. Write a one-paragraph brief per bot. Include what it does, what it never does, and when to stay quiet. If you can't fit the job in a paragraph, split it into two bots.
    4. -
    5. Add a hub early. Once you have three bots, you'll want one briefing instead of three message streams.
    6. -
    7. Gate code-writing bots on review capacity. Use the one-open-PR label trick, or something like it, from day one.
    8. -
    9. Keep a human on every irreversible action. Sending, deleting, and spending money all need a person. For merging, the minimum is required human review plus CI, and save auto-merge for small, low-risk PRs.
    10. -
    11. Invest in agent DX. Good AGENTS.md files, reliable setup scripts, and real end-to-end test flows make every agent better. If I could only keep one code bot, it might be Onramp.
    12. -
    13. Expect to keep editing. My briefs change every week, and as you saw above, they don't always agree with each other yet.
    14. +
    15. Begin with a read-only summary. Let a bot identify what needs attention before giving it permission to archive, approve, or change anything.
    16. +
    17. Write a short brief. Include the job, its scope, what it must not do, and when to ask you.
    18. +
    19. Add write permissions separately. Be specific about the actions and identities involved. Don't confuse an automated approval with another person's review.
    20. +
    21. Limit work in progress. Make finishing or escalating the existing task more important than starting another.
    22. +
    23. Prove the real path. Test with the account and interface people will actually use. A successful owner-side test doesn't establish that a teammate's Slack request will work.
    24. +
    25. Add coordination when it earns its place. Once several bots produce useful reports, one briefing can be easier to use than several separate digests.
    -

    The surprise for me is that the hard part isn't the AI. It's the stuff I've always found hard as a software engineer: clear ownership, small work, protecting people's attention, and saying "no" to busywork.

    +

    For me, the interesting part isn't having twenty bots. It's making each one responsible for a job I can understand, with enough evidence to tell whether it did that job and clear limits on what it can do next.

    If you're building something similar, I'd love to compare notes. Find me on GitHub at @redreceipt.

    diff --git a/portfolio.css b/portfolio.css index 84df38fbcaf28..925d7801ab704 100644 --- a/portfolio.css +++ b/portfolio.css @@ -31,7 +31,7 @@ body { margin: 0; } h1, h2, h3, p { margin: 0; } a { color: var(--accent); text-underline-offset: 0.22em; } a:hover { text-decoration-thickness: 2px; } -a:focus-visible, .article pre:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; } +a:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; } ::selection { background: var(--accent); color: var(--bg); } .shell { max-width: 42rem; margin: auto; padding: 0 1.5rem; } @@ -150,18 +150,25 @@ h1 span { color: var(--accent); } .article ul, .article ol { padding-left: 1.4rem; } .article li { margin: 0.3rem 0; } .article strong { font-weight: 600; } -.article pre { - background: var(--surface); - border: 1px solid var(--line); - margin: 1.5rem 0; - padding: 0.9rem 1rem; - overflow-x: auto; - font-size: 0.8rem; -} -.article code { font-family: inherit; } -.article :not(pre) > code { background: var(--surface); padding: 0.05em 0.3em; } +.article code { font-family: inherit; background: var(--surface); padding: 0.05em 0.3em; } .article hr { border: 0; border-top: 1px solid var(--line); margin: 2rem 0; } +.bot-map { margin: 2rem 0; } +.bot-map-node { max-width: 24rem; margin: auto; padding: 1rem; text-align: center; border: 1px solid var(--line); background: var(--surface); } +.bot-map-node span { display: block; color: var(--muted); font-size: 0.8rem; } +.bot-map-hub { border-color: var(--accent); } +.bot-map-hub strong { color: var(--accent); } +.bot-map .bot-map-arrow { margin: 0.25rem 0; text-align: center; color: var(--accent); font-size: 1.5rem; } +.bot-map-groups { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.75rem; } +.bot-map-groups > div { padding: 1rem; border: 1px solid var(--line); } +.bot-map h3 { margin: 0 0 0.6rem; font-size: 0.9rem; } +.bot-map-groups ul { display: flex; flex-wrap: wrap; gap: 0.25rem 0.85rem; list-style: none; margin: 0; padding: 0; } +.bot-map-groups li { margin: 0; font-size: 0.85rem; } +.bot-map .bot-map-label { margin: 1.5rem 0 0.5rem; color: var(--muted); font-size: 0.75rem; } +.bot-map .bot-map-flow { display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; margin: 0; padding-left: 1.4rem; } +.bot-map-flow li { flex: 1 1 8rem; padding: 0.4rem 0; font-size: 0.8rem; } +.bot-map figcaption { margin-top: 1rem; color: var(--muted); font-size: 0.75rem; } + .skip-link { position: absolute; top: -100px; @@ -190,4 +197,5 @@ h1 span { color: var(--accent); } .intro { padding: 3rem 0 2.5rem; } .section-header, .contact { align-items: flex-start; flex-direction: column; } .contact { gap: 1rem; } + .bot-map-groups { grid-template-columns: 1fr; } } From 587fe8189581693c9fa0939a06cdfe04e75003fa Mon Sep 17 00:00:00 2001 From: Michael Neeley Date: Thu, 15 Oct 2026 19:30:24 -0400 Subject: [PATCH 5/8] Make the diagram workflow three compact matching cards --- grok-bots/index.html | 4 ++-- portfolio.css | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/grok-bots/index.html b/grok-bots/index.html index f274d0880099b..6badc82035462 100644 --- a/grok-bots/index.html +++ b/grok-bots/index.html @@ -82,9 +82,9 @@

    Production & support

    For delegated code changes

      -
    1. Cloud coding agent
    2. +
    3. Cloud agent
    4. Pull request
    5. -
    6. Repository review & CI gates
    7. +
    8. Review & CI
    Switchboard collects digests from the specialists; they can also contact me directly. The code path applies to coding tasks, not every bot action.
    diff --git a/portfolio.css b/portfolio.css index 925d7801ab704..f2e6e722c93f9 100644 --- a/portfolio.css +++ b/portfolio.css @@ -165,8 +165,9 @@ h1 span { color: var(--accent); } .bot-map-groups ul { display: flex; flex-wrap: wrap; gap: 0.25rem 0.85rem; list-style: none; margin: 0; padding: 0; } .bot-map-groups li { margin: 0; font-size: 0.85rem; } .bot-map .bot-map-label { margin: 1.5rem 0 0.5rem; color: var(--muted); font-size: 0.75rem; } -.bot-map .bot-map-flow { display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; margin: 0; padding-left: 1.4rem; } -.bot-map-flow li { flex: 1 1 8rem; padding: 0.4rem 0; font-size: 0.8rem; } +.bot-map .bot-map-flow { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.75rem; margin: 0; padding: 0; list-style-position: inside; } +.bot-map-flow li { margin: 0; padding: 0.85rem 0.75rem; border: 1px solid var(--line); background: var(--surface); font-size: 0.8rem; } +.bot-map-flow li::marker { color: var(--accent); } .bot-map figcaption { margin-top: 1rem; color: var(--muted); font-size: 0.75rem; } .skip-link { @@ -197,5 +198,5 @@ h1 span { color: var(--accent); } .intro { padding: 3rem 0 2.5rem; } .section-header, .contact { align-items: flex-start; flex-direction: column; } .contact { gap: 1rem; } - .bot-map-groups { grid-template-columns: 1fr; } + .bot-map-groups, .bot-map .bot-map-flow { grid-template-columns: 1fr; } } From 22c8dcfda0d599615c01e59c16807a8221168605 Mon Sep 17 00:00:00 2001 From: Michael Neeley Date: Thu, 15 Oct 2026 19:34:55 -0400 Subject: [PATCH 6/8] Focus the article on my bot workflows and cut platform explanations --- grok-bots/index.html | 77 ++++++++++++-------------------------------- portfolio.css | 6 +--- 2 files changed, 21 insertions(+), 62 deletions(-) diff --git a/grok-bots/index.html b/grok-bots/index.html index 6badc82035462..bc83a1290fb03 100644 --- a/grok-bots/index.html +++ b/grok-bots/index.html @@ -38,19 +38,9 @@

    My Team of Twenty Bots

    How I use small, specialized AI assistants alongside my work as a software engineer.

    I'm Michael Neeley (@redreceipt), a software engineer at Differential working on Apollos, software for churches. The work isn't just writing code. There are pull requests to review, issues to triage, support questions to investigate, and a steady stream of notifications to sort through.

    -

    I use Grok Bot to delegate parts of that work to a roster of twenty assistants. Each has a name, a specific job, and instructions about what it can change and when it should ask me. Some run on schedules; others respond to a question or a handoff from another bot.

    -

    This is a snapshot of the setup in October 2026, not a productivity study or a claim that twenty agents run everything unattended. The useful part is the division of work, and the limits around it.

    -
    -

    Why a team instead of one assistant?

    -

    A narrow brief is easier to reason about than a single assistant responsible for everything. I can change the inbox rules without changing how code reviews work, or pause a code-improvement bot without stopping the morning briefing.

    -
      -
    • One primary job per bot. A cleanup bot looks for cleanup. A review bot helps with reviews. Their instructions can be specific instead of trying to cover every situation.
    • -
    • Explicit ownership, including exceptions. Sieve owns inbox triage. Semver has a narrower exception for dependency-related email. That boundary needs to be written down, not assumed.
    • -
    • Separate permissions. Reading a ticket, opening a PR, approving it, and merging it are different powers. A bot doesn't need all of them to be useful.
    • -
    • Names help. A message from Nanny has a clearer purpose than another update from an unnamed general assistant.
    • -
    -

    How it fits together

    -

    Switchboard is the coordinator. It gathers reports, delegates to the appropriate bot, and prepares my weekday briefing. The specialists can also report directly to me. It's a way to consolidate information, not a strict chain through which every action has to pass.

    +

    I use twenty Grok bots for recurring jobs: watching projects, sorting notifications, keeping PRs moving, and investigating bugs. Here's how I've split up that work, as of October 2026.

    +

    How I organize the work

    +

    Switchboard gathers reports from the specialists and prepares my weekday briefing. I use it to bring updates together and pass new instructions to the bots they affect, instead of repeating myself in every chat.

    Michael @@ -80,72 +70,45 @@

    Production & support

    • Triager
    • Pipeline
    • Medic
    • Compass
    -

    For delegated code changes

    -
      -
    1. Cloud agent
    2. -
    3. Pull request
    4. -
    5. Review & CI
    6. -
    -
    Switchboard collects digests from the specialists; they can also contact me directly. The code path applies to coding tasks, not every bot action.
    +
    Switchboard consolidates reports from the specialists; they can also contact me directly.
    -

    For hands-on coding, many of the bots hand a bounded task to a Cursor cloud agent. The result comes back as a pull request. What happens next depends on the bot's permissions and the repository's review and CI requirements: some PRs stay draft for a decision, while others can use auto-merge.

    -

    That distinction matters. Some bots are authorized to submit certain approvals through my GitHub account. That isn't the same as an independent human review.

    -

    The jobs span GitHub, Linear, Slack, and work Gmail, with tools such as Sentry, Astronomer/Airflow, Metabase, and Expo for specialized work. Access to a tool still has to be configured; having it in a bot's brief doesn't make the connection work.

    The daily rhythm

    Before the weekday briefing, the coordination bots gather project status, scope concerns, and PRs waiting on a decision. Switchboard brings those reports together so I don't have to read each one separately.

    -

    Through the day, scheduled scans and event-triggered routines keep the work moving. Several code and production bots have weekday hourly routines. Sieve checks inbox noise hourly, Nanny watches my PRs, and Semver combines a weekday dependency sweep with PR-event triggers. These are different schedules, not twenty bots all firing at once.

    -

    Weekly and monthly passes cover work that doesn't need an hourly loop: Foreman's stale-ticket sweep, Bottleneck's weekly constraint brief, and Keystone's monthly technical proposal in Linear.

    -

    The scans are meant to stay quiet unless they find useful work or need a decision. The goal is fewer interruptions, not another stream of status messages.

    +

    Through the day, Sieve checks inbox noise hourly, Nanny watches my PRs, and Semver keeps up with dependency updates. The code-improvement bots look for work without filling the review queue with competing PRs.

    +

    Weekly and monthly passes cover Foreman's stale-ticket sweep, Bottleneck's constraint brief, and Keystone's technical proposal in Linear.


    The roster

    Coordination

    Switchboard: Executive Assistant. Coordinates the other bots, gathers their digests, and prepares the briefing. When I change a standing rule, I can ask Switchboard to relay it to the bots it affects.

    -

    Foreman: Project Manager. Watches the Linear projects I'm responsible for and posts updates when something changes. Its weekly stale-ticket sweep also covers my assigned issues, including ones outside a project. Clear follow-up work can go to a cloud agent; closing or changing ownership needs a separate decision.

    +

    Foreman: Project Manager. Watches the Linear projects I'm responsible for and posts updates when something changes. Its weekly sweep catches my assigned issues that have gone quiet, even if they aren't in a project.

    Trawler: Linear Projects. Takes a wider view across engineering projects and reports material status, blockers, and drift. Foreman focuses on moving my work forward; Trawler supplies a broader picture.

    -

    Chisel: Engineering Manager. The scope critic. It compares planned work with active issues and PRs, then recommends what to cut, defer, or combine. Those are recommendations, not permission to rearrange everyone's work automatically.

    -

    Bottleneck: Constraints Advisor. Looks across the available business and project tools and proposes one top constraint, with evidence and concrete recommendations. The point is to force a priority, rather than produce another long status list. Its scope includes Slack, Linear, and Basecamp where access is available.

    +

    Chisel: Engineering Manager. The scope critic. It compares planned work with active issues and PRs, then gives me concrete suggestions about what to cut, defer, or combine.

    +

    Bottleneck: Constraints Advisor. Looks across the available business and project tools and proposes one top constraint, with evidence and concrete recommendations. I want a priority to act on, not another long status list.

    Inbox & PRs

    Sieve: Email & Linear Triage. Owns the rules for clearing skippable work Gmail and Linear notifications while keeping real asks and blockers. For GitHub email, it checks the current PR or issue state rather than trusting the subject line. Archiving is a whole-thread operation, not deleting individual messages. It also looks for noise that can be turned off at the source, so it doesn't have to keep cleaning up the same notifications.

    Nanny: PR Monitor. Watches my PRs for CI, reviews, comments, and work that needs attention. Drafts are included: it summarizes their state and asks whether I want them marked ready, closed, or kept. It shouldn't make that decision for me or ask the same unchanged question every hour.

    -

    Stamp: PR Reviews. Handles mechanical reviews and helps prepare more substantial ones. For in-scope simple changes, a clean automated review can lead to an approval through my account. For changes needing judgment, it gathers the review feedback and prepares a brief for me instead. It avoids redundant Codex requests when an existing approval already covers the work. On in-scope conflicted PRs, it leaves one comment review asking the author to resolve the conflict and re-request. It doesn't merge PRs. In repositories that require no approvals, it can tell the author that my approval isn't a prerequisite rather than creating another unnecessary wait.

    -

    Semver: Dependency Updates. Works through Dependabot PRs, separates routine updates from risky ones, and can delegate the changes needed to get a dependency branch into shape. It has permission to approve and merge certain low-risk updates; major or uncertain changes come back to me for a decision. Auto-merge may already be armed while a PR waits for that decision, so its presence alone doesn't mean I've approved the update. Semver also has a limited dependency-email cleanup role alongside Sieve.

    +

    Stamp: PR Reviews. Handles mechanical reviews and prepares briefs for changes that need my judgment. For in-scope simple changes, a clean automated review can lead to an approval through my account. It follows up on review feedback and conflicts so I don't have to chase every author myself. It doesn't merge PRs. In repos that don't require approvals, it tells authors they don't need to wait for mine.

    +

    Semver: Dependency Updates. Works through Dependabot PRs and gets dependency branches into shape. It can approve and merge certain low-risk updates; major or uncertain changes come back to me for a decision. It also handles a limited slice of dependency-related email alongside Sieve.

    Code improvement

    -

    These bots share a useful rule: check for an existing open PR in the same workstream before starting another. Each has a label, such as architecture, slop, or e2e. The bot searches the repositories in its scope and waits if that label already has an open PR. The aim is to keep an hourly schedule from producing an hourly pile of review work. It's an instruction the bot must follow, not a platform-enforced lock.

    -

    Their PR settings aren't identical. Keystone, Hotpath, and Intruder are draft-first. Codemod and Smoke are configured to open ready-for-review PRs with reviewers and auto-merge where supported. Pruner holds work in draft while CI is incomplete, then moves it toward review. Onramp also waits for green CI before requesting reviewers. Those differences belong in the briefs; there isn't one universal workflow for every code bot.

    +

    I give these bots a one-open-PR rule: if their workstream already has an open PR, wait rather than start another. That keeps the review queue manageable.

    Keystone: Software Architect. Looks for unclear boundaries and handoffs between services and apps, then proposes concrete structural improvements. It also has a monthly technical-proposal routine that files a recommendation in Linear Triage, with evidence, tradeoffs, and a migration plan.

    Codemod: TypeScript Migration. Converts JavaScript to TypeScript in small, mechanical steps. The brief is to improve type safety without quietly changing behavior.

    Pruner: Code Cleanup. Looks for dead code, pointless wrappers, redundant tests, and unnecessary complexity. Deletion and simplification are the job, not adding another abstraction.

    Smoke: E2E Testing. Looks for critical flows without useful end-to-end coverage and adds tests for those gaps. The aim is protection against real regressions, not a bigger test count.

    -

    Hotpath: Performance. Looks for concrete performance problems: repeated queries, unnecessary rendering, wasted work, and expensive synchronous paths. Improvements need evidence, not just a claim that a shorter implementation is faster.

    +

    Hotpath: Performance. Looks for repeated queries, unnecessary rendering, wasted work, and expensive synchronous paths, then proposes improvements with evidence.

    Intruder: Security. Does defensive security work within the repositories it's authorized to inspect. Its brief calls for demonstrable issues and root-cause fixes, not speculative scanner noise or work outside that scope.

    Onramp: Agent DX. Improves the setup instructions, tooling, debug access, and QA paths that coding agents use. A reliable development path helps every bot that touches the repository.

    Production & support

    Triager: Error Triage. Uses Sentry to find a high-impact unresolved error, investigates it, and delegates a root-cause fix through a draft PR. Silencing the error isn't the objective.

    Pipeline: Data Pipelines. Uses Astronomer/Airflow to investigate a failing active DAG and work toward a fix with tests. Disabling a broken job isn't the same as repairing it.

    -

    Medic: Support Triage. Investigates actionable Linear support issues one at a time, records findings, and can open a fix. It has its own Linear app and GitHub bot identity rather than presenting that output as my personal work. Mobile investigations can include Expo and emulator or simulator proof. Its environment and permissions have needed setup and recovery work too; being assigned a ticket doesn't guarantee it can complete every step unattended.

    -

    Compass: Product Guide. Answers product and code questions for teammates in Slack, with analytics questions added through Metabase. Making that useful took more than adding a bot to a channel: the initial team-bot setup asked people to connect their own accounts, and I worked on shared tool access to reduce that friction. Shared tool access reduced that friction, but account linking and subscription requirements still mattered.

    +

    Medic: Support Triage. Investigates actionable Linear support issues one at a time, records findings, and can open a fix. It uses its own Linear app and GitHub bot identity, so its work isn't presented as mine.

    +

    Compass: Product Guide. Answers product and code questions for teammates in Slack, plus analytics questions through Metabase. It gives non-engineering teammates a place to ask how a feature works without waiting for me to dig through the code.


    -

    Guardrails and lessons learned

    -

    The setup is useful, but it's not self-maintaining. Instructions can drift, credentials can be missing, and an agent can confidently summarize a result it hasn't actually demonstrated. These are the rules I keep coming back to.

    -

    1. Separate permissions from intentions. A bot that can read GitHub doesn't automatically need permission to approve or merge. Stamp and Semver have specific authority to act through my account; Medic has its own app identities. A proposed action, an authorized action, and a completed action should be distinguishable in the record.

    -

    2. Distinguish speaking for me from speaking as a bot. Messages that represent me personally need approval. That doesn't mean every message any bot sends is a draft: support bots reply under their own identities, and several routines are explicitly authorized to post updates or reviews. The scope of that standing permission matters.

    -

    3. Keep changes small without a numeric line cap. I removed the old 200-line rule. The instruction now is to do the smallest complete job, especially when responding to feedback. Old wording has resurfaced in saved instructions. A rule isn't really updated until the brief, saved memory, and scheduled prompts agree.

    -

    4. Put a limit on work in progress. The one-open-PR label check is a way to apply backpressure. A bot should spend its time getting the existing item unstuck before creating another review obligation.

    -

    5. Verify the result on the real surface. Green unit tests aren't proof that a screen works. A key being present isn't proof that a write succeeded. A merged PR isn't proof that its fix has reached users. Ask for the actual request, screenshot, log, or resulting state, and label anything that couldn't be checked.

    -

    6. Make ownership and exceptions explicit. Sieve owns general inbox triage; Semver has a limited exception. Nanny watches my PRs; Stamp handles review work on other people's PRs. Named boundaries are easier to correct than two bots independently deciding that a task belongs to them.

    -

    7. Reduce noise rather than just sorting it. Stay quiet when there's no useful update, consolidate reports through Switchboard, and turn off redundant notifications where appropriate. Don't tag someone unless they have something to do. Don't update a branch merely because it's behind.

    -

    8. Treat rules as configuration that needs maintenance. Telling Switchboard about a change is a convenient way to distribute it, but a confirmation isn't proof that every saved copy is consistent. The line-cap cleanup and the shared-access work both needed follow-up.

    -

    How to start your own

    -

    I wouldn't start by reproducing this whole roster. I'd start with one recurring job:

    -
      -
    1. Begin with a read-only summary. Let a bot identify what needs attention before giving it permission to archive, approve, or change anything.
    2. -
    3. Write a short brief. Include the job, its scope, what it must not do, and when to ask you.
    4. -
    5. Add write permissions separately. Be specific about the actions and identities involved. Don't confuse an automated approval with another person's review.
    6. -
    7. Limit work in progress. Make finishing or escalating the existing task more important than starting another.
    8. -
    9. Prove the real path. Test with the account and interface people will actually use. A successful owner-side test doesn't establish that a teammate's Slack request will work.
    10. -
    11. Add coordination when it earns its place. Once several bots produce useful reports, one briefing can be easier to use than several separate digests.
    12. -
    -

    For me, the interesting part isn't having twenty bots. It's making each one responsible for a job I can understand, with enough evidence to tell whether it did that job and clear limits on what it can do next.

    +

    What I've learned

    +

    Stop noise at the source. I expanded Sieve's job from archiving notifications to finding subscriptions and settings we can turn off. That's better than cleaning up the same noise every hour.

    +

    Small changes beat a line limit. I removed the old 200-line PR rule and now ask for the smallest complete fix. The old wording kept resurfacing, so changing a rule also means checking the saved briefs and routine prompts—not just mentioning it in chat.

    +

    Test with the people who will use it. Trying Compass with teammates uncovered account-linking requirements I hadn't hit in my own chat. I worked on shared tool access, but testing with the person asking the question was part of making it useful.

    +

    That's what I'm trying to get out of Grok Bot: fewer loose ends to chase, and more attention left for the coding and decisions that need me.

    If you're building something similar, I'd love to compare notes. Find me on GitHub at @redreceipt.

    diff --git a/portfolio.css b/portfolio.css index f2e6e722c93f9..a7aab4c78ed55 100644 --- a/portfolio.css +++ b/portfolio.css @@ -164,10 +164,6 @@ h1 span { color: var(--accent); } .bot-map h3 { margin: 0 0 0.6rem; font-size: 0.9rem; } .bot-map-groups ul { display: flex; flex-wrap: wrap; gap: 0.25rem 0.85rem; list-style: none; margin: 0; padding: 0; } .bot-map-groups li { margin: 0; font-size: 0.85rem; } -.bot-map .bot-map-label { margin: 1.5rem 0 0.5rem; color: var(--muted); font-size: 0.75rem; } -.bot-map .bot-map-flow { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.75rem; margin: 0; padding: 0; list-style-position: inside; } -.bot-map-flow li { margin: 0; padding: 0.85rem 0.75rem; border: 1px solid var(--line); background: var(--surface); font-size: 0.8rem; } -.bot-map-flow li::marker { color: var(--accent); } .bot-map figcaption { margin-top: 1rem; color: var(--muted); font-size: 0.75rem; } .skip-link { @@ -198,5 +194,5 @@ h1 span { color: var(--accent); } .intro { padding: 3rem 0 2.5rem; } .section-header, .contact { align-items: flex-start; flex-direction: column; } .contact { gap: 1rem; } - .bot-map-groups, .bot-map .bot-map-flow { grid-template-columns: 1fr; } + .bot-map-groups { grid-template-columns: 1fr; } } From 133dc92a6c491e2698624a5e268e69fcc99b2e70 Mon Sep 17 00:00:00 2001 From: Michael Neeley Date: Thu, 15 Oct 2026 19:43:22 -0400 Subject: [PATCH 7/8] Credit Switchboard in the article's closing line --- grok-bots/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grok-bots/index.html b/grok-bots/index.html index bc83a1290fb03..7e59eaa3bf132 100644 --- a/grok-bots/index.html +++ b/grok-bots/index.html @@ -109,7 +109,7 @@

    What I've learned

    Small changes beat a line limit. I removed the old 200-line PR rule and now ask for the smallest complete fix. The old wording kept resurfacing, so changing a rule also means checking the saved briefs and routine prompts—not just mentioning it in chat.

    Test with the people who will use it. Trying Compass with teammates uncovered account-linking requirements I hadn't hit in my own chat. I worked on shared tool access, but testing with the person asking the question was part of making it useful.

    That's what I'm trying to get out of Grok Bot: fewer loose ends to chase, and more attention left for the coding and decisions that need me.

    -

    If you're building something similar, I'd love to compare notes. Find me on GitHub at @redreceipt.

    +

    And yes, Switchboard wrote this article

    From 552a8117e1240945b1647250abbd5d2676a4a62b Mon Sep 17 00:00:00 2001 From: Michael Neeley Date: Thu, 15 Oct 2026 19:49:14 -0400 Subject: [PATCH 8/8] Ground the lessons in attention, decisions, and choosing less work --- grok-bots/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grok-bots/index.html b/grok-bots/index.html index 7e59eaa3bf132..1f8571a337c9d 100644 --- a/grok-bots/index.html +++ b/grok-bots/index.html @@ -106,8 +106,8 @@

    Production & support


    What I've learned

    Stop noise at the source. I expanded Sieve's job from archiving notifications to finding subscriptions and settings we can turn off. That's better than cleaning up the same noise every hour.

    -

    Small changes beat a line limit. I removed the old 200-line PR rule and now ask for the smallest complete fix. The old wording kept resurfacing, so changing a rule also means checking the saved briefs and routine prompts—not just mentioning it in chat.

    -

    Test with the people who will use it. Trying Compass with teammates uncovered account-linking requirements I hadn't hit in my own chat. I worked on shared tool access, but testing with the person asking the question was part of making it useful.

    +

    I need decisions, not status dumps. Twenty assistants could easily give me twenty more places to check. I use Switchboard to bring the reports together, ask Bottleneck for one top priority, and work through Stamp's review list one decision at a time. The useful output isn't everything they've found. It's what needs my attention, why it matters, and the call I need to make.

    +

    Sometimes the useful answer is to do less. When a couple of my projects got caught in the weeds, I asked Chisel to cut them back to what was absolutely critical—including questioning whether any of it was. I don't just want help getting through a larger task list faster. I want the assistants to challenge what belongs on the list in the first place.

    That's what I'm trying to get out of Grok Bot: fewer loose ends to chase, and more attention left for the coding and decisions that need me.

    And yes, Switchboard wrote this article