{"slug": "a-spreadsheet-will-accept-a-wrong-number-politely-verifying-what-an-ai-agent", "title": "A spreadsheet will accept a wrong number politely: verifying what an AI agent writes into Excel", "summary": "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.", "body_md": "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.\n\nA 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.\n\nSo 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.\n\nThree properties make a spreadsheet harder to supervise than a document or an inbox.\n\n**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.\n\n**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.\n\n**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.\n\nAn agent that checks its own write response will report success in every one of them.\n\nBefore asking whether an agent can be trusted with a workbook, the edit itself has to be describable in four ways.\n\nThe fourth is the one that separates a working integration from a demo. The others can be argued about; the read-back is testable.\n\nThe record I want after every unattended write has five fields, and it is deliberately boring:\n\n```\n{\n  \"target\": \"Sheet1!tbl_orders[amount]|row=invoice:INV-2291\",\n  \"intent\": {\"field\": \"amount\", \"value\": 184000, \"as\": \"KRW\"},\n  \"before\": {\"file_sha256\": \"9f2c…\", \"snapshot_at\": \"2026-11-15T04:10:22Z\"},\n  \"touched\": {\"range\": \"F118\", \"cells\": 1},\n  \"after\": {\"recalculated\": true, \"readback\": 184000, \"format\": \"#,##0\", \"total_check\": {\"cell\": \"F240\", \"was\": 9982000, \"now\": 10166000, \"delta_ok\": true}},\n  \"used_range\": {\"before\": \"A1:J240\", \"after\": \"A1:J240\", \"shifted\": false}\n}\n```\n\n`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.\n\n`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.\n\nWhere 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:\n\n`$B$2:B10` by dragging is a different operation from writing `=$B$2:B11`, and one of them silently changes what the column means.\nA 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.\n\nSorting, 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.\n\nThey 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.\n\nA 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.\n\nThe allow-list is narrow and boring, and that is the point:\n\nAnd the never list:\n\nThe most useful trick I have found is to stop describing the boundary in instructions and write it into the file.\n\nProtect 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.\n\nThe 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.\n\nA minimal version in openpyxl looks like this:\n\n``` python\nfrom openpyxl import load_workbook\nfrom openpyxl.worksheet.table import Table\nimport hashlib, json, datetime\n\ndef snapshot(path):\n    return {\"file\": path,\n            \"sha256\": hashlib.sha256(open(path, \"rb\").read()).hexdigest(),\n            \"at\": datetime.datetime.utcnow().isoformat() + \"Z\"}\n\nwb = load_workbook(\"orders.xlsx\")\nws = wb[\"입력\"]\n\n# 1. resolve a NAME, never coordinates\nref = wb.defined_names[\"input_amount\"]          # e.g. 입력!$F$2:$F$500\ntarget = next(ref.destinations)                  # (sheet, range)\n\n# 2. refuse if the cell is a formula\ncell = ws[\"F118\"]\nif isinstance(cell.value, str) and cell.value.startswith(\"=\"):\n    raise RuntimeError(\"formula cell — needs overwrite_formula with a reason\")\n\n# 3. write, then confirm the file's own protection is on\nws[\"F118\"] = 184000\nws.protection.sheet = True\nwb.calculation.fullCalcOnLoad = True             # force a recalc on open\nwb.save(\"orders.xlsx\")\n```\n\nThe `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.\n\nVerification should climb, not jump. Each rung catches a class of error the one below it misses:\n\nMost 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.\n\nIf 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.\n\nIf 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:\n\n*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.", "url": "https://wpnews.pro/news/a-spreadsheet-will-accept-a-wrong-number-politely-verifying-what-an-ai-agent", "canonical_source": "https://dev.to/maptosite/a-spreadsheet-will-accept-a-wrong-number-politely-verifying-what-an-ai-agent-writes-into-excel-2cgf", "published_at": "2026-11-14 20:36:20+00:00", "updated_at": "2026-11-14 20:51:09.514624+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "ai-safety", "developer-tools"], "entities": ["Excel", "Google Sheets"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/a-spreadsheet-will-accept-a-wrong-number-politely-verifying-what-an-ai-agent", "markdown": "https://wpnews.pro/news/a-spreadsheet-will-accept-a-wrong-number-politely-verifying-what-an-ai-agent.md", "text": "https://wpnews.pro/news/a-spreadsheet-will-accept-a-wrong-number-politely-verifying-what-an-ai-agent.txt", "jsonld": "https://wpnews.pro/news/a-spreadsheet-will-accept-a-wrong-number-politely-verifying-what-an-ai-agent.jsonld"}}