Branching — git for data
Branching is how an agent writes safely: its changes land on a zero-copy branch that a human reviews and merges, never on live data directly.
A branch is a zero-copy clone of a database that remembers its merge base (every table's version at branch time). Nothing is copied — a branch of a terabyte database is a metadata write.
CREATE BRANCH DEV FROM DATABASE DEMO; -- instant
USE DATABASE DEV; -- work freely: DML, new tables, models
SELECT * FROM TABLE(DATA_DIFF('DEMO.S.ORDERS', 'DEV.S.ORDERS'));
-- ID | V | DIFF$ACTION
-- 1 | a | REMOVED <- updated row: old value out...
-- 1 | aa | ADDED <- ...new value in
-- 3 | c | ADDED <- inserted on the branch
SHOW BRANCHES; -- changed / behind / conflicts per branch
MERGE BRANCH DEV INTO DEMO; -- fast-forward the changed tables
DROP DATABASE DEV; -- when done (or keep branching)
Agent sessions
This is what branching is built for. Every Obi conversation runs inside an agent session: the agent proposes writes, you review the diff, you merge. Main is never touched until you say so.
- - The conversation's first data-modifying statement automatically creates a
zero-copy branch of the target database (DB__AGENT_xxxxxx). From then on every statement the agent runs — reads included — is transparently redirected to the branch. The agent sees its own changes; main is untouched.
- - Every statement's estimated credits are charged to the session's budget
(default 25; set OBI_BUDGET_CREDITS to change it). When the budget is spent, execution is refused.
- - The Agents tab lists every session: agent, spend against budget,
statement count, state, and — once the agent has written — its branch, with diff / merge / discard buttons. Merging fast-forwards the source database; discarding drops the branch. SHOW AGENT SESSIONS gives the same audit trail in SQL.
Governance statements (GRANT, CREATE ROLE/USER/WAREHOUSE, ALTER SESSION) are never redirected to a branch — they apply, governed by RBAC as always.
The review-and-merge gate is a data-plane guarantee, not a convention the agent has to honor. See Agent sessions and The guarantees.
Merge semantics
Three-way per table, against the recorded base:
| Situation | Result |
|---|---|
| changed only on the branch | main fast-forwards to the branch's file set (zero-copy) |
| changed only on main | main kept — the branch was stale there |
| changed on both | conflict — merge aborts listing the tables, nothing moves |
| table created on the branch | created in main (zero-copy clone) |
After a successful merge the branch's base refreshes, so you can keep working on it and merge again.
DATA_DIFF
TABLE(DATA_DIFF('A.S.T', 'B.S.T')) works between any two tables with matching columns — branches, clones, backups. It's a multiset diff computed from the immutable file sets, so rows merely rewritten by copy-on-write DML cancel out and only real changes appear. This is the diff a human reads before merging an agent's branch.
Why this matters
Zero-copy clones without a merge drift forever. Branch + diff + merge turns the versioned-file spine into a real pull-request workflow for data: branch, transform (obelisk build into the branch), test (obelisk ci), inspect the diff, merge. That same workflow is what makes an autonomous agent safe to run — its writes are staged, reviewable, and reversible by construction.