Skip to content
kevin9327Public

About

Deterministic document runtime for agents. DOCX, ODT, Markdown, HTML, PDF/A, plus regional Hangul HWP/HWPX/HML.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

DocAgent — picture in, PDF/A out. Command Convert. Capsule hashed. GPU-free. Not OCR.

CI stars Rust 1.93 MIT Integer layout Capsule hashes Prove same bytes PDF/A XObject No GPU Not OCR MCP WIT

Picture in. PDF/A out. Capsule hashed. GPU-free. Command::Convert · SHA-256 ×3 · i32 1/7200" · PNG/JPEG → PDF/A XObject · not OCR. MinerU parses a scan. DocAgent embeds a PNG.

vs the field · Quickstart · What ships · API · Docs

Unique vs the locked ten — Command/Query/Event · capsule SHA-256 ×3 · prove same bytes. Not OCR. WeasyPrint tightness not claimed.

MinerU, Docling, Pandoc, Marker, Unstructured, PyMuPDF, WeasyPrint, ONLYOFFICE, python-docx, and LibreOffice do not ship an agent API, a three-hash capsule, and byte-identical replay together.

  • Picture in, PDF/A out. PNG/JPEG on Markdown, HTML, DOCX, ODT paint as a PDF/A XObject. We embed the bytes. We do not OCR.
  • Integer layout. Coordinates are i32 at 1/7200 inch. Same fonts → same bytes. GPU-free.
  • Hangul is a regional codec on the same IR (images —), not the product name.
  • Not claimed: OCR, VLM, OmniDocBench, WeasyPrint print-CSS tightness (table/paragraph still open).

Hashes below are the SHA-256 ×3 in letter-capsule.json.

Real convert of examples/letter.md: PDF/A page with the teal harbor mark under the H2, semantic HTML with the same mark, capsule SHA-256 ×3

examples/letter.md → PDF/A + HTML + capsule. Teal harbor mark under the H2. JSON b468b37f…; trio/capsule panel still b867db0a… (shots lag — not a fake hash). WeasyPrint tightness not claimed closed.

Hash SHA-256 (letter-capsule.json)
input b0f4423728db4238779b3bf6cbd238d4d0d637f733c078322be6ff23398bbcdf
plan 4b7360eb1b7a9bec20cc35d5c79f2156c22d2712ab62ededfb60e328b8f16d3a
output b468b37f1c3d8da7e4aac7e1a8417b46c29a57863817f9df16e8d4a6cc89f0f8

vs the locked ten

Locked against the ten most-starred document repositories an agent actually meets (star counts 2026-09-06). Agent-runtime matrix, not an OCR bake-off. No OmniDocBench numbers.

Tool Job C/Q/E Capsule Same bytes i32 layout GPU-free Hangul
DocAgent Agent document runtime yes SHA-256 ×3 yes 1/7200" yes yes
MinerU 79k PDF/Office → LLM markdown
Docling 66k Gen-AI parse + export optional
Pandoc 46k Universal markup convert yes
Marker 40k PDF → markdown/JSON
Unstructured 15k Document ETL for LLMs
PyMuPDF 11k PDF extract/convert yes
WeasyPrint 10k HTML/CSS → PDF yes
ONLYOFFICE 6.9k Collaborative office suite yes
python-docx 5.7k Word DOCX read/write yes
LibreOffice 4.3k Headless office convert yes

North star: drop examples/letter.md (or DOCX/ODT) that contains a PNG or JPEG, and get PDF/A + HTML + Markdown + DOCX + ODT whose bytes match the next run, with three hashes in the capsule. The picture is a PDF/A XObject. Not OCR.

Images: yes PNG + JPEG on Markdown / HTML / PDF/A / DOCX / ODT. — on Hangul. The demo letter is ![Harbor mark](docs/assets/mark.png). First-screen convert shot above shows the teal mark under the H2. Demo-image gap closed. Print-CSS tightness vs WeasyPrint is not claimed closed.

Quickstart

git clone https://github.com/kevin9327/docagent
cd docagent
cargo test --workspace
cargo run -p docagent-cli -- convert examples/letter.md \
  --pdf out.pdf --html out.html --odt out.odt --docx out.docx --capsule cap.json
cargo run -p docagent-cli -- prove examples/letter.md

examples/letter.md contains ![Harbor mark](docs/assets/mark.png). Convert paints that teal mark under the H2 as a PDF/A XObject. prove converts twice (PDF/A + HTML) and exits 0 only when the bytes and the three SHA-256 hashes match. The prove JSON (letter-prove.json) is a separate artifact from the convert capsule in the table above — those plan/output hashes stay distinct (928b4745… / 2607bb6f…). Do not copy them onto letter-capsule.json.

Binaries: docagent (CLI) · docagentd (daemon) · MCP + WIT adapters over the same Engine.

use docagent_api::{Command, Engine, ExportTarget};

let mut engine = Engine::new();
let out = engine.execute(Command::Convert {
    input: std::fs::read("examples/letter.md")?,
    input_kind: None,
    targets: vec![ExportTarget::PdfA, ExportTarget::Html, ExportTarget::Markdown],
})?;
// out.capsule.{input_hash, plan_hash, output_hash}

Command Convert: Markdown DOCX ODT HTML with PNG or JPEG. One integer engine. PDF/A XObject out. Three capsule hashes. Prove. Not OCR.

PNG and JPEG on Markdown, HTML, PDF/A, DOCX, and ODT become PDF/A XObjects. Hangul images are a dash. Capsule hashed. GPU-free. Not OCR.

Why this exists

MinerU, Docling, Marker, and Unstructured turn documents into tokens for models. Pandoc, python-docx, WeasyPrint, ONLYOFFICE, and LibreOffice turn documents into other documents. DocAgent is the runtime in the middle that an agent can call, replay, and prove.

What ships

Honest codec coverage — not a wishlist. Full table: docs/src/capabilities.md.

Mark Markdown HTML PDF/A DOCX ODT Hangul
Lists (ul/ol, nested) yes read ul/ol/tasks markers w:numPr text:list yes
Links [text](url) <a href> URI /Link w:hyperlink text:a yes
Strike ~~text~~ <s> fill w:strike line-through yes
Quotes > <blockquote> quote bar Quote Quote yes
Code `span` / fence <code> / <pre> fills Code Tcode yes
Thematic break --- <hr/> rule fill HorizontalLine HorizontalLine yes
Tasks - [x] checkbox task box [x] [x] yes
Highlight ==mark== <mark> fill w:highlight Tmark yes
Super / sub ^ ^ / ~ ~ <sup> / <sub> baseline w:vertAlign Tsuper / Tsub yes
Underline __text__ <u> fill w:u Tunder yes
Images (PNG, JPEG) ![alt](…) <img> XObject a:blip draw:image —
Table header GFM | --- | <th> / <thead> header fill w:tblHeader THcell yes

Images are the first-class row. PNG and JPEG round-trip on Markdown, HTML, PDF/A, DOCX, and ODT. They stay — on Hangul. That dash is real.

HTML read recovers data-URI <img>, lists, <th>/<thead>, <blockquote>, <pre>, <a href>, and <mark> into the same IR. http(s): src is skipped. This is not a full HTML5 engine.

No spreadsheet. No slides. No cursor. No undo stack. No OCR. Flow documents only.

Convert shots

Files from examples/letter.md: PDF/A · HTML · DOCX · ODT · Markdown · capsule JSON.

Harbor mark — the PNG that goes in

![Harbor mark](docs/assets/mark.png)

PDF/A page from examples/letter.md — teal harbor mark under the H2 as a PDF/A XObject

PDF/A from the integer layout engine. Teal harbor mark under Delivery confirmation — order 48291. GPU-free. Same fonts → same bytes.

Semantic HTML from examples/letter.md — teal harbor mark under the H2 as an img

HTML from the same IR. Teal harbor mark under the H2 as <img>. read recovers data-URI images. Not HTML5. GPU-free.

Capsule JSON with input, plan, and output SHA-256 hashes from examples/letter.md

Capsule from examples/letter.md: input / plan / output SHA-256. JSON b468b37f…; shot still shows b867db0a… (shots lag — not a fake hash). Two converts, same fonts, same bytes. GPU-free. Deterministic. Not OCR.

The test is letter_md_is_byte_identical_across_two_runs. Hashes above are the hashes in letter-capsule.json.

Surface What it is
IR Format-blind document model. Layout never sees “docx” or “hwp”.
Layout One engine. Coordinates are i32 at 1/7200 inch. f32 is forbidden.
PDF/A Archival print from the integer plan. PNG and JPEG are XObjects. Two runs, same fonts, same bytes.
DOCX / ODT Word and LibreOffice files. Headings, lists, links, tables, PNG + JPEG (a:blip / draw:image).
Markdown / HTML Agent-native text and semantic HTML. ![alt](src). HTML <img> write / data-URI read. Not HTML5.
Capsule Three SHA-256 hashes on every Command so a retry is evidence, not hope.
Hangul Regional codecs on the same IR, not the product name. Images on Hangul are still —.

Command / Query / Event

Command  →  Convert | Import | Export | LayoutDocument
Query    →  EngineVersion | LastCapsule | LastDocument | CapsuleByInputHash
Event    →  CommandCompleted { capsule_id } | Warning

Every Command writes a capsule. CLI, daemon, MCP, and WIT are thin adapters over the same Engine. See AGENTS.md and docs/src/intro.md.

flowchart LR
  A[DOCX / ODT / MD / HTML + PNG/JPEG] --> B[docagent-model IR]
  B --> C[docagent-layout<br/>i32 @ 1/7200 in]
  C --> D[PDF/A XObject]
  C --> E[HTML]
  C --> F[DOCX / ODT / MD]
  B --> G[capsule.json<br/>input · plan · output]
Loading

Crate graph

Codecs (docx, odt, md, html, hwp5, hwpx, hwp3, hml) do not import each other and do not import layout. Layout, paint, raster, and PDF do not know the source format.

cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo run -p docagent-lint
cargo run -p docagent-conformance -- --require-win

Docs

License

MIT. See LICENSE.

About

Deterministic document runtime for agents. DOCX, ODT, Markdown, HTML, PDF/A, plus regional Hangul HWP/HWPX/HML.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages