# Document Templates

Turn workspace data into finished documents — invoices, contracts, reports, letters,
labels, emails — by filling a reusable template instead of writing a file from scratch.
You register a template once, then generate a filled file (or a rendered email) from it as
many times as you like, feeding it data from records, a workflow, or an agent run.

This is a **capability + usage** guide. For the exact input schema of any tool named here,
run `lotics tools <tool_name>` — that is always the source of truth for arguments.

## The five template types

| Type | What it fills | Output | Create with |
|---|---|---|---|
| `pdf-form` | fields overlaid on an **uploaded PDF** at fixed positions | PDF | `create_pdf_template` (mode `form`) |
| `html` (a PDF) | an **HTML + Handlebars** layout you write from scratch | PDF | `create_pdf_template` (mode `html`) |
| `excel` | an **uploaded `.xlsx`** with `{{marker}}` cells | `.xlsx` | `create_excel_template` |
| `word` | an **uploaded `.docx`** with `{{marker}}`s | `.docx` | `create_word_template` |
| `email` | an **inline HTML + Handlebars** body, rendered when the email is sent | email | `create_email_template` |

Two shapes underneath: **file-backed** (`pdf-form`, `excel`, `word`) clone an uploaded
office file and mark it up; **inline** (`html`, `email`) store the markup you author directly.

## The lifecycle: create → generate → chain

1. **Create** a template — register the file (or inline markup) and declare a `variables`
   map (the named slots the template fills). This returns a template id (`dtl_…`).
2. **Generate** a filled file — call the matching `generate_*_from_template` with the
   template id, a `filename` (no extension), and a `data` map keyed by your variable names.
   It substitutes the markers and returns a **generated file** (with a `file_id`).
3. **Chain** the result — generation only *produces* the file. Attaching it to a record,
   sending it, or saving it locally is a separate step: inside a workflow, pass the returned
   `file_id` to the next step; from the CLI, `lotics download <file_id>` fetches it.

Email is the exception: there is **no** `generate_email_from_template`. An email template is
rendered to a subject + body **at send time** from the template and the data the send step
supplies — so you author it with `create_email_template` and a workflow/app send step (or the
web composer) does the rendering and delivery. External agents send their own email directly.

## Creating each type

### PDF from HTML (`create_pdf_template`, mode `html`)

Write a full HTML document with inline CSS and `{{variable}}` placeholders; it renders to PDF
via a headless browser. Good for invoices, reports, letters, certificates — anything whose
layout you control. Declare `variables` (plain text, rich `html`, an auto-rendered `table`,
or a `list`), and optionally `format` (page size) and `orientation`. See
`lotics tools create_pdf_template` for the exact variable shapes.

### PDF form (`create_pdf_template`, mode `form`)

For an existing PDF you must fill in place (a government form, a printed contract):

1. `lotics upload ./form.pdf` → a `file_id`.
2. `create_pdf_template` with mode `form` and that `file_id`.
3. `analyze_pdf_template` — extracts the labels and their positions off the page.
4. `update_pdf_template` — define the positioned fields (`text` / `checkbox` / `image`, each
   with a page + x/y/size) in `variables`.

Form-mode data is scalar-only (text, numbers, checkboxes) — one value per positioned field.

### Excel (`create_excel_template`)

1. Build a `.xlsx` in Excel (or by scripting `@lotics/xlsx`) and put `{{marker}}`s in the cells that
   should be filled. `lotics upload ./template.xlsx` → a `file_id`.
2. `create_excel_template` with that `template_file_id` and a `variables` map. Markers are
   **validated at create time** — a structural error (mismatched loop, unknown helper, bad
   placement) blocks the save, and declared variables with no matching marker come back in
   `unmarked_variables` (skipped, not filled).

To inspect or add markers on the uploaded file without leaving the CLI: `excel_get_range` /
`excel_find_cells` to look, `excel_update_range` to write markers, `validate_excel_template`
to re-check. Pass raw numbers / ISO dates / booleans at generate time — the cell's number
format handles display.

### Word (`create_word_template`)

1. Build a `.docx` with `{{marker}}`s where values go. `lotics upload ./template.docx`.
2. `create_word_template` with the `template_file_id`. `variables` is optional — every
   marker in the document is derived automatically (`{{name}}` → string,
   `{{FOR … IN name}}` → array, `{{IF name}}` → boolean). When you do declare, an unmarked
   declaration comes back in `unmarked_variables` and is skipped, and markers you didn't
   declare are still auto-added (`derived_variables`) — the stored contract always covers
   every marker in the document.

At generate time, `data` must provide a key for **every** marker — pass `""` for fields
that should render blank; a missing key fails with the full list of missing markers.

To read the uploaded file before marking it: `word_get_content`, `word_find_text`,
`word_get_table_data`. To add markers/loops/conditionals: `word_replace_text`,
`word_insert_loop`, `word_insert_conditional` — unmarking is `word_replace_text` putting the
plain text back.

### Email (`create_email_template`)

Inline HTML + Handlebars, no uploaded file. Declare `variables`, and optionally a default
`subject` (which itself supports `{{variable}}` expressions) and default to/cc/bcc. The body
and subject render from the data at send time.

## Markers, at a usage level

Every type supports three shapes of substitution. The exact syntax differs per engine — read
the create-tool description for the reference; here is the capability:

- **Scalar** — a single value in one spot: `{{name}}`, `{{total}}`. Whole-cell scalars in
  Excel preserve their type via the cell's number format.
- **Repeating rows / line items** — one template row rendered once per item in a list, for
  invoice lines, order rows, tables. Excel and the HTML/email engines use a Handlebars-style
  `{{#each items}}…{{/each}}`; Word uses `{{FOR item IN items}}…{{$item.field}}…{{END-FOR item}}`
  (the `word_insert_loop` tool writes these command rows for you). The HTML and email types
  also offer an auto-rendered `table` variable — declare its columns and pass an array, no
  hand-written loop. (Excel always uses the `{{#each}}` marker rows — it has no auto-rendered
  `table` type; its variable types are string/number/date/boolean/array.)
- **Conditional sections** — a block shown only when a condition holds (a "paid" stamp, an
  optional notes block). Excel/HTML/email use `{{#if}}…{{else}}…{{/if}}`; Word uses
  `word_insert_conditional`.

Run `lotics tools create_excel_template`, `create_word_template`, `create_pdf_template`, or
`create_email_template` for each engine's exact marker grammar and helper list — don't guess it.

## Generating a filled file

```bash
# See what a template expects, then fill it
lotics tools generate_excel_from_template
lotics run get_template '{"template_id":"dtl_..."}'          # its declared variables
lotics run generate_excel_from_template '{"document_template_id":"dtl_...","filename":"invoice-1042","data":{"company_name":"Acme","total":1042,"items":[...]}}'
lotics download <file_id> -o ./out/
```

- `data` is a map keyed by your variable names. Scalars for scalar/form fields; arrays for
  `table`/`list`/loop variables. `filename` excludes the extension (the type sets it).
- Each `generate_*_from_template` returns a generated file object; take its `file_id` onward.
- In a workflow, a **generate step** calls the same tools and hands the `file_id` to the next
  step (attach to a record, send as an attachment, etc.) — see `docs/workflow_engine.md` in
  the platform docs.

## Discovering and managing templates

Four unified tools work across all five types:

| Tool | Does |
|---|---|
| `query_templates` | list templates (optionally filter by type: excel/word/pdf/email) |
| `get_template` | one template's full definition, incl. the `variables` it expects |
| `clone_template` | copy a template to iterate on |
| `delete_template` | remove a template |

Call `get_template` before generating when you don't already know a template's variable names.

## Reaching the tools

```bash
lotics tools                              # all categories
lotics tools create_word_template         # one tool: full description + input schema
lotics run <tool> '<json-args>'           # execute (inline JSON, @file.json, or piped stdin)
```

The template tools live in the categories **PDF Templates**, **Excel Templates**,
**Word Templates**, **Email Templates**, and **Templates** (the unified query/get/clone/delete).
Uploading the source file for a file-backed template is `lotics upload <file>`; fetching a
generated file is `lotics download <file_id>`.
