🛰️ Signal Boost

Bots Are a Tactic, Not a Strategy

Most teams that build an internal bot think they're solving a tooling problem. They aren't. They're choosing a delivery mechanism before they've decided what they're delivering.

The question usually shows up like this: "Should we build a bot for X?" It sounds practical. It's actually the wrong question, the same way "Should we build a dashboard?" is the wrong question before anyone knows what decision the dashboard is supposed to serve. A bot isn't a solution. It's a way of getting a solution in front of people. The real questions come first: what work should be automated, and where should that automation live?

Answer those well and the bot question mostly answers itself. Skip them and you end up with a chat channel full of bots, each one somebody's side project, none of them part of a plan.

Automation Has Many Homes

When leaders say "automation," they usually picture the most visible kind. But most automation that actually pays off is boring and close to invisible. It lives in a lot of different places, and each one fits a different shape of work.

One-off scripts. For work you'll do once or twice: a cleanup, a backfill, a migration. Write it, run it, keep it somewhere findable, and move on.

CI and pipeline steps. For work that has to happen every time code changes. If it should run on every merge, it belongs in the pipeline, not in someone's memory.

Guardrails. Lint rules, policy checks, quality gates. For mistakes you never want to make again. A guardrail doesn't remind anyone of anything. It simply doesn't let the wrong thing through.

Scheduled jobs and digests. For slow-moving problems nobody notices in the moment: costs creeping up, resources left behind, a database getting a little less healthy every week. A digest turns background drift into a regular, readable signal.

Self-serve tools and dashboards. For questions people ask in different ways at different times. Exploration needs a place to explore, not a message.

Bots and agents. For work that shows up unannounced, needs judgment, and needs to reach people where they already are.

None of these is better than the others. They're different tools for different jobs. Most teams don't lack automation. They lack a deliberate decision about which home each piece of work belongs in.

Bot or Not

Bots get overused because they're the most fun to build and the most visible to ship. A bot announces itself. A lint rule quietly prevents a problem nobody ever sees. That visibility is exactly why it pays to be disciplined about when a bot is the right call.

A bot earns its place when the work is:

Event-driven. Something happens at an unpredictable moment and someone needs to respond: a pipeline fails, an error spikes, a resource gets left running.

In need of triage or judgment. The response isn't a fixed rule. Someone has to weigh what happened and decide what it means.

Crossing systems. The answer means stitching together information that lives in several different places.

Best delivered where people already work. The right person needs to know now, and the place they'll actually see it is chat.

A fit for staged autonomy. It can start by proposing, earn trust, and only later act on its own.

A bot is the wrong call when:

The rule is deterministic. If the answer is always the same, put it in CI or a lint rule. A bot enforcing a fixed rule is a guardrail with extra moving parts.

It's a one-off. Write a script. Don't stand up a service for something you'll run twice.

People need to explore. Build a tool or a dashboard. Nobody wants to hold a conversation with a bot to answer a question they could have answered by looking.

The short version: if the work doesn't need judgment or someone's attention in the moment, it probably doesn't need a bot.

Our Story: The Bot That Was Really a Platform

Ours started as "a bot that fixes production errors." It was a single scheduled script that watched production errors and opened merge requests with proposed fixes. Useful, narrow, and entirely dependent on the engineer who wrote it.

What changed its trajectory wasn't a better model or a smarter prompt. It was noticing that the valuable part wasn't the bot. It was everything underneath it. Making that one job reliable had required a handful of pieces that had nothing to do with fixing errors, so we pulled them out and made them shared:

An event bus, so anything can react to something that happened.

A durable job queue, so work survives restarts and never overlaps when it shouldn't.

Settings declared once and rendered as UI, so nobody hand-builds a configuration page or edits config in production.

A shared activity feed, so every automation records what it did in one place.

A standard rollout switch: off → dry-run → on, so every capability ships dark and proves itself before it acts.

Once that foundation existed, chat turned out to be just one surface. Half of what got built on it isn't a bot at all. There's a CI cost dashboard. There's a weekly digest of orphaned cloud resources quietly wasting money. There's a weekday digest of database health. Alongside them sit the parts that do look like bots: one that triages CI failures, and the original one that proposes fixes for production errors.

The moment I knew it was working was when another engineer on the team built two capabilities on it without the original author involved at all. That's when it stopped being one person's bot and became part of how the team automates.

The bot was the tactic. What it needed underneath turned out to be the strategy.

Building an Internal Automation Strategy

Strategy sounds grand. In practice it comes down to three moves.

Inventory the toil. Before you build anything, write down the repetitive work your team actually does. Not the work that would make an impressive demo. The work that eats Tuesday afternoons.

Pick the cheapest reliable mechanism for each item. Not the most interesting one. Most of the list will turn out to be scripts, pipeline steps, and guardrails. That's good news. Those are cheap to build and cheap to own.

Share one platform underneath. For what's left, the digests, tools, and bots, build on common foundations so every new automation, bot or not, is cheap to add.

That last move is where teams either build leverage or build a graveyard. A few early decisions make the difference, and they're worth defending:

One contract as the source of truth. Every capability declares itself in a single manifest: what it listens for, the settings it exposes, the secrets it needs, the schedules it runs on. A new contributor reads one file and knows the whole surface area. A reviewer reads one file and knows exactly what changed.

Hand capabilities in. An automation shouldn't go find its own credentials. The platform hands it the tools it's allowed to use: post to chat, record activity, queue work. That makes it safe, testable, and reviewable, because the list of what it can touch is right in front of you.

Events, not triggers. Automations subscribe to things that happened instead of being wired into someone else's code. A new one can attach to an existing event without touching anything already listening. Adding never requires editing.

Abstract on the second use, not the first. Build the first one concretely. When the second one needs the same thing, pull it into the platform. An abstraction designed for one use case is a guess. An abstraction extracted from two is evidence.

Making Bots Succeed Inside the Strategy

Choosing a bot for the right reasons is half the job. The other half is making it something people trust and want to extend. Building the platform is an engineering problem. Getting people to rely on it is a leadership problem. The goal is a pit of success: a shape where the easiest path for a contributor is also the correct one.

The second automation must be cheaper than the first. Early on, a new capability had to be registered in two places: once where it ran, and once where the admin interface discovered it. One got registered in only one. It ran perfectly, and nobody could see it or turn it on. That wasn't the contributor's mistake. It was a system that required two steps and checked one.

Trust before autonomy. At one point we audited the fix merge requests the bot had opened. Most of them should have been closed. Some patched code the error couldn't even reach. Some silenced the error instead of fixing it. The AI reviewer in the loop approved every one. Asking people for another chance wasn't going to fix that, so we built what should have been there from the start: quality gates that require every fix to bring a regression test that fails first and passes after, dry-run rollouts so each gate proves itself before it blocks anything, and a janitor that closes stale merge requests on its own. Those gates are rolling out the way everything else does, dark first. The point isn't a better pitch. It's making yes a safe answer.

Quiet unless a human is needed. During one outage, a single chat thread filled with dozens of near-identical replies. Noise teaches people to mute you, and once they have, your most important message goes unseen.

Measure outcomes, not executions. That same automation looked healthy for weeks. It ran. It posted. But only a small fraction of its retries ever actually happened. "It ran" proves nothing.

Report in the business's units. Nobody outside engineering cares how many events your platform processed. They care about dollars of waste found and hours of triage that never had to happen. Report in those units and the platform stops looking like a side project.

Humans stay the merge button. The bot proposes. A person decides. Autonomy is earned in stages, and the trust that default builds is what makes later autonomy possible.

Ownership must survive the builder. The real test isn't what the author can build on it. It's what someone else can build without them.

What Does Your Strategy Need?

A team that reaches for a bot first usually doesn't have an automation problem. It has a strategy problem, and the bot is just the most visible symptom.

That isn't a failure of effort. It's a failure of framing. The fix isn't a smarter bot. It's stepping back far enough to see all the work, choosing the right home for each piece, and building the shared foundation that makes the next automation cheap, whatever shape it takes.

Stop asking what your bot should do. Ask what your automation strategy needs, and whether a bot is the right tactic for it.

So ask yourself: if you listed every piece of repetitive work your team did last week, how much of it actually belongs in a bot?

A bot is a delivery mechanism. Strategy is deciding what's worth delivering.

🔗 Lead Link

One standout article from the web that delivers signal, not noise.

What is a Thinnest Viable Platform (TVP)? — Matthew Skelton and Manuel Pais, Team Topologies

Why this matters:

The Team Topologies authors argue that a good platform is "just big enough": run as a product, with the teams who use it treated as customers and developer experience treated as the measure of success. That's the right lens for an internal automation strategy. The goal isn't the most impressive bot. It's the thinnest shared foundation that makes every kind of automation, from a digest to a dashboard to a bot, easy to add and easy to trust. Start thin, extract on the second use, and judge the platform by whether other people choose to build on it.

🛠️ Tactical Byte

A quick tip or tactic you can try this week.

Pick the home before you pick the bot.

Before anyone on your team builds the next bot, spend a week finding out what the work actually is. Most of it will belong somewhere quieter.

Try This:

  • Inventory a week of toil. Ask the team to jot down every repetitive task they did this week. Then label each one: script, CI, guardrail, digest, tool, or bot. If "bot" is the most common label, look again. It usually means the work hasn't been understood yet.

  • Ship every capability dark first: off → dry-run → on. New behavior starts disabled, then runs in dry-run where it only records what it would have done, then goes live after someone has read that record. Use the same switch for everything, so nobody has to learn a new rollout story per feature.

  • Count outcomes, not executions. For each automation, pick the one number that proves it helped: retries that turned a red pipeline green, fixes that got merged and stayed merged, dollars of waste actually removed. Put it next to the execution count. If the two have drifted apart, you've found your next problem.

🎙️ From the Field

An insight, quote, or story from an experienced tech leader.

One of the capabilities on our internal automation platform watches CI. Its job is simple: when a job fails because of something outside our control, like a flaky dependency or an upstream service having a bad hour, retry it so an engineer doesn't have to.

Then an upstream provider had an outage, and failures started landing everywhere at once.

The bot did what it was built to do. For every failed job, it confidently posted "Retrying…" in the team's channel. One thread filled with dozens of near-identical replies. It looked busy. It looked like it was handling things.

It wasn't. Behind the scenes, it was skipping almost all of those retries. The bot had a rule of its own: if a newer pipeline existed for the same branch, retrying the older one was pointless, so skip it. Reasonable on paper. But the CI system already makes that call. It already decides which pipelines to keep and which to cancel. The bot's rule was a second opinion, and it disagreed with the first. So the bot announced each retry, then quietly decided not to do it.

Nobody was careless. The rule made sense when it was written. The real problem was that the bot had taken on a job the CI system already did better.

The fix was moving the decision back to where it belonged:

  • Remove the second opinion. The bot no longer decides which pipelines are worth saving. The CI system's decisions stand.

  • Retry while the pipeline is still in flight. Instead of waiting for a whole pipeline to finish and then judging it, the bot retries a failed job while its pipeline is still running, when a retry can still change the outcome. That part is shipping dark first, recording what it would retry before it acts.

  • Stay silent unless a retry fails again. A successful retry doesn't need an audience. The bot only speaks up when a human genuinely needs to look.

Retries actually run now. The bot got more useful by doing less.

Lesson for leaders: Before an automation makes a decision, ask whether another system already owns it. A bot that second-guesses the tools around it isn't adding judgment. It's adding a place for the truth to get lost.

💬 Open Threads

Something to chew on, debate, or share back—open questions for curious minds.
  • When your team last asked "should we build a bot for this?", what question should it have asked first?

  • If you sorted your current bots into script, CI, guardrail, digest, tool, or bot, how many would still land in the bot column?

  • What does your internal automation share underneath? Does each new automation get cheaper to add, or does every one start from scratch?

  • Which of your automations report how often they ran, and which report whether they worked?

  • Where is your automation making a decision that another system already owns?