Bottom Line Studio AI

Propose freely. Merge never.

Everyone wants their GTM data “AI-ready.” Most teams start by choosing an agent — which is the easy part, and the wrong end of the problem. Here is the architecture that actually makes an AI agent safe to run against the numbers your revenue team depends on.

A few weeks ago I mapped every automated check running across a production GTM data platform — the CI workflows guarding two repositories, roughly 640 automated data tests, dozens of scheduled jobs, and the alerts watching all of it.

The inventory itself was not the interesting part. Counts make for a nice slide and tell you almost nothing. What mattered was a single structural property of how the pieces fit together, and it is the thing I would carry into any team trying to put AI near their revenue data.

When the pipeline breaks, an AI agent triages the failure and drafts the fix. It has no path to production that skips the review gate. Not a discouraged path. No path.

That asymmetry — propose freely, merge never — is what makes the rest of the system safe to scale. Everything below is an argument for why, and what it costs to build.

What the loop actually does

Every night, the platform pulls the current merged code, rebuilds every model against production data, and runs its full test suite. When something breaks, the sequence is automatic and it ends somewhere specific.

01 02 03 04 05 Propose Gate Build Sense Detect a person or an agent drafts a change runs on production data, on a schedule tests record failures where a machine can read something reads that record and escalates automated checks must pass — no exceptions detected breakage becomes the next proposal — never a direct write
The loop only closes through stage 02. Anything that wants to change production — a person, an agent, an automated fix — enters at 01 and passes the same checks.

When the nightly build fails, the agent reads the failure, works out what broke, and drafts candidate fixes. Not a Slack message describing the problem — actual pull requests, often several competing options for the same break.

Those pull requests then face exactly the gates a human’s would. A compile check pinned to the same engine version production runs. A contract audit that fails the build if a schema change would break a downstream dashboard nobody remembered existed. A security review. Merge one, and automation closes the losing siblings; merge none, and a janitor sweeps them after two weeks.

The agent is fast, tireless, and occasionally confidently wrong. The gate does not care which, because the gate does not evaluate intent. It evaluates the diff.

Three decisions that made it work

None of these are glamorous. All three are the difference between a system that catches problems and one that merely contains the machinery for catching problems.

  1. Tests are sensors, not gates — and a warning nobody reads is worth zero

    Every data test in the platform runs at warning severity, deliberately and permanently. Nothing may block the nightly refresh. If a test could halt the build, one bad assertion on a Friday means the revenue team opens Monday with no numbers at all — a cure considerably worse than the disease.

    But that creates an obvious hole. A warning that fires into a log file nobody opens is indistinguishable from a passing test. The fix is not to make the tests blocking. It is to give the warnings somewhere durable to land: the tests that matter write their failing rows into a dedicated store, and a scheduled job reads that store every morning and escalates to a human when it is not empty.

    Sensors that nothing reads are just expensive decoration. The reader is the feature.

  2. The failure store doubles as the inventory of what is monitored

    This is the subtle one, and it is the failure mode most monitoring never catches.

    It is easy to detect a test that fails. It is much harder to detect a test that silently stopped running — deleted in a refactor, renamed, quietly disabled. Nothing fires. The dashboard stays green. You have lost coverage and gained confidence, which is the worst possible trade.

    So the morning job runs two checks, not one. It iterates every table in the failure store and escalates on any that has rows — meaning a newly added test is picked up automatically, with no list to maintain. Then it separately asserts that the set of tables matches the set it expects, as an equality. A missing table means a test disappeared. An unexpected one means a rename left a stale table behind, whose old rows would otherwise look like a live failure forever.

    An earlier version of this used a hardcoded list of test names. It drifted twice — someone added a test without updating the list, then someone else did it again. The same class of silent gap the tests existed to catch, reproduced inside the monitoring itself.

  3. The pipeline heals itself before anyone notices

    Scheduled jobs get suspended. A transient upstream failure, a dropped column in a vendor feed, a permissions change — and the chain stops. If recovery depends on a human noticing, the recovery time is however long it takes someone to look, which over a holiday weekend is days.

    An hourly guardrail checks the state of every job in the build chain, resumes anything suspended in child-to-parent order, and if the root job was the one suspended, triggers an immediate run rather than waiting for the next scheduled tick. It emails only when it actually found something wrong.

    An earlier version of this guardrail failed to recover production for three days. It read job state from a source where suspended jobs do not appear at all — so suspension, the exact condition it existed to detect, was undetectable by construction. Worth checking that your own monitoring can observe the state it claims to watch.

The pattern underneath all three

Every one of these is the same move: make the failure legible to a machine, then put a machine in front of it. Warnings become rows in a table. Coverage becomes a set comparison. Job health becomes an hourly query. None of it requires AI — and all of it is what makes adding AI safe rather than reckless.

Why the asymmetry is the whole design

There is a version of this architecture where the agent writes directly to the warehouse. It is faster. It demos beautifully. It also means that the moment the agent is wrong — and it will be wrong, because the interesting failures are the ones nobody anticipated — the wrongness lands in production with no review, no diff, and no record of what changed.

Routing the agent through the same pull request queue as a human costs you latency. What it buys:

  • Every automated change is reviewable as a diff, by a person, before it lands.
  • Every automated change is revertible, because it is a commit like any other.
  • The agent's proposals face the contract audit, so a fix that would break a downstream consumer fails the same way a human's would.
  • You get an audit trail for free — which matters more than teams expect the first time someone asks why a number moved.
  • You can let the agent be aggressive. When merge is impossible, a wrong proposal costs a review, not an incident.

That last point is the one people miss. The constraint is not a limit on what the AI can do — it is what lets you turn the AI up. Give an agent write access and you will spend the rest of the year making it cautious. Give it a gate it cannot cross and you can let it try things.

What this means if you are earlier than this

Most teams asking how to get AI into their revenue operations do not need an agent yet. They need the substrate that makes an agent useful. In rough order:

  • Know what depends on what. If you cannot answer “what breaks if I change this column” without asking three people, an agent cannot answer it either. Dependency awareness is the single highest-leverage thing to build first.
  • Give your tests somewhere to write. Test results that exist only in a build log are invisible to automation. Land them somewhere queryable.
  • Make one alert that a real person actually receives — and confirm they receive it. Alerting that routes to an unmonitored inbox is worse than none, because it feels like coverage.
  • Put a gate in front of production before you put anything clever behind it.

Do those four and the agent becomes almost an implementation detail. Skip them, and you have given a very fast, very confident assistant unsupervised access to the numbers your board sees.

Give an agent a well-instrumented pipeline and it compounds. Give it a pile of undocumented tables and it will generate nonsense at scale — faster than your team can catch it.

The gap between those two outcomes has almost nothing to do with which model you pick. It is contract tests, readable failure stores, self-healing schedules, and a review gate with no bypass. Boring infrastructure, and it is the entire ballgame.

Want to talk through what this would look like on your stack?

We help GTM and RevOps teams work out where AI genuinely fits in their data operation — and, just as usefully, where it does not fit yet. Whether that is an audit of what you already have, or building the guardrails before you add the agent, the first conversation is free and specific to your setup.

Bottom Line Studio AI — architecture and operations for GTM data teams.
This post describes an architectural pattern. Implementation details, system names and identifying specifics have been generalised.