Untouched parts drifted
0
WolfXL rewrote 0 untouched parts on a single-cell save. Headless LibreOffice rewrote 8 to 151.
Technical Study · Runtime Boundaries
The conversation right now is almost entirely about agent reasoning models: can the model plan financial models, audit revenue, or write Python? Nobody asks what happens when the agent actually saves the file.
Evaluating an AI agent on how well it formulates formulas or generates Python code misses the critical failure boundary. In production agent workflows, the primary point of failure is the file runtime.
When an agent needs to read, recalculate, or update a workbook, developers face three flawed compromises:
01 · Headless LibreOffice
Spawns a 410 MB desktop suite inside the container. Requires user-profile workarounds, emits noisy stderr on clean exits, and re-serializes the entire ZIP package on every save.
02 · openpyxl DOM rebuild
Deserializes the workbook into a heavy in-memory Python DOM. On save, it strips or alters charts, pivot tables, macros, and relationship graphs.
03 · XlsxWriter
Fast and reliable for greenfield creation, but strictly write-only. It cannot open, read, or edit an existing corporate spreadsheet template.
To edit a single cell, containerized agent harnesses resort to the first option: headless LibreOffice.1 Here is what happens next:
Untouched parts drifted
0
WolfXL rewrote 0 untouched parts on a single-cell save. Headless LibreOffice rewrote 8 to 151.
16-vCPU Linux sweep
12-0
WolfXL swept every registered task row: bulk CSV, roundtrip save, and PDF export.
200k roundtrip save
15.94x
0.424 s with WolfXL versus 6.753 s with headless LibreOffice on the same 200,000-row fixture.
An Excel workbook (.xlsx or .xlsm) is an Open Packaging Conventions (OPC) zip archive containing dozens of interconnected XML parts: worksheet data, shared string tables, styles, themes, drawing relationships, chart definitions, and pivot caches.
Now consider this: when an agent updates cell B2, only cell B2 changes. Styles tables, drawing relationship trees, and theme palettes remain untouched: a surgical patch directly into the ZIP archive.
We tested what happens when an agent modifies a single cell across five real-world spreadsheet fixtures:
Here is the same workbook, saved twice. The only requested change in both runs was cell B2, which lives in xl/worksheets/sheet1.xml:
Representative part set from the preservation receipts. Amber M = the part containing the edited cell. Rose M = an untouched part rewritten anyway. Dotted = byte-identical. Across the five-fixture study the unrelated-part count ranged from 8 to 151.
The observation: On a single-cell save, headless LibreOffice rewrote between 8 and 151 untouched internal parts across the fixtures.2 It re-serialized XML trees, dropped non-standard namespaces, reordered style index tables, and rebuilt drawing relationship graphs.
Even though cell B2 has no drawing or chart attached, LibreOffice parses and re-serializes xl/drawings/drawing1.xml and xl/styles.xml, rewriting namespace prefixes and reordering relationship IDs:
@@ -1,12 +1,10 @@ - <xdr:wsDr xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" - xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" - xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"> + <xdr:wsDr xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"> <xdr:twoCellAnchor editAs="oneCell"> - <xdr:from><xdr:col>4</xdr:col><xdr:colOff>0</xdr:colOff><xdr:row>2</xdr:row><xdr:rowOff>0</xdr:rowOff></xdr:from> - <xdr:to><xdr:col>9</xdr:col><xdr:colOff>12700</xdr:colOff><xdr:row>16</xdr:row><xdr:rowOff>50800</xdr:rowOff></xdr:to> - <xdr:graphicFrame macro=""> - <xdr:nvGraphicFramePr><xdr:cNvPr id="2" name="Chart 1"/><xdr:cNvGraphicFramePr/></xdr:nvGraphicFramePr> - <a:graphic><a:graphicData uri=".../chart"><c:chart xmlns:c="..." r:id="rId2"/></a:graphicData></a:graphic> + <xdr:from><xdr:col>4</xdr:col><xdr:row>2</xdr:row></xdr:from> + <xdr:to><xdr:col>9</xdr:col><xdr:row>16</xdr:row></xdr:to> + <xdr:graphicFrame> + <xdr:nvGraphicFramePr><xdr:cNvPr id="1" name="Object 1"/></xdr:nvGraphicFramePr> + <a:graphic><a:graphicData uri=".../chart"><c:chart xmlns:r="..." r:id="rId1"/></a:graphicData></a:graphic> </xdr:twoCellAnchor>
WolfXL patches the specific byte range of the target cell in xl/worksheets/sheet1.xml. Every other part in the zip container remains byte-for-byte untouched:
@@ -14,5 +14,5 @@ <row r="2" spans="1:4"> <c r="A2" t="s"><v>0</v></c> - <c r="B2"><v>1000000</v></c> + <c r="B2"><v>1250000</v></c> <c r="C2" s="1"><f>B2*0.2</f><v>200000</v></c> </row> # 0 other files modified (styles, drawings, themes, and relations unchanged)
Spawning a 410 MB desktop suite inside an agent container also carries substantial execution latency. We benchmarked WolfXL 2.1.0 against LibreOffice 24.2.7.2 on a dedicated 16-vCPU x86_64 Linux system using a 200,000 row by 8 column dataset across 12 registered task routes.3
200k-row CSV extract
5.25x faster
200k-row roundtrip save
15.94x faster
PDF export
2.84x faster
Small-file CSV extract
3.82x faster
Recalculate and extract
3.26x faster
Bars normalized per row against the slower engine; seconds printed. Full matrix below.
| Registered task | WolfXL median | LibreOffice median | Observed ratio | Scope |
|---|---|---|---|---|
| 200k CSV extraction | 1.545 s | 8.114 s | 5.25x faster | 200,000 × 8 fixture |
| 200k roundtrip save | 0.424 s | 6.753 s | 15.94x faster | 200,000 × 8 fixture |
| PDF export | 0.434 s | 1.230 s | 2.84x faster | Renderable styled fixture |
| Small-file CSV extract | 0.225 s | 0.860 s | 3.82x faster | 1,000 × 8 fixture |
| Formula recalculation | 0.264 s | 0.859 s | 3.26x faster | Recalc and extract mode |
| Surgical cell update | 0.032 s | Unsupported | WolfXL only | Single-cell patch |
Across every tested route, WolfXL outputs matched expected values.4 Cold start, warm latency, bulk CSV, roundtrip save, and PDF conversion were all won by WolfXL in this measured matrix.
For autonomous agent infrastructure, disk footprint and process initialization directly govern container provisioning speed, ephemeral disk costs, and memory ceiling under concurrency.
What an agent container actually pulls: the WolfXL wheel against the observed LibreOffice installation tree. Receipt-backed installation-tree comparison (39.4 MB vs 422.8 MB): 10.7x.
49.7 vs 59.4 MiB
On the 200,000-row workload, WolfXL recorded a 16.5% lower peak memory footprint across the complete execution lifetime.
In-process
WolfXL runs directly inside the Python process. LibreOffice requires spawning a separate desktop process with profile directory scaffolding.
ABI3 wheel
One wheel covers Python 3.9 through 3.13 with no native toolchain, no compiler, and no system libraries at install time.
All benchmark scripts, synthetic fixtures, diff tools, and SHA-256 evidence receipts are public in the WolfXL open-source repository so you can inspect the exact methods and verify numbers on your own hardware.