Source says 41,209 orders; the warehouse says 41,187. Somebody notices during month-end close, three weeks late.
A reconciliation agent flips that: a scheduled job compares source and warehouse aggregates daily, and when they drift, an LLM explains the drift in context — which segments, since when, correlated with which pipeline events — and files a ticket with evidence attached. The critical design decision is the division of labor: deterministic SQL detects, the LLM only explains, and every number in the ticket comes from the queries, not the model.
Use this for source-to-warehouse pairs where silent drift has real cost — billing and finance tables, regulatory reporting feeds, CDC-replicated operational tables — and where today's detection method is "someone eventually notices."
Triggers:
Define the comparison contract per table pair. Key metrics (row counts, sums of critical measures, max timestamps), the comparison grain (daily by business date, plus 2–3 segment dimensions), the lag allowance (replication delay that is normal), and exact-match vs explained-tolerance per metric. Write this as config, not code — the agent should take on new tables by config entry.
Build the deterministic detection layer first — no LLM yet. A scheduled task (Airflow, Dagster, or plain cron) runs paired aggregate queries and lands results in a reconciliation table:
-- executed against each system, results landed side by side
SELECT business_date, region,
COUNT(*) AS row_count,
SUM(amount) AS total_amount,
MAX(updated_at) AS max_updated
FROM orders
WHERE business_date >= CURRENT_DATE - INTERVAL 7 DAY
GROUP BY business_date, region;
A pure-SQL check then flags any cell where the systems disagree beyond the contract. Run this alone for a few days: if detection is noisy or wrong, an LLM on top will be confidently noisy and wrong.
Add the LLM explanation stage with structured output. When drift is flagged, the agent assembles context — the drifted cells, 30 days of drift history for the pair, and recent pipeline events (DAG runs, deploys) — and requests a structured explanation:
from anthropic import Anthropic
from pydantic import BaseModel
class Hypothesis(BaseModel):
cause: str
mechanism: str
confirming_query: str
confidence: str # "high" | "medium" | "low"
class DriftExplanation(BaseModel):
summary: str
affected_scope: str # segments/dates, from the evidence
started_at: str # first drifted business_date
hypotheses: list[Hypothesis] # ranked
severity: str # "page" | "ticket" | "log"
client = Anthropic()
response = client.messages.parse(
model="claude-opus-4-8",
max_tokens=2000,
thinking={"type": "adaptive"},
messages=[{
"role": "user",
"content": (
"You are explaining a data reconciliation drift. Use ONLY "
"the evidence provided; every number you cite must appear "
"in it. Rank hypotheses; each needs one confirming SQL "
"query.\n\nDrifted cells:\n" + drift_json +
"\n\nDrift history (30d):\n" + history_json +
"\n\nPipeline events (72h):\n" + events_json
),
}],
output_format=DriftExplanation,
)
explanation = response.parsed_output
Verify the explanation before it ships — inside the agent. Two automated gates, run inline: every numeric claim in summary and affected_scope is checked against the drift table (a regex-extracted-numbers-must-exist-in-evidence check is crude and effective), and each hypothesis's confirming_query is validated as read-only and syntactically runnable. Optionally the agent executes the top hypothesis's confirming query (read-only role, row limit) and attaches the result. Explanations failing the gates ship as raw drift data with a "no verified explanation" note — degraded output beats fabricated output.
File the ticket with evidence attached. The ticket body: contract violated, drifted cells table, drift-since date, the verified explanation, and the confirming queries ready to run. Severity routes per the contract (finance pair drifting = page; low-stakes pair = weekly digest). The agent never fixes anything — reconciliation agents that auto-repair are how small drifts become large ones with no audit trail.
Tune on a burn-in period. Two weeks of shadow operation: every flag reviewed by a human, verdicts recorded (real/noise), lag allowances and tolerances adjusted from the verdict log. Only then does it page anyone. Revisit quarterly with the same verdict-replay method.
The agent's credibility budget is spent in its first month. A burn-in period that eliminates false alarms before anyone gets paged is the difference between a trusted teammate and a muted channel.
Reconciliation evidence is aggregate by construction — counts and sums by date and segment — which makes this agent unusually easy to run client-safe: keep detection entirely in-warehouse, and route the explanation stage through Bedrock or Azure OpenAI provisioned in the client's tenancy so evidence packs never cross the boundary; a local Ollama model can serve the explainer for lower-stakes pairs. Ensure segment dimensions in the contract are non-identifying (region, product line — never customer-level), scrub free-text pipeline-event descriptions before they enter the evidence pack, and file tickets in the client's own tracker under their access controls.