Your first example
Let’s run KAOS on a task every lawyer knows: redlining a contract. This example compares
two versions of an agreement, produces a Word-style redline (tracked changes), and then
accepts or rejects them in code — using kaos-office
and kaos-content. It’s fully deterministic and
offline: no API key, no model download, same output every time.
Run it
Section titled “Run it”One command — no clone, no virtualenv, no key:
uv run https://raw.githubusercontent.com/273v/learn-kaos/main/examples/redline-contract.pyOr from a local clone of this repo:
uv run examples/redline-contract.pyYou’ll see:
Wrote 3 Word files to ./redline-demo/ — open them in Word to review: • original.docx — the original contract • revised.docx — counsel's revised version • redline.docx — the tracked-changes redline ← open this one
before: The interest rate is five percent and the term is three years. after: The interest rate is seven percent and the term is five years.
4 tracked change(s) in redline.docx: deleted: 'five' inserted: 'seven' deleted: 'three' inserted: 'five'
Resolve the markup in code: accept all -> The interest rate is seven percent and the term is five years. reject all -> The interest rate is five percent and the term is three years.It writes real Word files you can open (redline.docx shows the tracked changes just
like a hand-marked redline), then reads them back: counsel changed the rate (five → seven
percent) and the term (three → five years), and KAOS surfaces each edit as a typed tracked
change it can accept or reject in code.
The code
Section titled “The code”This is the exact file that runs above — and the exact file this site’s CI runs on every change. What you read here cannot drift from what’s tested, because the page imports the file byte-for-byte:
#!/usr/bin/env -S uv run --script# /// script# requires-python = ">=3.13"# dependencies = ["kaos-office>=0.1.4,<0.2", "kaos-content>=0.1.3,<0.2"]# ///"""Redline two contract versions — and review the result in Word.
`kaos-office` compares two DOCX versions into a Word **redline** (trackedchanges); its reader surfaces those changes as *typed revisions* you can inspectand resolve in code with `accept_all` (the final version) or `reject_all` (theoriginal). Fully offline, no model.
This writes three real Word files you can open and review, then prints the diff.
Run it:
uv run examples/redline-contract.py"""
from __future__ import annotations
from pathlib import Path
import kaos_content as kcimport kaos_office as kofrom kaos_content.revision import RevisionType, Revisions, accept_all, reject_all
ORIGINAL = "The interest rate is five percent and the term is three years."REVISED = "The interest rate is seven percent and the term is five years."
# Write the Word files somewhere a person can actually open them.OUT = Path.cwd() / "redline-demo"
def clause(text: str) -> kc.ContentDocument: b = kc.DocumentBuilder() b.heading(1, "Loan Agreement") b.paragraph(text) return b.build()
def body_text(doc) -> str: """The last non-empty line of the rendered document — the clause text.""" lines = [ln.strip() for ln in kc.serialize_markdown(doc).splitlines() if ln.strip()] return lines[-1] if lines else ""
def main(): OUT.mkdir(exist_ok=True) original = OUT / "original.docx" revised = OUT / "revised.docx" redline = OUT / "redline.docx" ko.write_docx(clause(ORIGINAL), original) ko.write_docx(clause(REVISED), revised) # Compare the two versions into a Word redline (real tracked changes). ko.write_redline(original, revised, redline)
print(f"Wrote 3 Word files to {OUT}/ — open them in Word to review:") print(" • original.docx — the original contract") print(" • revised.docx — counsel's revised version") print(" • redline.docx — the tracked-changes redline ← open this one\n")
print(f" before: {ORIGINAL}") print(f" after: {REVISED}\n")
# Read the redline back; each edit is a typed revision. doc = ko.parse_docx(str(redline), track_changes=True) revisions = list(Revisions.from_document(doc)) print(f"{len(revisions)} tracked change(s) in redline.docx:") for rv in revisions: verb = "inserted" if rv.change_type is RevisionType.INSERTION else "deleted" print(f" {verb:>8}: {rv.text!r}")
# Resolve the markup two ways, in code. accepted = body_text(accept_all(doc)) rejected = body_text(reject_all(doc)) print("\nResolve the markup in code:") print(f" accept all -> {accepted}") print(f" reject all -> {rejected}") return revisions, accepted, rejected
if __name__ == "__main__": revisions, accepted, rejected = main() types = {rv.change_type for rv in revisions} # The redline carries both insertions and deletions... assert RevisionType.INSERTION in types and RevisionType.DELETION in types # ...accepting keeps the revised numbers, rejecting restores the originals. assert "seven percent" in accepted and "five years" in accepted assert "five percent" in rejected and "three years" in rejectedWhat just happened
Section titled “What just happened”- The
# /// scriptblock at the top is PEP 723 inline metadata.uvreads it, resolves the packages into a cached isolated environment, and runs the file — that’s why one command is enough. write_redline(v1, v2, out)compares two DOCX versions into a real Word redline. Open it in Word and it looks hand-marked.parse_docx(path, track_changes=True)thenRevisions.from_document(doc)surfaces each edit as a typedRevision— itschange_type(insertion/deletion),text, andauthor— so you can review changes in code, not by eyeballing.accept_all/reject_allresolve the markup: accepting yields the revised version, rejecting restores the original. Theasserts at the bottom make the file its own test, so this page is guaranteed correct.