A LibreOffice extension (Python + UNO) that adds generative AI editing to Writer, Calc, and Draw.
- Install: Download
.oxtfrom Releases, double-click to install - Configure: Open WriterAgent > Settings in LibreOffice
- Set Backend: Enter endpoint (e.g.,
http://localhost:11434for Ollama) and model - Chat: Open sidebar with View → Sidebar → WriterAgent or use Ctrl+Q / Ctrl+E shortcuts
- Local-First & Flexible
- Powerful Feature Suites
- Web Research & Fact-Checking
- High-Fidelity Editing & Formatting
- MCP Server
- Agent Backends
- Architecture
- Roadmap & Future Vision
- Credits & Collaboration
- Installation & Setup
- Contributing
- License
Unlike proprietary office suites that lock you into a single cloud provider and send all your data to their servers, WriterAgent is local-first. You can run fast, private models locally (via Ollama, LM Studio, or local servers) ensuring your documents never leave your machine. If you choose to use cloud APIs, you can switch between providers (e.g., OpenRouter, Together.AI) in 2 seconds, maintaining full control over your data.
- LLM-facing Writer APIs: 9 core tools for everyday chat plus dozens of specialized UNO-backed tools. The main model keeps a small default list while
domain-scoped sub-agentsunlock deep APIs for page layout, shapes, charts, bookmarks, fields, footnotes, track changes, indexes, forms, and more—so models run multi-step document automation, not just rewrite paragraphs. - Format Preservation: Uses a "surgical" replacement method that preserves existing bold, italics, highlights, and font sizes.
- Agentic Analysis: The AI can run Numpy computations and return structured results (as JSON) to update your document.
- Real-time Grammar & Style Checker: An asynchronous proofreader with a sentence cache and Unicode-aware splitting. Includes Token-aware Overlap Repair to fix "LLM slop" and ensure surgical replacements. Persistent storage of good/bad sentences with document. Supports multiple backends configurable in Settings → Doc → Enable grammar checker (Writer):
- AI (LLM): Cloud or local AI models/API.
- LanguageTool (Local): Offline grammar server running locally.
- Vale (Local Style) (WIP): Style guides checker (Google, Microsoft, write-good).
- Harper (Local Rust): Lightning-fast offline Rust-backed grammar linter. Underlines appear shortly after you pause typing.
- Optional sentence language detection: Local (langdetect) uses
langdetectin your configured Python venv (embeddings worker) to auto-fix wrongCharLocaleand then grammar-check in the right language; AI (LLM) uses the chat API for the same step. Set Settings → Doc → Sentence language detection. Read the Plan. - Rich-text sidebar: Hosts a rich text control in the sidebar. Off by default.
- Math & LaTeX: MathML and TeX delimiters are automatically turned into editable LibreOffice Math formulas (OLE objects). Use
\(...\)/$...$for inline and$$...$$/\[...\]for display in chat or HTML content; prefer\(...\)over bare$near numbers. See docs/math-tex.md. - Symbolic Math (SymPy): Math Helpers —
solve_equation,symbolic_simplify,integrate,differentiate. Results insert as editable LibreOffice Math objects. - Charts from Python: Matplotlib figures from Viz Helpers or custom scripts insert as inline images.
- Text Analytics (spaCy): Readability metrics, named entities (NER), and key phrases for Writer documents. Use WriterAgent → Text Analytics… (with Readability (doc/sel), Entities, Key Phrases, Insert report). Requires
spacy+textdescriptives+ a model in the venv configured in Settings → Python.
- =PROMPT() Function: Run AI prompts within spreadsheet cells.
- =PY() / =PYTHON() Function: Run Python/NumPy within spreadsheet cells:
=PY("sp.prime(data)", A10). Supports multi-range inputs (e.g.,=PY("np.mean(data)", A1:A10, C1:C10)) and auto-unpacks single-cell inputs to Python scalars. Thedatavariable contains the cell values, dynamically injected at runtime. Returns can include lists/dicts of figures (multiple images) or DataFrames. Return semantics:None→ empty cell;float("nan")/np.nan→ Calc error cell (#NUM!/#VALUE!, cascades). Usenp.nanmean/np.nansumetc. when input contains blanks. See Data Handoff Guide and Empty cells vs NaN. - Automatic spill (Calc): On by default (Settings → Python → "Python auto spill in Calc"). A single-cell
=PYTHON()returning a list, 2D array, or DataFrame automatically spills the result into adjacent cells. Blocked cells produce#SPILL!in the formula cell. Spill locations are saved in the document (persistent across reloads). Explicit matrix formulas (Ctrl+Shift+Enter) and per-row index arguments remain available for manual control. - Trusted Calc helpers: via
analyze_data, chat delegation, and Tools → Run Python Script — set Data range where applicable.
| Domain | Helpers | Notes |
|---|---|---|
| Analysis | 14 trusted helpers (detail) + calc_goal_seek, calc_solver |
Run Python Script → Analysis Helpers; numpy/pandas/scipy/… stack. Analysis Tools · Architecture |
| Viz | quick_plot, correlation_heatmap, time_series_plot |
Charts insert on sheet; =PY() / matplotlib same; multi-figure lists/dicts. matplotlib, seaborn. Visualization |
| Math | solve_equation, symbolic_simplify, integrate, differentiate |
SymPy; inserts editable LO Math. sympy |
| Quant | fetch_historical_data, technical_analysis, portfolio_tearsheet, efficient_frontier |
yfinance, pandas-ta, quantstats, pyportfolioopt |
| Optimize | optimize_portfolio, linear_programming, solve_scheduling_problem |
scipy.optimize. Optimization |
| Units | convert_quantity, parse_quantity, format_quantity, check_dimensionality |
Calc: single formatted cell by default (36 km/h); output_style: "detailed" for grid. Beyond CONVERT() for compound units. pint. Units |
- Rich Text Cells: Paste HTML (bold, links, breaks) into a single cell using advanced StarWriter import paths.
- Batch Range Edits: Apply formulas and formatting in bulk. Specialized Toolsets.
- Advanced Features: Conditional Formatting and Sheet Filtering (AutoFilter).
- Spreadsheet → Python conversion: Run WriterAgent → Convert Sheet to Python… on an open Calc sheet (or selection) to rewrite spreadsheet formulas as
=PY()/=PYTHON()while constants, text, dates, and formats stay unchanged. A deterministic translator covers 235+ Calc functions—aggregates, logic, lookups (VLOOKUP,XLOOKUP), dates, financial, statistical, database, and array helpers—emitting NumPy/pandas/xl.*Python with precedent ranges wired as explicitdataarguments so Calc’s recalc graph stays correct. Optional column vectorization collapses repeated fill-down patterns; output defaults to a new sheet with an optional verify recalc pass and a conversion report for any formulas left as Calc (e.g.INDIRECT, array formulas). Details: Calc Spreadsheet → Python Import.
- Web Research: Powered by a vendored smolagents loop. Web Research Loop & Search Integration.
- Audio & Voice: Integrated cross-platform voice recording. Audio Architecture.
- Image Generation: Generate or edit (Img2Img) images. Image Generation Guide.
- Local OCR (Writer & Calc): Extract text and layout from embedded images offline via Docling — no cloud vision API required. Run Python Script → Vision Helpers —
extract_text(Writer: inserts at cursor; Calc: sheet report below the image). Packages:docling,rapidocr-paddle,numpy,pillow,onnxruntime(required for default RapidOCR), and optionalpaddleocr,paddlepaddlefallback. Settings: WriterAgent → Vision OCR Settings… for pipeline defaults; Settings → Python for venv path and Test. Image recognition design.
- Document Object Model (LO-DOM): A recursive model that understands structural relationships. LO-DOM Semantic Tree.
- Persistent Memory: Hermes Agent Patterns (memory & skills) and Librarian Onboarding.
- 34 Locales: Automated AI-driven translation and review pipeline. Localization Pipeline.
- Multilingual Grammar & language detection: When the AI grammar checker is on, optional sentence language detection can verify each complete sentence against the document locale, auto-switch the paragraph language when you typed in the wrong one, and re-run grammar checking in the correct language. Local (langdetect) requires Settings → Python venv with
langdetectinstalled (same venv as embeddings). Use AI (LLM) instead if you prefer your chat model for detection. Configure Settings → Doc → Sentence language detection (Off/AI (LLM)/Local (langdetect)). - Cross-Document Research: Say my or our in the sidebar (e.g. “pull Q4 from our budget spreadsheet”) to read other files in the same folder as your saved document; edits stay on the active doc.
- Optional folder search cache (off by default; enable Embeddings + FTS in Settings → Vector Search) builds beside your documents in
writeragent_embeddings/(supports both ODF and OOXML formats, and old binary (DOC) formats: one**corpus.db** (FTS5 + sqlite-vec). Experimental backends: Zvec and LanceDB. Default model is**paraphrase-multilingual-MiniLM-L12-v2**for multilingual support. LLMS use**search_nearby_files**— keyword (BM25/NEAR) and semantic hits merged with Reciprocal Rank Fusion (RRF). Multi-document plan · Embeddings & hybrid search. Venv packages:sentence-transformers numpy sqlite-vec langgraph langchain-core langchain-text-splitters envwrap odfpy.
- Run Python Script: Tools → Run Python Script… — built-in sections Analysis, Viz, Math, Units, Quant, Optimize, Vision, SQL (DuckDB; folder files + live/named Calc ranges; requires
duckdbin venv) (set Data range where applicable, editparamsif needed, run). Configure venv in Settings → Python. SQL is also available to the chat analysis sub-agent viaquery_folder_sql. - Monaco Editor UI Packages:
pywebview,rocher,jedi,PyQt6,PyQt6-WebEngine,qtpy(Monaco editor HTML/JS/CSS + runtime served fromrocherin the venv). Use the Test button in Settings to see which packages are installed. - Shared Code Cell: Store your code in a cell (e.g.,
A1) and reference it across multiple formulas (e.g.,=PY($A$1; B1)). - Shared Kernel: Keeps a persistent, single global Python namespace per Calc workbook across all
=PY()cells. This allows cells to share variables, imports, and state, mimicking Jupyter notebook behavior. Enable it in Settings → Python → Python session mode → Shared kernel, and use WriterAgent → Reset Python Session to clear variables for the active workbook. - Initialization Scripts: Run a workbook startup script once per workbook in a dedicated initialization session (even when session mode is Isolated) to handle expensive setup or seed global constants. Edit it via WriterAgent → Edit Initialization Script… (Calc only).
- Document-Attached Scripts: Save and manage Python scripts directly inside document custom properties rather than just in your personal user-profile library. This ensures your custom scripts travel with the document when shared. Access this in the script run dialog under "This Document" to attach, save, or run document-backed scripts.
- Safety & Isolation: Code runs safely in a separate process and is evaluated by a custom AST-based executor (adapted from Hugging Face smolagents) that acts as a secure sandbox which blocks dangerous modules (like
os,subprocess, orsys) and functions (likeevalorexec), ensuring that the AI can only perform safe, mathematical, and data-processing tasks. - High performance: Compact pickle Protocol 5 + Split-grid binary blob serialization for numbers, 50x faster and 60% smaller than standard JSON lists.
- Auto-imported Packages:
numpy(asnp),pandas(aspd),sympy(assp), standard librarymath,datetime,re,random,statistics,collections,itertools,json, andcsvare auto-imported to avoid needing manual imports.
Analysis helpers (detail)
| Helper | Purpose |
|---|---|
describe_data |
Extended EDA + column quality |
kpi_summary |
Aggregate mean/min/max/sum for metrics |
detect_outliers |
IQR, z-score, or isolation forest |
quick_stats |
Compact metric card |
format_currency / format_percent |
Display formatters |
clean_and_prepare |
Dedupe, simple imputation |
pivot_aggregate |
Pivot table wrapper |
group_summary |
Group-by aggregates |
compare_periods |
YoY/QoQ/MoM comparisons |
correlation_matrix |
Top correlated pairs |
run_regression |
OLS via statsmodels |
cluster_numeric |
KMeans centroids |
monte_carlo |
Monte Carlo resampling |
calc_goal_seek |
Single-variable what-if (native Calc, no venv) |
calc_solver |
Constrained optimization on formulas (native Calc) |
| Feature | Screenshot |
|---|---|
| Hermes + Opus 4.6 (Web Research) | ![]() |
| Arch Linux Resume | ![]() |
| Spreadsheet Dashboard | ![]() |
| Math Expressions | ![]() |
| Python in LibreOffice | ![]() |
| Sonnet diagram of an Arch Linux deity | ![]() |
Private, local web searches and fact-checking with citable sources. No data leaves your machine unless you opt into cloud APIs.
Powered by Hugging Face smolagents (vendored and adapted to have zero dependencies, per this discussion). Now you can ask the AI a question and it will search the web and give you the answer—with all requests running directly from your computer. It uses DuckDuckGo for privacy and executes the entire search-and-browse loop locally, ensuring your research stays private.
It's better than a standard Google search box because it understands natural language and can synthesize information from multiple pages.
- Ask a question: "What is the current version of Python and when was it released?"
- Complex Tasks: "Write a long and pretty summary of After the Software Wars, according to Wikipedia."
- Real-time Data: Ask it to find the current price of a specific item and it can update your document with current data.
- Two-Layer Editing: Basic grammar fixes first, then detailed "add comment" feedback.
- Formatting Preservation: Maintains styles, tables, and images during edits.
WriterAgent is "format-aware." Unlike simpler plugins that strip away your hard work, our engine is designed to respect your document's visual integrity.
- Format Preservation: When fixing typos or rephrasing, WriterAgent uses a "surgical" replacement method. It preserves your existing bold, italics, highlights, and font sizes—even if the AI sends back plain text.
- HTML-First Architecture: For complex elements like tables, nested lists, and colored layouts, we use a robust HTML import layer. This ensures that what the AI "sees" and what it "writes" matches the professional standards of LibreOffice.
- Legacy Support: Optimized to work perfectly even on older versions of LibreOffice (pre-26.2) where native Markdown support is unavailable.
- Tracked Changes Support: Proper handling of tracked deletions, and streamed rewrite with single-undo.
One of the unique challenges of building an AI assistant for a rich word processor, unlike a plain-text code editor, is the multiple ways of applying formatting. Eventually, we will encourage models to output properly classed HTML that maps to your LibreOffice template. See LLM_STYLES.md and Styles & Formatting.
Enable integration with Model Context Protocol (MCP) for advanced AI workflows.
When enabled in WriterAgent > Settings, an HTTP server runs on localhost and exposes the same Writer/Calc/Draw tools to external AI clients (Cursor, LM Studio, Claude Desktop, etc.).
Configure the MCP endpoint URL (default port 8765):
{
"mcpServers": {
"writeragent": {
"url": "http://localhost:8765/mcp"
}
}
}Use the URL from MCP Server Status (includes the /mcp path). Enable MCP Server in Settings.
Important for integrators: MCP exposes core document tools plus delegate_to_specialized_writer_toolset. The MCP tools/list does not change with the delegate call. The current design delegates to a separate inner agent with a special toolset and a clear task (shapes, web research, etc.). That is simpler than giving the outer MCP model dozens of LO APIs to juggle over a session. The internal agent stack is required for the background grammar checker. See docs/mcp-protocol.md — MCP architecture for developers.
- Real-time Sidebar Monitoring: All MCP activity (requests and tool results) is logged in real-time in the sidebar.
- Hybrid AI Orchestrator Model: This exposes the entire toolset to external agents while maintaining the document as the single source of truth.
By default, MCP uses LibreOffice's active document (whichever window has focus). That is fine with a single file open, but it is unreliable when several documents are open or focus changes while an external client (Cursor, a script, etc.) is running.
To target a specific open document, you can either:
**document_urlparameter**: Pass thedocument_urloptional parameter directly in the tool call arguments (now dynamically supported on all tools). This is the cleanest and most standard way in MCP.**X-Document-URLheader**: Send the HTTP header on each MCP request (tools/list,tools/call, …). The value must be the exact LibreOffice URL of an already-open document (usuallyfile:///…for saved files).
To discover all currently open document URLs, names, and types, you can call the MCP-only tool **list_open_documents**.
Targeting is per-request: one call can edit a Writer doc and the next can target a Calc sheet.
curl -X POST http://localhost:8765/mcp \
-H 'Content-Type: application/json' \
-H 'Expect:' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_document_content","arguments":{"document_url":"file:///home/user/report.odt"}}}'MCP server config JSON typically sets only the endpoint URL; your client or wrapper must attach document_url or the X-Document-URL header per call. See docs/mcp-protocol.md (Document Targeting) and [scripts/mcp_live_smoke.py](scripts/mcp_live_smoke.py) (--document-url).
Meta / integration helpers (recommended for Cursor and agent users):
- Cursor users: Install the dedicated Cursor plugin for rules + skills when working with LibreOffice/WriterAgent: https://github.com/KeithCu/cursor-libreoffice
- Agent frameworks (Hermes, custom MCP clients, etc.): Use the ready-made skill definition: https://github.com/KeithCu/libreoffice-skill (includes setup guidance and best practices for
document_url+ multi-doc targeting).
- Local: Ollama, LM Studio, or custom servers (e.g.,
http://localhost:11434). - Cloud: OpenRouter, Together.AI, or any OpenAI-compatible API.
You can plug in external agent backends so that Chat with Document uses an external process (e.g., Hermes or others) instead of the built-in LLM.
- Hermes ACP Integration: Spawns Hermes locally as a subprocess using the Agent Communication Protocol (ACP) via stdio.
- Grok Build (ACP): Spawns xAI's Grok Build CLI WriterAgent uses the CLI's cached login. Note, an endpoint in Settings is required for the nested tool-calling.
- HITL (Approve/Reject): If a backend requests approval for a tool call, a dialog appears for the user.
Figure 1: Unified state machine architecture for AI tool interactions.
WriterAgent is engineered for professional-grade reliability, moving beyond simple script-based plugins. WriterAgent Architecture Overview & Sidebar Implementation Guide.
-
Finite State Machine (FSM): All complex AI interactions are managed by a pure FSM. This architecture breaks down the extension's behavior into small, isolated, and testable units of logic. See Formal Verification.
-
JSON Repair: Uses a multi-stage parsing pipeline (inspired by Hermes) and json-repair to handle model syntax errors or Python-style literals. LLM Hacks & Workarounds.
-
Async Threading: A custom worker-pool and queue system keep the LibreOffice UI responsive during heavy reasoning. Streaming & Threading & Threading Architecture.
-
Static Analysis: Type Checking with (
ty,Mypy, andPyright). -
Comprehensive Test Suite: Thousands of tests ensuring stability. Test Architecture.
Help us improve. WriterAgent is actively used and heavily tested (thousands of automated tests), with architecture aimed at professional reliability. Even so, the problem space is enormous: LibreOffice’s feature set and UNO API, dozens of LLM backends and models, multiple operating systems, 34 locales, and a growing feature set in Writer, Calc, and Draw. You may hit a rough edge—a model that formats tool calls oddly, a Calc formula path that isn't covered, or a locale-specific quirk.
We especially welcome people who like to explore and either : file a GitHub issue with steps to reproduce, or open a PR. Curious tinkerers are valuable and there is documentation on every feature. If you use Python in LibreOffice (
=PY()/=PYTHON(), etc.), we’d love your input on any holes. Even a star helps.
The primary focus is deep LibreOffice Fidelity—systematically closing the gap between the AI's capabilities and the full breadth of the UNO API to ensure the agent can manipulate every professional feature the suite offers.
The application-specific roadmap is focused on closing the remaining gaps in the LibreOffice API surface:
- 🖋️ Writer: This is expanding from text and style management into complex document automation, including Mail Merge (CSV/DB/Sheets), Bibliographies, and Watermark support. We are also evolving our Sections tools from read-only navigation to a full lifecycle suite (multi-column layouts, conditional visibility, and password protection).
- 📊 Calc: Beyond cell and sheet manipulation, this is targeting advanced data modeling. This includes Macros & VBA compatibility, Scenarios (what-if analysis), and External Data integration (SQL/Web queries). We are also working toward interactive controls like Table Slicers, comprehensive Sheet Protection, and Python/NumPy support.
- 🎨 Draw & Impress: This is moving toward full presentation mastery by adding support for Slide Animations, Layer Management, and Slide Show Controls. High-priority multimedia support, including Audio/Video insertion and 3D Shape manipulation, will round out the creative suite.
Cross-document reads (shipped): Sidebar chat can already discover and read sibling Writer, Calc, and Draw files in the same folder as your saved document (see multi-document plan). Still ahead: configurable extra directories, @ mention UI, headless opens, and broader directory-wide synthesis.
Building on this foundation, we are working on long-document navigation for 100+ page files—internal caching and a page-at-a-time system so the agent can move through large files while keeping awareness of nested elements.
WriterAgent stands on the shoulders of giants. We'd like to give credit to:
| Project | Contribution |
|---|---|
| LibreCalc AI Assistant | AI support for LibreOffice Calc provided the foundation and inspiration for our integration |
| LibreOffice MCP Extension | Embedded MCP server reference; we used their Makefile system, modular discoverable service registry, and tool registry |
| Hermes Agent | Client-side tool call parsers and JSON repair, memory, humanizer skill, CDP support |
| latex2mathml | Converts LaTeX to MathML |
Units & dimensional analysis (Pint)
Trusted Units Helpers are now shipped for Writer and Calc: convert, parse, format, and dimensionally-check physical quantities via Pint. Use Run Python Script → Units Helpers ([Units] convert_quantity, …), edit params, and run. Writer inserts formatted text at the selection; Calc writes a single cell by default (e.g. 36 km/h) or a detailed key-value grid with output_style: "detailed". Pint package required; Settings → Python Data Engineering Libraries confirms availability. Details: Data Engineering / Units.
LLM Evaluation Suite & Efficiency Rankings
We have recently integrated an internal LLM Evaluation Suite directly into the LibreOffice UI. This allows users and developers to benchmark models across 10 (so far) real-world tasks in Writer, Calc, and Draw, tracking both accuracy and Intelligence-per-Dollar (IpD). By fetching real-time pricing from OpenRouter, the system calculates the exact cost of every AI turn and ranks backends by Value (C²/$)—average correctness squared, divided by average dollars per run (higher is better).
| Rank | Model | Avg correctness | Avg score | Avg tokens | Avg cost ($) | Value (C²/$) |
|---|---|---|---|---|---|---|
| 1 | openai/gpt-oss-120b | 0.980 | 0.942 | 3767.1 | 0.00025 | 3827.240 |
| 2 | google/gemini-3-flash-preview | 0.890 | 0.860 | 2957.2 | 0.00035 | 2234.257 |
| 3 | qwen/qwen3.5-9b | 0.730 | 0.691 | 4645.0 | 0.00050 | 1068.806 |
| 4 | nvidia/nemotron-3-nano-30b-a3b | 0.922 | 0.851 | 7195.5 | 0.00082 | 1037.536 |
| 5 | mistralai/devstral-2512 | 0.980 | 0.950 | 3000.8 | 0.00154 | 623.434 |
| 6 | inception/mercury-2 | 0.948 | 0.896 | 5150.9 | 0.00160 | 562.405 |
| 7 | minimax/minimax-m2.7 | 0.990 | 0.943 | 4671.9 | 0.00191 | 512.581 |
| 8 | deepseek/deepseek-v3.2 | 0.985 | 0.909 | 7575.4 | 0.00206 | 470.222 |
| 9 | qwen/qwen3.5-35b-a3b | 0.990 | 0.933 | 5671.1 | 0.00220 | 445.760 |
| 10 | x-ai/grok-4.1-fast | 0.950 | 0.886 | 6431.9 | 0.00204 | 442.733 |
| 11 | qwen/qwen3.5-27b | 0.993 | 0.942 | 5049.9 | 0.00259 | 380.538 |
| 12 | qwen/qwen3.5-122b-a10b | 0.990 | 0.950 | 3958.8 | 0.00308 | 318.312 |
| 13 | nvidia/nemotron-3-super-120b-a12b:free | 0.757 | 0.696 | 6388.4 | 0.00181 | 317.859 |
| 14 | allenai/olmo-3.1-32b-instruct | 0.323 | 0.306 | 1912.4 | 0.00046 | 226.704 |
| 15 | z-ai/glm-5.1 | 0.890 | 0.843 | 4677.8 | 0.00524 | 151.141 |
Quadratic utility (Value = C² ÷ average USD per run) on hardened, realistic Writer tasks highlights a few patterns that raw "accuracy only" tables can hide:
Qwen 3.5-35B-A3B (rank 9) uses more tokens per run on average (~5,671) than Qwen 3.5-122B-A10B (rank 12, ~3,959), but its lower average cost per run (~0.00220 vs ~0.00308) still yields a higher Value (C²/$) (~446 vs ~318). Token count alone does not determine dollar efficiency; list pricing and usage patterns interact.
OLMo 3.1 32B Instruct (rank 14) shows ~0.32 average correctness—squaring it crushes value despite a low ~0.00046 average cost. Nemotron 3 Super 120B (free) (rank 13) sits at ~0.76 correctness with mediocre value, a reminder that "free" or inexpensive is not enough when quality collapses.
openai/gpt-oss-120b (rank 1) pairs ~0.98 average correctness with a very low ~0.00025 average cost per run, for Value (C²/$) ≈ 3827. Google Gemini 3 Flash (rank 2) remains a strong second (~0.89 correctness, Value ≈ 2234) on this snapshot.
Qwen 3.5-27B (rank 11) reaches ~0.993 average correctness—among the highest in the table—while x-ai/grok-4.1-fast (rank 10) sits at ~0.95 with similar average cost. Both are useful "accuracy-first" options when the ranking metric is dominated by models with even lower $/run at the top.
This benchmarking framework is used to tune system prompts and select the best-performing models for local-first office automation. Details: scripts/prompt_optimization/README.md.
Sophisticated LLM-as-a-Judge Scoring. We have moved beyond simple keyword matching to a nuanced, multi-dimensional evaluation system. A high-tier "Teacher" model (typically Claude Sonnet 4.6) generates gold-standard answers, while a specialized "Judge" model (Grok 4.1 Fast) evaluates performance using a weighted rubric.
This framework allows us to differentiate between "Flash" models that prioritize speed and "Frontier" models that possess the "taste" and refinement needed for professional documents.
Fine-tuning. An interesting direction is to fine-tune a model specifically for this tool set and task distribution: the same correctness could potentially be achieved with fewer reasoning steps and fewer tokens, improving both latency and Value (C²/$). The existing eval and dataset are a natural training signal (correct vs incorrect tool use, minimal vs verbose traces).
- Download the latest
.oxtfile from the releases page. - Double-click the downloaded
.oxtfile to install it in LibreOffice, then restart LibreOffice if prompted.
WriterAgent requires an OpenAI-compatible backend. Recommended options:
- Ollama: ollama.com (easiest for local usage)
- text-generation-webui: github.com/oobabooga/text-generation-webui
- OpenRouter / OpenAI: Cloud-based providers
For the GPU-poor: If you don't have a powerful GPU or an API key, consider OpenRouter (free models, but prompts may be used for training) or Together.AI (generous private free tier).
Configure your endpoint, model, and behavior in WriterAgent > Settings. The dialog includes Chat/Text (endpoint, models, API key, etc.), Image Settings (size, aspect ratio, gallery/frame options), Http (MCP server), Agent backends, and other tabs generated from the extension modules.
- Endpoint URL: e.g.,
http://localhost:11434for Ollama - Additional Instructions: A shared system prompt for all features with history support
- API Key: Required for cloud providers
- Connection Keep-Alive: Automatically enabled to reduce latency
- MCP Server: On the Http tab; when enabled, an HTTP server runs on the configured port (default 8765) for external AI clients. Use Toggle MCP Server and MCP Server Status from the menu
- Agent backends: On the Agent backends tab; enable an external backend (Aider or Hermes) so Chat uses that agent instead of the built-in LLM. Paths and arguments are optional per backend
- OpenRouter Chat Extras: Advanced provider configuration via JSON editing (Settings → General → Edit config file) for provider routing, model selection, and request metadata
For detailed configuration examples, see CONFIG_EXAMPLES.md.
A weekly chronicle of building a professional AI suite inside LibreOffice:
- Week 1: Initial fork, sidebar chat, multi-turn tools, and async streaming
- Week 2 & 3: MCP, research sub-agent, voice support, and evaluation dashboard
- Week 4-6: State machines, formal verification, and specialized toolsets
- Week 6 & 7: Async grammar checking and TeX import support
DeepWiki provides excellent analysis of the codebase, including visual dependency graphs
Update May 11, 2026: Removed dspy from pyproject.toml to remove dependencies like litellm. Run uv sync to update your .venv. If you want to do prompt optimization, install manually.
Prerequisites: Python 3.11+, uv, and LibreOffice with unopkg on your PATH. Run make check-setup to verify.
# Clone the repository
git clone https://github.com/KeithCu/writeragent.git
cd writeragent
# Install dependencies
uv sync
# Build the extension package (.oxt)
make build
# Full dev cycle: build + reinstall + restart LibreOffice + show log
make deploy
or
make deploy writer, calc, draw, or impress
# Run typecheckers (ty, mypy, pyright) then tests
make test
# See all available targets
make helpWriterAgent is released under the GNU General Public License v3 (or later). See LICENSE for the full text. This transition ensures all improvements remain open and reciprocal under GPL v3.
WriterAgent was originally released under the MPL 2.0 license. In 2026, it was transitioned to GPL v3 to ensure stronger protection for user freedoms and better compatibility with modern Python libraries.
| Year | Contribution | Contributor |
|---|---|---|
| 2024 | Original release | John Balis |
| 2025-2026 | Config, registries, build system | quazardous |
| 2026 | Calc integration features (originally MIT) | LibreCalc AI Assistant |
| 2026 | Modifications and relicensing | KeithCu |






