All docs
Examples
Hosted workflow

Branch diff review for data cleanup

Run agent cleanup on a branch, inspect the diff, and merge only reviewed changes.

Problem

Data cleanup agents need to try changes without corrupting production state.

Why app glue gets messy

Ad hoc temp tables and app-side staging make it hard to prove what changed.

How Synapsor helps

Synapsor branches make proposed table changes inspectable before merge.

Value sources

Example names and seed ids are developer-defined. SESSION values are set by your backend. ARG values come from the SDK/HTTP call. Handles such as wrp://..., evidence://..., and agent-run://... are returned by Synapsor and should be stored for audit/replay.

Read the value-source guide
Expected outcome

The app shows a branch diff and merges only after policy checks pass.

Production checks

  • Cleanup writes happen off main until merge.
  • Diff output is visible before merge.
  • Reviewer can drop the branch to abandon changes.
  • Hosted database-scoped keys prevent switching branches from the public API.
schema.sql
CREATE TABLE customers (
  id INT PRIMARY KEY,
  tenant_id VARCHAR NOT NULL,
  email VARCHAR NOT NULL,
  lifecycle VARCHAR NOT NULL
);
agent.ddl.sql
CREATE AGENT WORKFLOW cleanup.customer_lifecycle_cleanup_flow
SESSION REQUIRE tenant_id, principal, current_customer_id
ALLOWED CAPABILITIES (
  cleanup.propose_lifecycle_change
)
EVIDENCE REQUIRED
AUTO BRANCH ON PROPOSAL
CHECKPOINT EVERY STEP
ON RISK medium REQUIRE APPROVAL ROLE 'data_steward';

CREATE AGENT CONTEXT cleanup.customer_context
ROOT customers AS customer
LOOKUP customer.id = SESSION current_customer_id
BIND tenant_id FROM SESSION tenant_id
BIND principal FROM SESSION principal
OUTPUT SLOTS
  customer_id AS customer.id,
  email AS customer.email,
  lifecycle AS customer.lifecycle
EVIDENCE ON;

CREATE AGENT CAPABILITY cleanup.propose_lifecycle_change
DESCRIPTION 'Stage a customer lifecycle cleanup change on an agent branch'
ARG customer_id INT64 REQUIRED
ARG lifecycle VARCHAR REQUIRED
ARG reason VARCHAR REQUIRED
HIDDEN tenant_id FROM SESSION tenant_id
HIDDEN principal FROM SESSION principal
HIDDEN current_customer_id FROM SESSION current_customer_id
USE CONTEXT cleanup.customer_context
EXECUTION PROPOSAL
RETURNS JSON '{"type":"object","properties":{"proposal":{},"branch":{},"evidence_bundle":{}}}'
PROFILE MINIMAL
INLINE EVIDENCE handles_only
WRITE PROPOSAL TARGET customers
OPERATION UPDATE
LOOKUP id FROM ARG customer_id
TENANT tenant_id FROM BINDING tenant_id
COLUMNS lifecycle FROM ARG lifecycle
AUDIT cleanup_audit
SUMMARY TEMPLATE 'Propose lifecycle cleanup for customer {customer_id}';
python
run = db.agent_runs.start(
    workflow="cleanup.customer_lifecycle_cleanup_flow",
    input={"customer_id": 42, "target_lifecycle": "inactive"},
)

proposal = run.invoke_capability(
    "cleanup.propose_lifecycle_change",
    step_key="propose_lifecycle_change",
    arguments={"customer_id": 42, "lifecycle": "inactive", "reason": "invalid trial email"},
    mode="propose_only",
    auto_branch=True,
    response_envelope=True,
)

diff = db.diff_branch(proposal["branch"]["branch_id"], "main")
print(diff)