Skip to main content
KayanOS renders managed DOCX templates by reading tags from Word document parts and evaluating them against an approved context. A reliable template is more than valid JEXL: it uses the right Word structure, keeps control tags on their own paragraph or table row, handles empty data deliberately, and stays within the renderer’s safety limits. This guide is the authoring reference for tags. Start with Document templates for template lifecycle, versions, action binding, output formats, and administrative control. Upload validation parses tag text and balance, but it does not prove that a control tag occupies a permitted Word structural node. A control that is accidentally embedded in ordinary text can receive a clean upload summary and still render incorrectly or disappear. Treat a generated-file render as mandatory evidence for every if, each, else, and include placement. The renderer processes the main document plus Word headers, footers, footnotes, endnotes, and comments. Keep one reviewed source DOCX and test each location that contains a tag; a tag in a header has the same expression rules as a tag in the body, but its layout still needs visual review in the final document. KayanOS managed document-template setup for a public-service acknowledgement, including its filename expression and execution mode.

Author tags with the AI helper

The AI helper can propose the same supported tag surface described here, but it does not relax any renderer rule. Start it with Create with AI helper or Versions → Revise with AI helper, provide an authorized entity/sample or bounded manual JSON context, acknowledge the configured-provider disclosure, and give a narrowly scoped instruction. KayanOS sends normalized document text and authorized context—not the raw DOCX archive or XML—and preserves wording/layout unless the instruction explicitly authorizes a bounded rewrite. Human review remains mandatory. Inspect tag placement, the change summary, and the generated file. Resolve reviewable or ambiguous path mappings before approval; if PDF is unavailable, download DOCX and explicitly acknowledge DOCX-only review. The helper does not expand read or administration rights, change action bindings, or bypass the limits below. Its temporary draft expires after 24 inactive hours and no later than seven days after creation.

When to use it

Use tags when a document sentence, table, image, link, QR code, or repeated block must reflect stored data. Good examples are a request reference, resident name, list of supplied documents, public appointment URL, service-office logo, or a table of inspection visits. Keep policy decisions in the record and use a tag only to show the already approved result. Do not use a template tag to bypass an action, manufacture a serial reference, or query a broad population “just in case.” If a reviewer must decide the result, model that decision with controlled fields and render the selected result. If an expression becomes hard to read, store or calculate the approved source value first and render the simple key.

Configuration

Word authoring rules

Write a tag with double braces: {{ expression }}. Inline text and inline tags can share one Word paragraph, for example Reference: {{ $record.request_reference }}. The renderer combines text spread across Word runs, so a simple expression can still resolve when Word split its characters during formatting. Even so, keep each tag visually simple: do not hide punctuation inside a styled run, and retype a tag rather than pasting invisible formatting if validation behaves unexpectedly. Control tags are different. At render time, opening and closing if or each tags, else, and an include must be the only content of a complete Word paragraph or table row. This is how the renderer selects, removes, repeats, or imports whole Word nodes. Put a loop opening tag in its own paragraph or row, put the repeatable paragraph or row between it and the closing tag, and put the closing tag in its own paragraph or row. An include that contains any other text in that paragraph or row is rejected. Upload validation cannot certify this placement, so render a saved test record after each structural change. Use this layout for a conditional paragraph:
The first, third, and fifth paragraphs contain only a control tag. Do not put a control marker after a greeting in the same paragraph and expect the greeting to become conditional.

Available context and inline expressions

An entity-record render context provides the following roots: Any ordinary tag is evaluated as JEXL and converted to document text. A null or undefined result becomes an empty string. Guard optional data so the document remains understandable:
The parser validates balanced if and each blocks. An if requires an expression, and an each must use the exact grammar {{#each expression as item}}. The renderer treats a non-array loop expression as an empty collection, so a misspelled key can silently produce no rows; test a populated record as well as an empty one.

Repeat paragraphs and table rows

Inside an each block, the alias belongs to the current item. KayanOS also sets $index, which is zero-based, plus $first and $last Boolean values for that iteration. A loop repeats the complete Word paragraphs or table rows between its opening and closing controls. This makes it suitable for a notice with several required documents or a table with several inspections. For a table, use separate rows for the controls:
The renderer enforces a total of 10,000 loop iterations across the render and a nesting depth of 20. Keep loops narrow and avoid nested lookups inside a large collection. Use $first or $last only for presentation, such as inserting a separator or a final instruction; they do not change record access.

Rich tags and includes

Rich tags are supported only with the exact command name and options. Options are whitespace-separated key=value tokens, so use simple values without spaces or prepare a short stored value first. For a managed render, an image value can be an approved HTTPS public URL, a file-reference object containing fileId, or a base64 data URL in the form data:image/png|jpeg|jpg|webp;base64,.... Supported raster content types are JPEG, JPG, PNG, and WebP, and image bytes are limited to 10 MiB. A missing non-optional image stops rendering. optional=true is appropriate only when an absent value may yield no image at all; it does not turn a broken URL, failed download, unsupported content type, invalid data URL, unreadable raster, or oversized image into a safe omission. Test the exact source used by the template. Use approved public destinations for links and QR codes:
An include resolves the included template’s current version, detects include cycles, and permits at most five nested include levels. It imports a body fragment, so do not rely on a child template bringing Word styles that the parent does not have; unsupported subtemplate style dependencies are rejected. Keep shared clauses, such as standard privacy wording, small and independently testable.

Look up records deliberately

The getRecords JEXL function accepts an object with a required entityKey and optional q, filters, limit, sorting, and search. Store the lookup object in the selected record context and use it in a structural loop:
In managed actions, each getRecords call is clamped to a minimum of 1 and a maximum of 500 rows; the service records returned row counts in the render audit. Use a small limit and a deterministic filter. In caller mode, the query runs with the requesting member’s access. In admin mode, it runs as the system administrator; when the action config contains allowed entities, any other entity key is rejected. Do not represent the renderer type’s declared 5,000-row field as an enforced aggregate lookup limit: the source-backed managed-action guard is the 500-row cap per call.

Unsupported content and hard limits

KayanOS rejects raw XML insertion, including {{@rawXml ...}} or {{rawXml ...}}. It also reports @html and @chart tags as unsupported. Do not try to work around those limits by inserting XML, HTML, or script-like content into an expression; use normal DOCX content, a supported image, or a reviewed upstream value. The renderer also enforces a 15-second render timeout, an 80 MiB rendered-output limit, the 10 MiB image limit, the 10,000 total-loop limit, 20 levels of structural nesting, and five levels of nested includes. These are safety boundaries, not performance targets. Design documents that are much smaller than each ceiling. The upload check also protects the DOCX package itself. It rejects an unreadable ZIP, unsafe entry paths, more than 2,000 entries, more than 80 MiB of uncompressed content, or a compression ratio above 100:1. It rejects macro-enabled parts, OLE or embedded binary parts, XML DTD/entity declarations, and unsafe external relationships; ordinary http, https, and mailto hyperlinks are the allowed external relationship case. Start from a clean .docx source rather than attempting to strip macros or embedded objects after a rejection.

Worked example

A Syrian public-service office issues an acknowledgement for a resident-service request. The letter shows a serial request reference, lists required documents that were received, includes an optional office logo, links to a public status page, and starts a separate page for a standard next-steps clause. The template must not show an approval decision unless the controlled record status already says it is approved. The owner prepares $record.required_documents as an array of objects with name and status. In Word, they create a three-column table and place the each opening tag in one empty control row, the repeatable document row in the next row, and the close tag in a final control row. They add a conditional paragraph for a missing appointment and an inline status link. The document contains three meaningful test cases: no documents, one document, and several documents. For a safe optional logo, the author uses:
They render a saved request that has a serial, a public-status URL, and three document rows. The expected outcome is one acknowledgement whose rows are complete, whose optional logo does not leave a broken placeholder when its value is absent, and whose wording stays appropriate to a request that is still under review.

Testing

Test tag behavior with real Word structures, not a plain-text copy of a template. Upload validation detects package issues and some malformed grammar; a render test detects structural-control placement, missing data, inaccessible lookups, unresolved assets, and layout problems. When validation reports a problem, correct the Word source and upload a new template version. Do not hide a broken tag in white text, put a control marker in a table cell with other text, or rely on a viewer to ignore invalid content.

Troubleshooting

Permissions and data-quality limits

Tag authoring does not grant access. Managed-template administration is a separate Builder-level administrator capability: it controls template files, versions, action configs, validation, and test rendering. A document action’s caller or admin mode controls how its runtime lookups are executed. Keep these concerns distinct in review: a person may be allowed to use an approved caller-mode action without being allowed to upload a new template or switch an action to admin mode. Use caller mode whenever the document should reflect only records the requesting member can read. An admin action requires explicit governance because it can query as the system administrator; constrain allowed entities, set narrow filters, review every requested field, and treat the rendered output as sensitive. The output may expose derived information even when a field is not shown directly, so apply the same disclosure review to counts, labels, link targets, and QR values. Avoid secrets, authentication material, unreviewed identifiers, or sensitive internal notes in expressions, QR codes, URLs, alt text, filename rules, and lookup filters. The render audit is useful for diagnosis, but it is not a substitute for legal wording review, approval controls, or the organization’s retention rules.