Today, we release Paper Office, a suite of Python packages that allow agents to manipulate Word, PowerPoint, and Excel files with added safety, correctness and breadth, building on legacy open source packages: python-docx, python-pptx and OpenPyxl. Across five models and 61 tasks, Paper packages plus guidance passed 92.5% of trials, versus 80.7% for upstream packages without skills and 69.5% with Anthropic's comparable Office skills. Agents also wrote code to edit Office file internals directly in just 1.6% of Paper runs, compared with 78.7% without skills and 50.5% with Anthropic skills. We note that basic software, in addition to prompt, skills, and tools, remains an important lever for harness optimization.
Brownfield Knowledge Work
Agents still have low penetration in the daily work of consultants, lawyers, bankers, and operators. We believe the bottleneck to professional adoption is fidelity to real workflows. Agents dont manipulate existing documents with the same techniques that humans do, and the resulting decks, sheets, and documents sit in an uncanny valley that aren't fit for client consumption.
DOCX, PPTX, and XLSX files use Office Open XML (OOXML): each is a ZIP archive containing XML files, images, and other resources linked together, rather than a single text file. Editing them means keeping those parts and their relationships consistent, so even a small visible change can require updates in several places.
The standard Python Office libraries (python-docx, python-pptx, and openpyxl) are mature construction tools with years of accumulated edge cases, and most production agents often rely on these libraries for doc manipulation. However, they haven't seen updates in several years and, for many important workflows, lack feature breadth and correctness contracts. In some cases, models opt for other Javascript based packages or HTML-to-document processes to more easily represent and manipulate classic office documents, but these intermediate representations are lossy and often corrupt existing, brownfield work.
We forked, patched, and reworked the APIs of the standard Python Office libraries to support a variety of agent-first use cases, improving correctness and expanding feature completeness.
An agent editing a file often has to:
- find the logical object a user refers to, even when its text is split across elements or inherited from a template
- apply the requested change while maintaining formatting and relationships
- preserve everything outside the requested scope, including package parts the library does not understand
- reopen the saved artifact and establish that the intended effect survived serialization.
When the package cannot express those operations, the model falls through to wrapper scripts and raw OOXML, polluting its context with package mechanics. This frequently leads to silent regressions in comment anchors, chart workbooks, fields, custom XML, formula dependencies and so on.
Paper Office Packages
Paper Office keeps the familiar imports and extends the packages underneath them. Existing model priors remain useful: import docx, from pptx import Presentation, and import openpyxl still work.
The additions expose hidden structure as typed, machine-readable data, validate targets before supported edits, provide package-preserving save paths, report bounded changes, and refuse explicitly when an operation cannot be handled safely.
Paper DOCX
Overview
paper-docx extends python-docx with document-wide search, tracked edits, comments, composition, and reversible redlines, allowing agents to revise and review existing Word documents using Word's native review model.
Explore Features
The additions, tied to the work:
- Cross-Run Text Search.
docx.searchmatches exact text across Word's run fragmentation, with opt-in normalized matching, and returns a liveSpanfor replacement, tracked edits, or comment anchoring. Spans revalidate before mutation; reacquire a span after a text-changing replacement. - Numbering Restarts.
docx.numbering.restart_numbering()creates a new numbering instance that retains the existing definition and restarts at one;apply_numbering()assigns it to the intended paragraphs. - Native Word Redlines.
docx.package.compareemits text and table-row changes as Word-native tracked changes, verifies both accept and reject outcomes on private copies, and refuses differences it cannot represent safely. - Review Resolution and Comment Threads.
doc.revisionsenumerates supported revisions and accepts or rejects them atomically;remaining_unsupported()identifies forms requiring another tool.docx.commentopsmanages replies, anchors, and resolution state as a connected thread. - Content Controls.
docx.controlsfills supported controls with typed values. Supported data-bound text updates synchronize visible text with the custom XML store; unsupported bound types, locked controls, and unsafe structures refuse. - Fields and Bookmarks.
docx.bookmarksanddocx.fieldscreate bookmarks over a span and author page numbers, dates, cross-references, and tables of contents as fields with placeholder results. - Cross-Document Composition.
docx.compositioncopies formatted content between documents, reconciles styles, numbering, media, hyperlinks, and bookmarks, and reports every part touched. - Package Diffs and Saves.
docx.package.patch_saverestores original bytes for semantically unchanged package parts;diff_packageandtext_diffreport changes, anddiagnoseexplains unreadable packages. NormalDocument.save()validates its output but does not promise byte-minimal serialization. - Document Protection.
docx.protectionchecks Paper mutations against the active restriction mode: comments-only protection permits comment operations, and forms protection permits supported form updates. An explicit acknowledgment overrides the guard without removing the protection setting.
The fork also traverses body text, headers, footers, footnotes, endnotes, comments, tracked insertions, content controls, and text boxes through docx.story, with revision views and counts of blind regions it cannot read.
Paper PPTX
Overview
paper-pptx extends python-pptx with inherited-format inspection, native bullets, guarded slide and shape edits, cross-deck composition, and structural diffs, enabling surgical diffing of PowerPoint files.
Explore Features
The additions, tied to the work:
- Effective Formatting Inspection.
pptx.inspect,inspect_text, andinspect_deckresolve supported font, paragraph, and shape formatting through the placeholder, layout, master, and theme chain, with provenance and content-fingerprintedBlockAnchortargets. Unsupported values are marked unresolved and unreadable regions are counted. - Formatting-Preserving Text Replacement.
pptx.edit.replace_text,replace_text_at, andrefindreplace text while preserving unaffected runs, and anchored edits detect stale content and refuse before a change lands on the wrong text. - Relationship-Safe Slide Cloning.
prs.slides.clone(),delete(),reorder(), andmove()are relationship-safe; cloned charts receive independent embedded workbooks, and unsupported relationships raise typed refusals. - Package-Safe Shape Editing.
SlideShapes.delete(),move(), andadd_copy()edit shapes while preserving ownership, and group-aware by-name lookup refuses ambiguous names and asks the caller to disambiguate. - Merged-Cell Table Editing.
Table.insert_row(),delete_row(),insert_column(), anddelete_column()keep the grid consistent and guard merged regions at the affected cells. - Bullets, Numbering, and Notes.
Paragraph.bulletandTextFrame.normalize_autofit()author real bullets and make inherited autofit explicit.Slide.read_notes_text()reads without creating a notes part;replace_notes_text()edits an existing notes body. - Safe Image and Chart Updates.
Picture.replace_image()changes only the target picture while preserving position and crop, even when an image part is shared.Chart.replace_data_safe()validates the target chart and workbook structure, refusing shared chart parts and unsupported chart families. - Policy-Based Slide and Deck Imports.
Presentation.import_slide()andappend_deck()require an explicit reconciliation mode: adopt the destination theme, keep the source appearance, or bake effective values into explicit formatting. They return anImportReportfor each imported slide. - Layout Rebinding.
Slide.rebind_layout()moves a slide to another layout under explicit placeholder and orphan policies, and itsRebindReportidentifies every run whose resolved appearance changed. - Live Slide Number and Date Fields.
Presentation.apply_footers()andSlide.apply_footers()author nativea:fldelements bound to footer placeholders. Date formats usedatetime1throughdatetime13;fixed_dateinstead writes literal text. - Package-Preserving Saves.
pptx.package.patch_save()restores original bytes for semantically unchanged members, so unrelated serialization changes need not appear in the delivered package. - Permanent-ID Deck Diffs.
pptx.diff.diff_decksreports structural changes in decks derived from a common ancestor.detail="text"adds text, chart-data, and notes deltas;detail="full"adds resolved run-formatting and bullet changes.
Intake is hardened too: the package rejects ambiguous or unsafe ZIP archives, including duplicate or case-colliding members, noncanonical paths, encryption, and unsupported compression. Path-based saves write a sibling temporary package and atomically replace the destination after serialization succeeds.
Paper XLSX
Overview
paper-xlsx extends openpyxl with package-preserving saves, reference-aware structural edits, edit receipts, and LibreOffice-backed recalculation, supporting diffs that account for formulas, dependencies, and package content.
Explore Features
The additions, tied to the work:
- Targeted Workbook Inspection. Standard surfaces such as
wb.sheetnames, bounded cell ranges, andwb.defined_namesremain the starting point.wb.search()finds text or regex matches in values and formulas;ws.allowed_values(cell)reports validation-derived choices. - Reference-Aware Structural Edits. Supported row, column, sheet, and range operations update dependent formulas, names, print areas, table ranges, and chart references, or refuse. Row and column insertions and deletions return an
AddressRemap; sheet renames andmove_range()do not. - Preserve-Mode Object Editing.
copy_format()copies formatting,chart.repoint()updates a value series and removes its stale cache,ws.append_table_row()expands a supported table atomically, andws.replace_image()replaces one loaded image without rewriting the drawing. Category ranges and the intended business scope still need explicit attention. - Formula Cache Freshness. Formula edits and input changes that may feed formulas invalidate retained cached results and request recalculation on open. Style-only and unrelated value edits keep their caches. Until recalculation, a data-only reader may see
None; Paper does not calculate formulas itself. - Error Inspection and Diffs.
openpyxl.preserve.scan_errors()inspects formula and cached/value error representations without LibreOffice.diff_workbooks(..., remaps=())separates content changes from cells shifted by structural edits. - Edit Receipts.
wb.save(..., receipt=True)returns anEditReceiptnaming changed cells and parts;wb.validate()runs save validation without writing. A receipt can include formula-cache invalidations as well as the cell the agent explicitly edited. - LibreOffice Recalculation and Certification.
oracle.recalc()recalculates a temporary copy, scans for errors, and can write a separate Paper-preserved candidate throughoutput_path.oracle.certify()reports whether LibreOffice reproduces cached values asCERTIFIED,DIVERGED, orBASELINE_UNVERIFIABLE.oracle.evaluate()andoracle.evaluate_many()apply temporary inputs and return requested outputs. These operations never overwrite the source, and preservation does not require LibreOffice. - Protection and Pivot Refresh. Writes to locked cells can warn;
wb.strict_protection = Truemakes them refuse.wb.set_pivot_refresh_on_load()grants explicit consent for dependent edits and asks Excel to refresh the selected pivots on open. Their cached results remain stale until that refresh.
Path saves build the archive on disk, validate ZIP consistency, and fsync before rename. Callers, rather than fixed package-wide size or compression-ratio limits, control resource budgets.
Experimental Design
The reported comparison covers 61 tasks: 27 DOCX, 15 PPTX, and 19 XLSX. It covers a wide range of existing-file workflows involving fragmented text, revisions, comment threads, numbering, fields, slide relationships, embedded workbooks, template lineage, formulas, names, charts, and dependent ranges, alongside two creation controls.
We evaluated five models: Opus 5, GLM 5.3 Flash, GPT 5.6 Sol, Grok 4.6, and DeepSeek v4.1 Flash. Each model-task pair is rolled out under each of three conditions:
| Condition | Package | Guidance |
|---|---|---|
| No skills | Upstream | None |
| Anthropic skills | Upstream | Anthropic's Office skills |
| Paper + skills | Paper | Paper skills |
All conditions ran through OpenCode in Harbor, with identical task prompts across conditions.
Both upstream conditions used the same pinned versions: python-docx==1.2.0, python-pptx==1.0.2, and openpyxl==3.1.5.
Task Success
Task success by model
Opus 5
GLM 5.3 Flash
GPT 5.6 Sol
Grok 4.6
DeepSeek v4.1 Flash
All five models
Paper passes 282/305 trials (92.5%), compared with 246/305 (80.7%) upstream raw and 212/305 (69.5%) with Anthropic skills.
Performance by Slice
Task success by format
DOCX
PPTX
XLSX
Against no skills, Paper improves success in 12 of 15 model-by-format slices, ties on DeepSeek PPTX and XLSX, and trails by one task on GLM PPTX. Pooled across models:
- DOCX: 83.0% without skills, 84.4% with Anthropic skills, 96.3% with Paper.
- PPTX: 84.0% without skills, 74.7% with Anthropic skills, 92.0% with Paper.
- XLSX: 74.7% without skills, 44.2% with Anthropic skills, 87.4% with Paper.
Trajectory Analysis
The main difference was who handled the file's internal bookkeeping. In the reviewed upstream runs, agents often wrote code to reconnect comments, copy slide relationships, or repair spreadsheet references and caches. Some did this successfully. Paper usually handled that work through its APIs, although agents still inspected XML to check the result. Across all 915 retained runs, explicit raw ZIP editing code appeared far more often with upstream packages:
Direct edits to OOXML internals
The recurring failure in the reviewed cases was an incomplete edit: the requested text or numbers were right, but a comment link, dependent range, or unrelated part of the file was not. Paper helped with those connected changes.
How we counted trajectory behavior
We analyzed the selected run for each model, task, and condition across the 61 tasks. The chart counts a run once if agent-submitted code contains an explicit .writestr(...) call. We inspected source submitted through inline Python, script heredocs, file writes, edits, and added patch lines, excluding returned documentation and library source.
Across the trials, Paper found formula errors that upstream runs missed, kept comment replies attached when a thread was edited, and updated spreadsheet validation and formatting ranges when a column was inserted. Even if the edit was simple to make, without Paper the model often corrupted the surrounding document in subtle ways.
The following examples compare how the same model completed the same task with each setup.
Example 1: DOCX Comments
DeepSeek was asked to extend an existing comment, add a reply, and mark the conversation as resolved while leaving another discussion open. Using the upstream package without skills, it added the requested text but did not correctly update the links that connect the replies and record the conversation's resolved status. Paper maintained those links through its comment APIs, while the agent using Anthropic skills updated them manually. Both passed, while the version without skills failed.
Example 2: PPTX Slide Copying
Grok was asked to copy a slide and change the copy's chart and speaker notes without affecting the original. All three setups passed the checks for keeping the chart and notes independent. The copies made with the upstream package retained internal creation identifiers from the original slide, and this was their only failed check. Paper assigned new identifiers when copying the slide and passed all checks.
Example 3: XLSX Forecast Updates
GLM was asked to add a forecast quarter and update the chart and annual totals. All three setups reached the correct revenue of 485 and EBITDA of 111. With the upstream package, some input-validation and formatting rules still covered the old cell ranges, and the agent without skills left the old quarter in the chart. Paper updated the dependent ranges, and the agent produced a workbook that passed all checks. The other two setups got the totals right but left parts of the workbook out of date.
A separate spreadsheet task asked GPT 5.6 Sol to identify formula errors without changing the file. Using Paper's scan_errors(), it found all four required errors in the formulas and stored calculation results. In both upstream setups, it found only two. The Paper result passed, and the workbook remained unchanged.
Software as a Performance Lever
Across five models, Paper packages increased complete task success across the board, and highlight software as an important lever to improve agent performance for knowledge work problems.
We use Paper Office by default inside the Feather harness. Learn more about the packages here.
You can see all tasks here.
Citation
Khazi, Daanish; Bains, Gavin; and Besgen, Joey, "Introducing Paper Office",
Paper Instruments Blog, September 23, 2026.
@misc{khazietal2026paperoffice,
author = {Daanish Khazi and Gavin Bains and Joey Besgen},
title = {Introducing Paper Office},
howpublished = {Paper Instruments Blog},
year = {2026},
month = {September},
url = {https://www.paperinstruments.com/blog/introducing-paper-office}
}