Docs
Open Babbit

Get started

What's in the box?

Agents write code faster than anyone can review it, so Babbit doesn't ask you to read the code. It cuts the code into boxes, checks every call at a box's edges, and when a run fails, it names one box.

Open one up

A box is a function, an API handler or a database table, with three things attached:

PartWhat it holdsFor a cart total
ContractWhat goes in, what comes out, and the shape of each.A cart id in; a total in cents, zero or more, out.
OwnerThe goal or scenario the box exists for.The goal Checkout charges what the cart shows.
RecordIts crossings: every call that went in or came out.Each call, counted and checked against the contract.
What's in a box The cart total box takes a cart id and returns a total in cents. Inside it are three things: its contract (a cart id in, a total in cents of zero or more out), its owner (the goal: charge what the cart shows) and its record (every crossing, counted and checked). Every call is checked against the contract at both edges of the box. In cart id cart total box Contractcart id → total in cents, ≥ 0 Ownergoal: charge what the cart shows Recordeach crossing, counted and checked Out 1840 Every call is checked against the contract at both edges.
A box shows its edges and hides its insides. Every call is checked at both edges.

That's the whole box. It doesn't describe how it works inside, and you don't need it to. You need what it promised, who it promised it to, and whether it kept the promise.

Why Babbit uses boxes

The usual check on agent-written code is a person reading the diff. A diff shows what changed, not whether the product still works, and the diffs get longer as agents get faster. Babbit moves the check from the code to the edges of each box, where it runs on every call without anyone reading anything.

The boxes give you three things that reading the code doesn't:

  • Blame you can act on. When a run fails, Babbit names one box, not a stack trace.
  • Fixes that stay in place. A fix may touch only the boxes its explanation named. A pull request that wanders into other code is refused.
  • A map that matches the code. The Architecture map is drawn from the boxes themselves, not from a document an agent was asked to keep up to date.

Outside boxes

An outbound client, such as an HTTP client or a vendor's SDK, is a box of its own, marked outside. When a vendor's API breaks, Babbit blames the outside box, not your code.

Legacy code

Code from before Babbit is listed in the map as legacy. It's visible on the map, the shape rules don't apply to it, and Babbit doesn't trace it box by box. It stays legacy until a change rewrites it into boxes.

Code written for a project Babbit hosts is in boxes from the start. The Code Writing agent declares each box in the repository's map with its owner and kind. The call that records a box's crossings is generated, never written by hand.

Runs

Every run leaves one trace, however many services it crosses. A run is any of these:

  • A person's action, such as a click that saves a form.
  • A request that no action made, such as a webhook.
  • A job, such as a deploy or a test run.

The trace starts where the run starts, often in the browser, and its id travels with every call: into every service, every agent workspace and every MCP tool call. The boxes a request crossed in five services read as one path, with each box under the box that called it.

What a trace keeps

Every crossing is counted and checked against its contract on every tier. The tiers differ in which crossings keep their values:

TierValues kept
dev and preprodEvery crossing.
prodEvery crossing that broke its contract, and one in a hundred of the rest. The others are counted and checked, and keep no values.

A field the contract marks as a person's data, such as a message, is kept as its shape, ‹string 41›, never its value. Traces never go into Git. Preprod traces are kept for 14 days and prod traces for 30; the counts on each box stay after the trace is gone. One request deletes a person's data from every tier.

Blame

When a run fails, many boxes fail with it. Babbit blames one: the deepest box that broke its contract while every box it called held.

How a run blames one box A request enters the checkout handler, which calls the cart total and the payment client. The cart total calls the price lookup. The price lookup kept its contract; the cart total broke its contract. The cart total is blamed because it is the deepest box that broke while every box it called held. The checkout handler also failed, but only because of the cart total. checkout handlerfailed cart totalbroke price lookupheld payment clientoutside Blamed: cart total The deepest box that broke its contract while every box it called held.
The checkout handler failed, but only because the cart total broke. The price lookup it called held, so the cart total is blamed.

Blame ends one of three ways:

  1. One box broke its contract. The fix goes in that box.
  2. No box broke its contract, yet the result was wrong. A contract is too loose. The fix tightens the contract first and records the failing case as a scenario.
  3. The break is outside your product, in an outside box such as a vendor's API. The change says so and stops.

Fixes stay in their box

A fix may touch only the boxes its explanation named. If a fix for the cart total also changes the checkout handler, Babbit's newdev/shape check refuses the pull request and names the box. After the fix, the scenarios of everything that calls the box run again, to prove they still hold.

What a box can't tell you

A box checks a boundary. It doesn't check that the product does what someone asked for. Every contract in a run can hold while the result is still wrong, which is the second way blame can end.

That's what scenarios are for. A scenario's test checks a behavior you approved, at the exact commit that will ship. Babbit runs both checks, and neither replaces the other. See Evidence and verification.

Where you see boxes

  • Events lists every run your project kept, newest first, named for the action that started it.
  • Run draws one run as a sequence diagram, with a lifeline per part of your product, the blamed call marked, and each call's values one click away.
  • Architecture is one map of your whole project, from features down to boxes.

To use them, see Investigate a run.

The shape

Babbit keeps every codebase it runs in one standard layout, called the shape, so its tools work on one kind of code:

  1. All code is in boxes, and each outbound client is a box marked outside.
  2. Every box has a contract and an owner.
  3. One map, written with the code, says which boxes each scenario uses.
  4. Files stay under a size limit, names follow one convention, and styles come from design tokens.
  5. The recording call is generated and checks the box's contract on every tier.
  6. A fix stays in the boxes its explanation named.
  7. A change adds no workflow file and no secret, and keeps the release scripts the map needs.

The newdev/shape check enforces these rules on each pull request head. It reads only the boxes a pull request touches, and a failure names the rule and where it broke.