cd /news/ai-agents/a-spreadsheet-will-accept-a-wrong-nu… · home › topics › ai-agents › article
[ARTICLE · art-169718] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=· neutral

A spreadsheet will accept a wrong number politely: verifying what an AI agent writes into Excel

A developer outlined a verification model for AI agents that write into spreadsheets, arguing that a successful write call proves little because cells are positional addresses, formulas are programs, and formats coerce values silently. The approach requires each unattended write to produce a structured record with target, intent, before-state hash, touched range, and an after-state read-back including a total-check cell whose movement confirms the change was correct. The developer also recommends a write adapter that refuses to overwrite formula cells unless the request explicitly sets an overwrite_formula flag with a stated reason.

by read6 min views4 publishedNov 14, 2026

The question people ask about an agent in a spreadsheet is usually about the model: can it read the sheet, can it write the right value. The risk is not there. It is in the container.

A cell in Excel or Sheets is not a named thing. It is an address. D14 means "the fourteenth row", and the moment anyone inserts a row above it, that address points at a different record. A formula is not a value either; it is a small program that happens to display a number. And a number is not a type; it is whatever the sheet decided to store after the number format, the locale and the column's history had their say.

So an agent that writes "successfully" into a spreadsheet has proven almost nothing. What follows is the verification model I actually use when the thing being edited is a workbook someone depends on for money.

Three properties make a spreadsheet harder to supervise than a document or an inbox.

It is positional. An agent that reasons in rows and columns and a person who reasons in headers and meanings can both be correct about "the third row" and disagree about which record that is once anything above it changes. Merged cells, hidden rows and grouped columns widen the gap: the sheet the agent parsed and the sheet the human sees can genuinely differ, and neither view is wrong.

It holds programs. A value written over a formula does not look wrong. It looks like a number. The workbook silently stops being a model and becomes a snapshot, and nobody notices until next month's figures are quietly missing their inputs.

It coerces silently. Writing into a cell succeeds even when the cell's format turns the value into text, when the locale expects a comma as the decimal separator, when a leading zero is dropped from an identifier, or when a date string is stored as something else entirely. The write call returns OK in all of those cases. The data is now wrong.

An agent that checks its own write response will report success in every one of them.

Before asking whether an agent can be trusted with a workbook, the edit itself has to be describable in four ways.

The fourth is the one that separates a working integration from a demo. The others can be argued about; the read-back is testable.

The record I want after every unattended write has five fields, and it is deliberately boring:

{
  "target": "Sheet1!tbl_orders[amount]|row=invoice:INV-2291",
  "intent": {"field": "amount", "value": 184000, "as": "KRW"},
  "before": {"file_sha256": "9f2c…", "snapshot_at": "2026-11-15T04:10:22Z"},
  "touched": {"range": "F118", "cells": 1},
  "after": {"recalculated": true, "readback": 184000, "format": "#,##0", "total_check": {"cell": "F240", "was": 9982000, "now": 10166000, "delta_ok": true}},
  "used_range": {"before": "A1:J240", "after": "A1:J240", "shifted": false}
}

touched is the range the agent actually wrote, not the range it meant to write. Those two differ more often than anyone expects — a fill that spilled one row too far, an append that landed on a header — and the difference is invisible in a "write succeeded" log.

total_check is the cell that would move if the change were right. If a total does not move the way the intent predicted, the write is wrong even though it succeeded.

Where a value write is merely risky, writing near formulas is where the expensive mistakes live. Four rules have held up in every case I have seen:

$B$2:B10 by dragging is a different operation from writing =$B$2:B11, and one of them silently changes what the column means. A practical consequence: the agent's write adapter should refuse to touch a cell whose type is formula unless the request carries an explicit overwrite_formula: true with a reason. That is a permission model, not a prompt.

Sorting, filtering and then saving; find-and-replace across a sheet; remove-duplicates; re-saving as CSV. None of these produce a cell-level diff anyone will read, and every one of them can move data across rows or strip formulas, leading zeros and date formats.

They are also the operations an agent is most likely to reach for, because they are the ones a person asks for in a sentence ("clean up the duplicates"). A safe implementation treats them as structural changes requiring a snapshot and a post-check on row identity — not as a series of writes.

A shared workbook, where another person has the file open, is the same class of problem with a shorter fuse: a write can be overwritten by the other editor's save, and no error is raised.

The allow-list is narrow and boring, and that is the point:

And the never list:

The most useful trick I have found is to stop describing the boundary in instructions and write it into the file.

Protect the formula and report columns. Leave the input columns unlocked. Mark the append region as a real table, not a range with a bold header. Give the agent a named range to write into, and leave data validation on it so a wrong type is rejected by the file rather than by the model's judgement.

The boundary then becomes enforceable by the container, auditable by anyone who opens the workbook, and independent of which agent, prompt or person is on the account that day. Trust stops being a claim about the model and becomes a property of the thing it is allowed to touch.

A minimal version in openpyxl looks like this:

from openpyxl import load_workbook
from openpyxl.worksheet.table import Table
import hashlib, json, datetime

def snapshot(path):
    return {"file": path,
            "sha256": hashlib.sha256(open(path, "rb").read()).hexdigest(),
            "at": datetime.datetime.utcnow().isoformat() + "Z"}

wb = load_workbook("orders.xlsx")
ws = wb["입력"]

ref = wb.defined_names["input_amount"]          # e.g. 입력!$F$2:$F$500
target = next(ref.destinations)                  # (sheet, range)

cell = ws["F118"]
if isinstance(cell.value, str) and cell.value.startswith("="):
    raise RuntimeError("formula cell — needs overwrite_formula with a reason")

ws["F118"] = 184000
ws.protection.sheet = True
wb.calculation.fullCalcOnLoad = True             # force a recalc on open
wb.save("orders.xlsx")

The fullCalcOnLoad line matters more than it looks. Without a recalculation, the number a human opens tomorrow may still be the cached one from yesterday, and the read-back you performed earlier proved the wrong file state.

Verification should climb, not jump. Each rung catches a class of error the one below it misses:

Most agent integrations stop at rung 1 or 2 and then report confidence. The expensive failures live at rung 3 and above, and they are exactly the ones a demo never shows, because a demo is one write into a workbook nobody else uses.

If you want the short version: a spreadsheet will always accept a wrong number politely. The only thing that makes an agent safe here is a named target, a copy you can go back to, and a read-back that proves the result rather than the attempt. Only the last one is new. It is also the one that matters.

If you want to see how the same "prove the result, not the attempt" idea applies outside a workbook — what an assistant can and cannot do on a phone, and where a daily usage limit sits in that model — I keep two public notes:

Disclosure: I use Pickle, a phone-side AI assistant app, and I am not its vendor. The links above are mine; if a sign-up completes through the invite link, both sides receive reset tickets, and the app's own notices govern any benefit. Nothing in this article is a paid placement, and the verification model described here is what I run on my own workbooks.

── more in #ai-agents 4 stories · sorted by recency
── more on @excel 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/a-spreadsheet-will-a…] indexed:0 read:6min 2026-11-14 · —