AiOffice
AiOffice is an AI-native document engine for creating and editing DOCX files through stable selectors, strict schemas, validated plans, and verifiable output. Agents work with document semantics instead of Word object APIs or OOXML internals.
The current 0.4.0 release is an alpha milestone. It provides:
- lossless opening and conservative editing of existing DOCX packages;
- stable semantic node IDs and deterministic target resolution;
- eight professional recipes for common document tasks;
- 75+ typed operations with progressively disclosed JSON Schema;
- atomic
plan/committransactions with revision conflict detection; - semantic, native-package, reopen, accessibility, privacy, and visual QA gates;
- a Python API, CLI, workspace model, and transport-neutral six-tool adapter.
The active document spec is the 0.2 draft exposed by
aioffice.spec.models.SPEC_VERSION. The public API can continue to evolve before
1.0.
Why AiOffice
Agent-safe targeting
inspect() and locate() return stable selectors such as #status and never
require an agent to construct native references. Ambiguous queries are reported as
ambiguous; AiOffice does not silently choose the first result.
Transactional editing
Every edit can be planned before it is committed. Plans are bound to one artifact revision, validated against strict operation models, and protected by a deterministic hash.
Verifiable DOCX output
For imported DOCX files, AiOffice preserves untouched package parts byte-for-byte and reports whether every native change was declared and the result remains a valid OPC package. Professional tasks can additionally reopen and render the result before delivery.
Install
pip install aioffice
AiOffice requires Python 3.11 or newer.
For raster page analysis and visual quality gates:
pip install "aioffice[render]"
Native PDF/PNG rendering also requires LibreOffice and Poppler on the host. See the native rendering contract.
Create a document
from aioffice import DocumentBuilder
doc = (
DocumentBuilder(title="Project Report", theme="business-clean")
.heading("Project Report", id="report_title")
.paragraph("The first delivery milestone is complete.", id="status")
.bullet_list(
["Validated spec", "Generated DOCX", "Published HTML preview"]
)
.build()
)
validation = doc.validate()
assert validation.valid
doc.export("report.json")
doc.export("report.md")
doc.export("report.html")
doc.export("report.docx")
Professional Agent workflow
For common editing tasks, use the recipe layer:
import aioffice
doc = aioffice.open("report.docx")
# Discover structure and resolve one target without guessing.
outline = doc.inspect(view="outline")
assert outline["nodes"]
resolution = doc.locate(query="Draft", scope="all")
if resolution.status != "resolved" or resolution.selected is None:
raise RuntimeError(resolution.diagnostic or "Target was not resolved.")
task = {
"recipe": "text.replace-scoped",
"target": {"selector": resolution.selected.selector},
"parameters": {
"search": "Draft",
"replacement": "Approved",
},
"constraints": {
"visual_review": "optional",
"require_native_verification": True,
},
"acceptance": {
"must_contain": ["Approved"],
"must_not_contain": ["Draft"],
},
}
# Planning does not mutate the source document.
plan = doc.plan_task(task)
if not plan.valid:
raise RuntimeError([item.model_dump() for item in plan.diagnostics])
# Commit atomically, then require professional QA to pass.
result = doc.commit_task(plan)
if not result.success:
raise RuntimeError(result.model_dump())
assert result.quality.passed
result.commit.artifact.export("updated.docx")
The workflow is:
open
-> inspect
-> locate
-> recipe_schema
-> plan_task
-> review predicted changes
-> commit_task
-> quality report
-> export
Inspection views
| View | Purpose |
|---|---|
outline |
Heading hierarchy, sections, tables, images, stable selectors |
context |
One target with bounded neighboring nodes |
styles |
Style inventory, usage, direct and effective formatting |
table |
Bounded grids, cell IDs, spans, edit constraints |
layout |
Section geometry, floating images, layout diagnostics |
agent |
Paginated generic node discovery |
summary |
Compact artifact metadata and counts |
debug |
Native troubleshooting; not for normal agent edits |
Deterministic target resolution
resolution = doc.locate(
query="Revenue",
kinds=["paragraph", "table_cell_paragraph"],
scope="all",
)
if resolution.status == "ambiguous":
for match in resolution.matches:
print(match.occurrence, match.selector, match.context_before)
# Retry with a stable selector or ordinal=...
elif resolution.status == "not_found":
raise LookupError(resolution.diagnostic)
else:
selector = resolution.selected.selector
find() remains available for intentionally collecting multiple nodes. Check the
number of matches before selecting one.
Professional recipes
Discover the compact catalog first, then fetch only the schema you need:
catalog = doc.recipe_catalog()
schema = doc.recipe_schema("document.polish")
Built-in recipes:
| Recipe | Purpose | Risk |
|---|---|---|
text.replace-scoped |
Exact replacement with ambiguity control | low |
template.fill |
Fill declared placeholders and detect missing fields | low |
document.polish |
Normalize headings, body, tables, and pagination | medium |
styles.normalize |
Normalize typography while preserving content | low |
table.polish |
Improve table geometry, headers, margins, and banding | low |
heading.toc-ready |
Normalize outline levels and optionally insert TOC | low/medium |
brand.apply |
Apply a theme and professional typography | medium |
review.finalize |
Accept/reject revisions and remove comments | high |
Initial professional profiles:
business-professional-zhbusiness-professional-en
Example:
plan = doc.plan_task(
{
"recipe": "document.polish",
"profile": "business-professional-zh",
"parameters": {
"fix_pagination": True,
"apply_theme": False,
},
"constraints": {
"preserve_brand": True,
"visual_review": "required",
"allow_page_count_change": False,
},
"acceptance": {
"max_page_count_change": 0,
},
}
)
result = doc.commit_task(plan)
assert result.success
High-risk plans expose requires_approval=True. Review their normalized operations
before committing:
if plan.requires_approval:
print(plan.plan.normalized_operations)
result = doc.commit_task(plan, approve=True)
See Professional agent editing.
Quality gates
commit_task() returns the normal commit evidence and a QualityReport.
for gate in result.quality.gates:
print(gate.name, gate.status, gate.message)
assert result.quality.passed
The built-in gates cover:
- operation commit status;
- semantic document validation;
- recipe and caller acceptance assertions;
- native DOCX package verification;
- exported-DOCX reopen validation;
- accessibility checks for image alt text and heading-level jumps;
- privacy review for identifying, custom, or sensitive metadata;
- optional or required rendered-page analysis, including page-count constraints.
Visual rendering failures are warnings when visual_review="optional" and hard
failures when it is "required".
Raw operations
Use raw operations for bespoke edits not covered by a recipe. Resolve one target, fetch one strict schema, plan, and commit:
resolution = doc.locate(
query="Draft",
kinds=["paragraph", "heading"],
scope="all",
)
if resolution.status != "resolved" or resolution.selected is None:
raise RuntimeError(resolution.diagnostic or "Target was not resolved.")
schema = doc.operation_schema("text.replace")
plan = doc.plan(
[
{
"op": "text.replace",
"target": resolution.selected.selector,
"search": "Draft",
"replacement": "Approved",
}
]
)
assert plan.valid
commit = doc.commit(plan)
assert commit.success
commit.artifact.export("updated.docx")
The full operation union is intentionally not required in an agent prompt:
compact_catalog = doc.recommend_operations(
"Replace the approval status",
selector=resolution.selected.selector,
)
operation_schema = doc.operation_schema(compact_catalog[0]["name"])
Advanced code can import typed operations:
from aioffice.ops.document import ReplaceText
plan = doc.plan(
[
ReplaceText(
target="#status",
search="Draft",
replacement="Approved",
)
]
)
Document.apply() remains available for compatibility and engine-level workflows,
but new agent integrations should use plan_task() / commit_task() or
plan() / commit().
Native DOCX fidelity
Opening a DOCX attaches its native package while projecting supported content into the semantic document model:
doc = aioffice.open("existing.docx", roundtrip="preserve_unknown")
assert doc.origin == "native"
snapshot = doc.verify_fidelity()
assert snapshot.byte_identical
After a raw commit:
verification = commit.verification
assert verification is not None
assert verification.verified
assert verification.undeclared_changes == []
assert verification.opc_valid
After a professional task, the same evidence is available at
result.commit.verification and is included in the quality report.
AiOffice rewrites only affected native parts and proves untouched parts are byte-identical. Unsupported XML remains opaque and is preserved rather than guessed at or reconstructed.
Read:
- Native round-trip contract
- Native fidelity verification
- Structural editing contract
- Native image contract
- Native rendering contract
Six-tool adapter
aioffice.agent.tools provides a transport-neutral surface suitable for function
calling or an MCP integration:
inspect_documentlocate_contentlist_recipesplan_professional_taskcommit_professional_taskverify_professional_result
from aioffice.agent import professional_tool_catalog
tools = professional_tool_catalog()
assert len(tools) == 6
The adapter is available now. A packaged network MCP Server, its authentication model, and artifact storage policy remain future integration work.
Golden-case evaluation
Use representative documents to continuously measure target and operation selection:
from aioffice.agent import evaluate_professional_case
evaluation = evaluate_professional_case(
doc,
{
"id": "approve-status",
"task": {
"recipe": "text.replace-scoped",
"target": {"selector": "#status"},
"parameters": {
"search": "Draft",
"replacement": "Approved",
},
"constraints": {"visual_review": "off"},
},
"expected_operations": ["text.replace"],
"expected_targets": ["#status"],
},
)
assert evaluation.passed
The evaluator reports plan validity, target recall, operation recall, commit status, and quality-gate status.
CLI
Professional workflow
aioffice inspect report.docx --view outline
aioffice recipes list
aioffice recipes schema document.polish
aioffice task-plan report.docx task.json -o task-plan.json
aioffice task-commit report.docx task-plan.json \
-o updated.docx \
--report quality.json
Add --approve to task-commit only after reviewing a high-risk plan.
Raw operations
aioffice ops list
aioffice ops describe text.replace
aioffice ops schema text.replace
aioffice plan report.docx patch.json -o plan.json
aioffice commit report.docx plan.json -o updated.docx
Patch files accept an operation array or an envelope:
{
"operations": [
{
"op": "text.replace",
"target": "#status",
"search": "Draft",
"replacement": "Approved"
}
]
}
Inspection, validation, rendering, and schemas
aioffice inspect report.docx --view styles
aioffice inspect report.docx --view table --selector "#metrics"
aioffice capabilities report.docx
aioffice validate report.docx
aioffice render report.docx --format pdf -o report.pdf
aioffice render-pages report.docx --analyze --output-directory evidence
aioffice schema --kind operations -o operations.schema.json
aioffice schema --kind agent-protocol -o agent-protocol.schema.json
aioffice verify original.docx updated.docx \
--declared-affected /word/document.xml
Workspace
aioffice workspace init project
aioffice workspace import existing.docx --root project
aioffice workspace list --root project
aioffice workspace inspect ARTIFACT_ID --root project
aioffice workspace apply ARTIFACT_ID patch.json --root project
aioffice workspace reconcile ARTIFACT_ID edited.docx --root project --commit
aioffice workspace export ARTIFACT_ID updated.docx --root project
Supported scope
| Surface | Status |
|---|---|
| DOCX creation and semantic editing | supported |
| Existing DOCX lossless open and conservative native editing | supported |
| JSON and Markdown document input | supported |
| JSON, Markdown, semantic HTML, and DOCX output | supported |
| Native PDF/PNG rendering and visual evidence | supported with host tools |
| XLSX, PPTX, and PDF semantic editing | planned |
| Packaged network MCP Server | planned; six-tool adapter available |
Feature availability can depend on the current document and native package:
summary = doc.capabilities()
preflight = doc.preflight("table.row.insert", selector="#metrics")
The operation registry is the source of truth. See the generated capability matrix for the complete status vocabulary and feature-level caveats.
Documentation
- Professional Agent editing
- Capability matrix
- Style and rendering contracts
- Paragraph formatting surfaces
- Table layout
- Header and footer editing
- Section layout
- Dynamic fields
- Security policy
- Changelog
Development
python -m pip install -e ".[dev,render]"
python -m unittest discover -s tests -q
ruff check src tests
pyright
python -m build
python -m twine check dist/*
Capability documentation is generated from the registry:
aioffice capability-doc
aioffice capability-drift
Production releases use PyPI Trusted Publishing. The release tag must match the
version in src/aioffice/_version.py.
Compatibility is maintained within the active 0.4.x line where practical. The
document spec and public model remain pre-1.0 and can still evolve.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aioffice-0.4.0.tar.gz.
File metadata
- Download URL: aioffice-0.4.0.tar.gz
- Upload date:
- Size: 706.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
adebb3721b76ed7a17e6059e8fb24f5f52a8c34b4828d65d2675eac0f7a39b0d
|
|
| MD5 |
92e2aa40a7b71cb4a804582393e0b149
|
|
| BLAKE2b-256 |
de534d5da154a3e6aa7c9c365148085ff9f6e8bdf003fb2cbbeae694250855a6
|
Provenance
The following attestation bundles were made for aioffice-0.4.0.tar.gz:
Publisher:
publish.yml on HuiTurn/aioffice
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aioffice-0.4.0.tar.gz -
Subject digest:
adebb3721b76ed7a17e6059e8fb24f5f52a8c34b4828d65d2675eac0f7a39b0d - Sigstore transparency entry: 2272231503
- Sigstore integration time:
-
Permalink:
HuiTurn/aioffice@8f8ac4bcbbe59acd750d68a97cb6e84af94f6825 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/HuiTurn
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8f8ac4bcbbe59acd750d68a97cb6e84af94f6825 -
Trigger Event:
push
-
Statement type:
File details
Details for the file aioffice-0.4.0-py3-none-any.whl.
File metadata
- Download URL: aioffice-0.4.0-py3-none-any.whl
- Upload date:
- Size: 519.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f66231a65ee9ab6a0a9b179eb2449db1a1488059c6ab4e9252a0565d8193c00b
|
|
| MD5 |
acc3248accc947d08bf9135cffc571be
|
|
| BLAKE2b-256 |
80eba83fa772e48d55de7411db3a79b1ec0c2f7170a25450387fe1068203931c
|
Provenance
The following attestation bundles were made for aioffice-0.4.0-py3-none-any.whl:
Publisher:
publish.yml on HuiTurn/aioffice
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aioffice-0.4.0-py3-none-any.whl -
Subject digest:
f66231a65ee9ab6a0a9b179eb2449db1a1488059c6ab4e9252a0565d8193c00b - Sigstore transparency entry: 2272231666
- Sigstore integration time:
-
Permalink:
HuiTurn/aioffice@8f8ac4bcbbe59acd750d68a97cb6e84af94f6825 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/HuiTurn
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8f8ac4bcbbe59acd750d68a97cb6e84af94f6825 -
Trigger Event:
push
-
Statement type: