LX Draft — Writing Documents with an AI Agent

Version 2026-05-29

How an AI agent should author .lxdoc documents in markdown for LX Draft.

Click to copy the full guide as plain text, then paste it into your AI agent as a prompt. The agent will then know how to produce LX Draft documents.

What is an .lxdoc file?

A .lxdoc file is a UTF-8 text file with three parts:

  1. YAML frontmatter — metadata and document properties (between --- markers at the top)
  2. Markdown body — the actual content using standard Markdown plus a few extensions
  3. Optional document-assets and document-meta blocks — for embedded images and review data (you usually don't need these)

The simplest .lxdoc is just markdown wrapped in frontmatter:

---
format: "lxd/1.0"
title: "My Document"
revision: "v0.1"
status: "draft"
---

# My Document

This is the body. Standard Markdown works fine.

The integrity hash — do NOT write it

LX Draft stores a self-excluding SHA-256 hash in frontmatter.integrity to detect later tampering (it underpins signature auto-clear-on-edit). As an agent, never write or guess the integrity field — omit it entirely. LX Draft computes and injects the correct hash automatically when the document is saved or edited in the app. A hash you invent would be wrong and flag the document as modified. (Unsigned drafts don't need a hash at all; it only matters once a human/Lexis signs the document.)

Standalone vs Lexis (context you should know)

LX Draft is used two ways, and it affects governance (not how you write content):

As an agent you write the same markdown either way. Do not set lexis_controlled yourself, and do not try to sign documents — placing a {signature:...} field is enough; the human or Lexis performs the signing.

Required frontmatter fields

You MUST include these:

format: "lxd/1.0"           # always this exact value
title: "Document Title"     # required
revision: "v0.1"            # use v0.1 for first draft
status: "draft"             # draft | review | approved | released | obsolete

Add these whenever you have the information:

short_title: "Short Name"   # for headers / breadcrumbs
document_number: "T-XXX-001" # if there's a doc numbering scheme
date_created: 2026-03-30    # YYYY-MM-DD
classification: "internal"  # public | internal | commercial-in-confidence | restricted
template: "standard"        # standard | proposal | test-report | datasheet | minutes | review
project: "Project Name"
prepared_for: "Client Name"
author: "Your Name"
font: "Poppins"             # default body font; use Poppins unless told otherwise

Standard Markdown features (just use them)

These work as you'd expect from any Markdown:

LX-specific extensions (use these for engineering docs)

Callout boxes

Use these for tips, warnings, important notes:

> [!NOTE]
> Informational note. Blue left border.

> [!TIP]
> Helpful tip. Green left border, "Tip:" prefix.

> [!IMPORTANT]
> Important caveat. Amber left border, "Important:" prefix.

> [!WARNING]
> Warning text. Red left border, "Warning:" prefix.

> [!STEP]
> Procedural step. Blue left border, no prefix.

Tables (rich CSV blocks)

For engineering tables (BOMs, test matrices, requirements), use CSV blocks instead of pipe tables:

```csv:bom
reference,part_number,quantity,manufacturer
U1,STM32F405RGT6,1,STMicroelectronics
C1,CL21B104KBCNNNC,10,Samsung
R1,RC0805FR-07100KL,4,Yageo
```

The label after csv: describes the data type (e.g. bom, requirements, test-results). The editor renders these as editable grids.

Equations (LaTeX)

Inline math: $R = V / I$ where $V$ is voltage.

Block math:

$$
P_{total} = \sum_{i=1}^{n} V_i \cdot I_i
$$

Footnotes and endnotes

This statement needs a citation[^1].

This refers to an endnote[^note:pricing].

[^1]: Footnote text — typically appears at the bottom of the page.
[^note:pricing]: Endnote text — appears at the end of the document.

Cross-references and bookmarks

<!-- bookmark: thermal-section -->

See {ref:sec:introduction} for background.
Refer to {ref:bookmark:thermal-section|the thermal section} for details.

Document-property fields (live values from frontmatter)

You can embed a live reference to a frontmatter field in the body. It renders the current value of that field (and updates if the frontmatter changes), and resolves to the value in PDF/DOCX export. Use the {field:NAME} token:

Document number: {field:document_number}
Revision {field:revision} — prepared for {field:prepared_for}.

Valid field names: title, short_title, document_number, revision, author, status, classification, date_created, project, prepared_for.

In the editor, a human inserts these via the Insert Field toolbar button; as an agent, just write the {field:NAME} token in the markdown — it round-trips and resolves on export.

Signature fields

A signature field renders the signer's name (in a cursive font) once the document is signed, or a muted "Your signature here" placeholder when unsigned:

Signed: {signature:author}

Signing itself is a human/Lexis action (see "Standalone vs Lexis" above) — as an agent you place the {signature:...} token where the signature should appear; you do not sign the document.

Page breaks

If you need a hard page break in the printed output:

<!-- pagebreak -->

Multi-column sections

<!-- columns: 2 -->
Content here flows into two columns.
<!-- /columns -->

Text boxes (bordered content)

<!-- textbox -->
Content inside a bordered box.
<!-- /textbox -->

Images

For external images (URLs), use standard Markdown:

![Alt text describing the image](https://example.com/image.png)

For embedded images, use the asset reference syntax:

![Alt text](asset:my-image-id)

Then add the image to a document-assets block at the end of the file (see "Embedded images" below).

Size, alignment and crop are persisted as an HTML comment immediately after the image. You normally don't need to write these (the human adjusts images by dragging in the editor), but they round-trip and the exporter honours them:

![Alt text](asset:my-image-id)<!-- width=320 height=180 align=center crop=10,10,10,10 -->

Table of contents

Insert a self-updating TOC anywhere:

<!-- toc -->

The editor renders this as an actual TOC. In source form it stays as the directive.

Media attachments (preferred: deliver a bundle, don't base64 yourself)

Do not base64-encode media inside the .lxdoc. LLM output is unreliable for large binary blobs — you will silently truncate, corrupt, or hit token limits. Instead, deliver two things:

  1. A clean .lxdoc (or .md) file with asset:<id> references in the body.
  2. A .zip archive containing the actual media files, named to match those references.

LX Draft's import dialog has a "Document + Archive" tab that does the embedding for you — it reads the archive, matches each ref to a file, base64-encodes server/browser-side, and produces a self-contained .lxdoc.

Reference syntax in the markdown

Strongly preferred — use bare asset:<id> references with no folder prefix:

![Tag at 10 o'clock](asset:photo-013435032)
![PCB Layout](asset:pcb-rev-b)

Relative paths (./diagrams/field-plot.png) are accepted as a fallback — LX Draft matches them by exact path then by basename — but they couple the document to the directory layout. Avoid them in agent output.

Absolute filesystem paths (C:\..., /home/...) can never resolve in a browser. Don't use them.

Folder structure

The folder can be flat or have subfolders — both work, because LX Draft matches by filename stem. Filename stems must be unique within the bundle when you use asset:<id> references.

my-report/                        ← name doesn't matter; user picks this folder
├── photo-013435032.jpg           ← matches asset:photo-013435032
├── photo-013449261.jpg           ← matches asset:photo-013449261
└── pcb-rev-b.png                 ← matches asset:pcb-rev-b

If you have many media files of different types, put them in subfolders for your own organisation — the matcher still works:

my-report/
├── photos/
│   ├── photo-013435032.jpg       ← still matches asset:photo-013435032
│   └── photo-013449261.jpg
└── diagrams/
    └── pcb-rev-b.png             ← still matches asset:pcb-rev-b

The asset:<id> reference does not include the subfolder.

Supported media types

Anything LX Draft can render or link: png, jpg/jpeg, gif, webp, svg, bmp, tiff, pdf, mp4, webm, mp3, wav, ogg. The MIME type is inferred from the extension.

What to deliver to the human

You'll get the cleanest result if you deliver:
  1. The .lxdoc file (with asset: references, no document-assets block).
  2. A folder of media files matching those references.
The user uploads both via LX Draft's "Document + Archive" import tab — they can pick the folder directly (no zipping needed) or zip it first if their browser doesn't support folder upload.

You don't need to zip anything. Write the files into a folder; LX Draft reads only the files actually referenced by the document and ignores the rest.

If you absolutely cannot deliver media files (e.g. you only have URLs), use plain HTTPS image references. They'll work but won't be embedded — the document depends on the URL staying live.

Manual base64 embedding (only if you have no other option)

The format is documented for completeness. Avoid using it from an agent:

<!-- document-assets

- id: pcb-rev-b
  filename: pcb-layout-rev-b.png
  mime: image/png
  size: 145832
  data: iVBORw0KGgoAAAANSUhEUgAA[... full base64 string, no line breaks ...]

/document-assets -->

The data: field must be the complete base64 (no line breaks, no truncation). The size: field should match the original file's byte length.

Review markers (do NOT use unless instructed)

The <!--[c1]-->...<!--[/c1]--> and <!--{ch1:del}-->...<!--{/ch1}--> syntax is for review comments and tracked changes. Do not generate these manually. Use the API endpoints if you need to add review data programmatically.

How to use headings, paragraphs, and emphasis

Engineering documents are read for reference, not narrative. Structure beats prose. Use these tools deliberately:

Heading levels carry meaning

Don't skip levels. Going from ## straight to #### confuses readers and breaks the table of contents.

Don't use # (H1) inside the body — the document title is in the frontmatter and rendered as the cover. Body sections start at ##.

Paragraphs vs callouts

Don't overuse callouts. If every other paragraph is a callout, none of them stand out.

Emphasis

Lists

Tables vs CSV blocks

Document structure for engineering documents

A typical LX engineering document has this structure:

---
[frontmatter]
---

<!-- toc -->

## 1 Introduction

Brief overview of the document and project.

## 2 Scope

What this document covers.

## 3 [Main content section]

### 3.1 Subsection

Content here.

### 3.2 Another subsection

```csv:requirements
id,description,criticality
REQ-001,System must boot in under 5 seconds,High
REQ-002,Battery life must exceed 8 hours,High
```

## 4 [Another main section]

## Appendix

### A. Additional Information

Three ways to deliver a document to LX Draft

If you're an agent producing a document, you have three options:

Option 1: Hand the user a .md file

Just write standard markdown. The user clicks "Import Markdown" in LX Draft and uploads the file. LX Draft wraps it in default frontmatter automatically.

Option 2: Hand the user a complete .lxdoc file

Write the full file with frontmatter. The user clicks "Import Markdown" → "Upload File" and selects the .lxdoc. It imports as-is.

Option 3: Use the agent-edit API directly

If you have programmatic access to the LX Draft API, use the stateless content-based endpoint. You pass the FULL current document as content and the new section text as content_to_apply; the response returns the rebuilt full document content for you to apply (LX Draft no longer stores documents server-side, so there is no :id):

POST /api/agent/edit
Content-Type: application/json

{
  "content": "<the full current .lxdoc text>",
  "section_heading": "3 DFM Review",
  "action": "replace",                  // replace | append | prepend
  "content_to_apply": "New markdown content...",
  "track_changes": true,
  "agent_name": "Your Agent Name"
}

Response: { ok: true, content: "<rebuilt full document>", section, action, validation }. The validator runs server-side; if the edit would make the document invalid you get a 422 with the issues to correct. Related stateless endpoints: POST /api/agent/sections ({content} → list of sections) and POST /api/spellcheck ({content}).

Common mistakes to avoid

Stuff agents have actually done that broke the import or rendering. Don't repeat these:

Validate your output before delivery

LX Draft has a public validation endpoint. Run your .lxdoc through it before handing the document to the user — you'll catch malformed YAML, missing required fields, broken asset references, and the rest of the issues listed above.

From the command line (Node 18+, no npm install needed; the script lives in the LX Draft repo):

node scripts/lint-lxdoc.mjs path/to/your/doc.lxdoc

It exits 0 on success and 1 on validation errors, so you can use it in scripts.

As an HTTP endpoint (for agents that have internet but not the LX Draft repo):

POST https://lxdraft.lx-cloud.com/api/validate-public
Content-Type: text/plain

<the entire .lxdoc content as the request body>

Returns:

{
  "valid": true,
  "issues": [
    { "rule": "V003", "severity": "warning", "message": "...", "location": "..." }
  ]
}

valid: false means there is at least one error-severity issue. Fix all errors before delivery; warnings are advisory.

Validation rules to follow

Your output will be validated. To avoid rejection:

Quick checklist before delivering

← Back to the LX Draft user guide

# Agent Writing Guide for LX Draft Documents

This guide tells AI agents how to write `.lxdoc` documents that LX Draft can render and edit. Give this guide to any agent that needs to produce engineering documents for the LX Design House team.

## What is an .lxdoc file?

A `.lxdoc` file is a UTF-8 text file with three parts:

1. **YAML frontmatter** — metadata and document properties (between `---` markers at the top)
2. **Markdown body** — the actual content using standard Markdown plus a few extensions
3. **Optional document-assets and document-meta blocks** — for embedded images and review data (you usually don't need these)

The simplest .lxdoc is just markdown wrapped in frontmatter:

```
---
format: "lxd/1.0"
title: "My Document"
revision: "v0.1"
status: "draft"
---

# My Document

This is the body. Standard Markdown works fine.
```

## The integrity hash — do NOT write it

LX Draft stores a self-excluding SHA-256 hash in `frontmatter.integrity` to
detect later tampering (it underpins signature auto-clear-on-edit). **As an
agent, never write or guess the `integrity` field — omit it entirely.** LX Draft
computes and injects the correct hash automatically when the document is saved
or edited in the app. A hash you invent would be wrong and flag the document as
modified. (Unsigned drafts don't need a hash at all; it only matters once a
human/Lexis signs the document.)

## Standalone vs Lexis (context you should know)

LX Draft is used two ways, and it affects governance (not how you write content):

- **Standalone** — the document is a plain `.lxdoc` file the user opens/saves on
  their own drive (or Google Drive). The user self-signs; revision history is a
  table they maintain.
- **Lexis-managed** — the document is a controlled project artifact. Lexis owns
  its lifecycle (releases, version history, signing). A controlled document
  carries `lexis_controlled: true` in its frontmatter.

As an agent you write the same markdown either way. Do **not** set
`lexis_controlled` yourself, and do **not** try to sign documents — placing a
`{signature:...}` field is enough; the human or Lexis performs the signing.

## Required frontmatter fields

You MUST include these:

```yaml
format: "lxd/1.0"           # always this exact value
title: "Document Title"     # required
revision: "v0.1"            # use v0.1 for first draft
status: "draft"             # draft | review | approved | released | obsolete
```

## Recommended frontmatter fields

Add these whenever you have the information:

```yaml
short_title: "Short Name"   # for headers / breadcrumbs
document_number: "T-XXX-001" # if there's a doc numbering scheme
date_created: 2026-03-30    # YYYY-MM-DD
classification: "internal"  # public | internal | commercial-in-confidence | restricted
template: "standard"        # standard | proposal | test-report | datasheet | minutes | review
project: "Project Name"
prepared_for: "Client Name"
author: "Your Name"
font: "Poppins"             # default body font; use Poppins unless told otherwise
```

## Standard Markdown features (just use them)

These work as you'd expect from any Markdown:

- `# H1` through `###### H6` for headings
- `**bold**`, `*italic*`, `~~strikethrough~~`, `` `inline code` ``
- `- bullet list` and `1. numbered list` (nest with 2-space indent)
- `| col | col |` pipe tables (with header separator row)
- `> blockquote`
- ` ```language ` fenced code blocks
- `[link text](https://url)` for hyperlinks
- `---` for horizontal rules

## LX-specific extensions (use these for engineering docs)

### Callout boxes

Use these for tips, warnings, important notes:

```markdown
> [!NOTE]
> Informational note. Blue left border.

> [!TIP]
> Helpful tip. Green left border, "Tip:" prefix.

> [!IMPORTANT]
> Important caveat. Amber left border, "Important:" prefix.

> [!WARNING]
> Warning text. Red left border, "Warning:" prefix.

> [!STEP]
> Procedural step. Blue left border, no prefix.
```

### Tables (rich CSV blocks)

For engineering tables (BOMs, test matrices, requirements), use CSV blocks instead of pipe tables:

````markdown
```csv:bom
reference,part_number,quantity,manufacturer
U1,STM32F405RGT6,1,STMicroelectronics
C1,CL21B104KBCNNNC,10,Samsung
R1,RC0805FR-07100KL,4,Yageo
```
````

The label after `csv:` describes the data type (e.g. `bom`, `requirements`, `test-results`). The editor renders these as editable grids.

### Equations (LaTeX)

```markdown
Inline math: $R = V / I$ where $V$ is voltage.

Block math:

$$
P_{total} = \sum_{i=1}^{n} V_i \cdot I_i
$$
```

### Footnotes and endnotes

```markdown
This statement needs a citation[^1].

This refers to an endnote[^note:pricing].

[^1]: Footnote text — typically appears at the bottom of the page.
[^note:pricing]: Endnote text — appears at the end of the document.
```

### Cross-references and bookmarks

```markdown


See {ref:sec:introduction} for background.
Refer to {ref:bookmark:thermal-section|the thermal section} for details.
```

### Document-property fields (live values from frontmatter)

You can embed a *live* reference to a frontmatter field in the body. It renders
the current value of that field (and updates if the frontmatter changes), and
resolves to the value in PDF/DOCX export. Use the `{field:NAME}` token:

```markdown
Document number: {field:document_number}
Revision {field:revision} — prepared for {field:prepared_for}.
```

Valid field names: `title`, `short_title`, `document_number`, `revision`,
`author`, `status`, `classification`, `date_created`, `project`, `prepared_for`.

In the editor, a human inserts these via the **Insert Field** toolbar button; as
an agent, just write the `{field:NAME}` token in the markdown — it round-trips
and resolves on export.

### Signature fields

A signature field renders the signer's name (in a cursive font) once the
document is signed, or a muted "Your signature here" placeholder when unsigned:

```markdown
Signed: {signature:author}
```

Signing itself is a human/Lexis action (see "Standalone vs Lexis" below) — as an
agent you place the `{signature:...}` token where the signature should appear;
you do not sign the document.

### Page breaks

If you need a hard page break in the printed output:

```markdown

```

### Multi-column sections

```markdown

Content here flows into two columns.

```

### Text boxes (bordered content)

```markdown

Content inside a bordered box.

```

### Images

For external images (URLs), use standard Markdown:

```markdown
![Alt text describing the image](https://example.com/image.png)
```

For embedded images, use the asset reference syntax:

```markdown
![Alt text](asset:my-image-id)
```

Then add the image to a `document-assets` block at the end of the file (see "Embedded images" below).

**Size, alignment and crop** are persisted as an HTML comment immediately after
the image. You normally don't need to write these (the human adjusts images by
dragging in the editor), but they round-trip and the exporter honours them:

```markdown
![Alt text](asset:my-image-id)
```

- `width` / `height` — display size in px.
- `align` — `left` | `center` | `right` | `inline`. `left`/`right` float the
  image so body text wraps around it; `center` is a centered block.
- `crop` — `top,right,bottom,left` inset in px (the visible region is the image
  minus these insets). Omit if not cropped.

### Table of contents

Insert a self-updating TOC anywhere:

```markdown

```

The editor renders this as an actual TOC. In source form it stays as the directive.

## Media attachments (preferred: deliver a bundle, don't base64 yourself)

**Do not base64-encode media inside the .lxdoc.** LLM output is unreliable for large binary blobs — you will silently truncate, corrupt, or hit token limits. Instead, deliver two things:

1. A clean **`.lxdoc` (or `.md`) file** with `asset:` references in the body.
2. A **`.zip` archive** containing the actual media files, named to match those references.

LX Draft's import dialog has a "Document + Archive" tab that does the embedding for you — it reads the archive, matches each ref to a file, base64-encodes server/browser-side, and produces a self-contained .lxdoc.

### Reference syntax in the markdown

**Strongly preferred — use bare `asset:` references with no folder prefix:**

```markdown
![Tag at 10 o'clock](asset:photo-013435032)
![PCB Layout](asset:pcb-rev-b)
```

- `` must match a filename **stem** somewhere in the bundle folder (e.g. `asset:photo-013435032` matches `photo-013435032.jpg`).
- The folder name is **irrelevant** — LX Draft strips the top-level folder when matching. Don't put the folder name in the reference.
- The id should be a slug: letters, digits, hyphens. No spaces, no slashes.
- **Don't write `![alt](photos/photo-1.jpg)` or `![alt](report-bundle/photo-1.jpg)`.** If you change the folder name later, every reference breaks. Use `![alt](asset:photo-1)` and let LX Draft handle the lookup.

Relative paths (`./diagrams/field-plot.png`) are accepted as a fallback — LX Draft matches them by exact path then by basename — but they couple the document to the directory layout. Avoid them in agent output.

Absolute filesystem paths (`C:\...`, `/home/...`) can never resolve in a browser. Don't use them.

### Folder structure

The folder can be flat or have subfolders — both work, because LX Draft matches by filename stem. Filename stems must be unique within the bundle when you use `asset:` references.

```
my-report/                        ← name doesn't matter; user picks this folder
├── photo-013435032.jpg           ← matches asset:photo-013435032
├── photo-013449261.jpg           ← matches asset:photo-013449261
└── pcb-rev-b.png                 ← matches asset:pcb-rev-b
```

If you have many media files of different types, put them in subfolders for your own organisation — the matcher still works:

```
my-report/
├── photos/
│   ├── photo-013435032.jpg       ← still matches asset:photo-013435032
│   └── photo-013449261.jpg
└── diagrams/
    └── pcb-rev-b.png             ← still matches asset:pcb-rev-b
```

The `asset:` reference does **not** include the subfolder.

### Supported media types

Anything LX Draft can render or link: `png`, `jpg`/`jpeg`, `gif`, `webp`, `svg`, `bmp`, `tiff`, `pdf`, `mp4`, `webm`, `mp3`, `wav`, `ogg`. The MIME type is inferred from the extension.

### What to deliver to the human

> **You'll get the cleanest result if you deliver:**
> 1. The `.lxdoc` file (with `asset:` references, no `document-assets` block).
> 2. A folder of media files matching those references.
>
> The user uploads both via LX Draft's "Document + Archive" import tab — they can pick the folder directly (no zipping needed) or zip it first if their browser doesn't support folder upload.

You don't need to zip anything. Write the files into a folder; LX Draft reads only the files actually referenced by the document and ignores the rest.

If you absolutely cannot deliver media files (e.g. you only have URLs), use plain HTTPS image references. They'll work but won't be embedded — the document depends on the URL staying live.

### Manual base64 embedding (only if you have no other option)

The format is documented for completeness. **Avoid using it from an agent**:

```markdown

```

The `data:` field must be the complete base64 (no line breaks, no truncation). The `size:` field should match the original file's byte length.

## Review markers (do NOT use unless instructed)

The `...` and `...` syntax is for review comments and tracked changes. **Do not generate these manually.** Use the API endpoints if you need to add review data programmatically.

## How to use headings, paragraphs, and emphasis

Engineering documents are read for reference, not narrative. Structure beats prose. Use these tools deliberately:

**Heading levels carry meaning:**

- `## 1 Section` — top-level. Numbered. Examples: Introduction, Scope, Requirements, Test Plan.
- `### 1.1 Subsection` — major topic within a section. Numbered.
- `#### Subtopic` — finer division. Usually unnumbered.
- `##### Detail` and `###### Note` — rare; only for deep technical reference material.

**Don't skip levels.** Going from `##` straight to `####` confuses readers and breaks the table of contents.

**Don't use `#` (H1) inside the body** — the document title is in the frontmatter and rendered as the cover. Body sections start at `##`.

**Paragraphs vs callouts:**

- Plain prose → paragraphs. Most of the document.
- Critical information that must not be missed → `> [!IMPORTANT]` callout.
- A safety warning → `> [!WARNING]`.
- An optional pointer or rule of thumb → `> [!TIP]`.
- A procedural step inside an instruction list → `> [!STEP]`.
- Background context that interrupts the flow → `> [!NOTE]`.

Don't overuse callouts. If every other paragraph is a callout, none of them stand out.

**Emphasis:**

- `**bold**` for terms being defined and absolutely critical phrases. Two or three per page maximum.
- `*italic*` for proper nouns, document titles, and gentle emphasis.
- `` `inline code` `` for identifiers, filenames, signal names, command-line arguments, register names — anything the reader might type or look up literally.
- Don't bold whole sentences. Don't italicise for "this is important" — use a callout instead.

**Lists:**

- Use bullets for unordered facts (features, components, considerations).
- Use numbered lists for ordered steps or where the order matters and you'll refer to step N later.
- Indent with 2 spaces to nest. Don't go deeper than two levels — restructure if you find yourself nesting three deep.

**Tables vs CSV blocks:**

- Pipe tables (`| col | col |`) — short inline tables, 3-6 rows, primarily textual content.
- CSV blocks — engineering data: BOMs, requirements lists, test results, register maps, anything with >6 rows or that has structured columns. Use `csv:requirements`, `csv:bom`, `csv:test-results`, `csv:registers` etc. The label after `csv:` is descriptive; use whatever fits.

## Document structure for engineering documents

A typical LX engineering document has this structure:

```markdown
---
[frontmatter]
---



## 1 Introduction

Brief overview of the document and project.

## 2 Scope

What this document covers.

## 3 [Main content section]

### 3.1 Subsection

Content here.

### 3.2 Another subsection

```csv:requirements
id,description,criticality
REQ-001,System must boot in under 5 seconds,High
REQ-002,Battery life must exceed 8 hours,High
```

## 4 [Another main section]

## Appendix

### A. Additional Information

```

## Three ways to deliver a document to LX Draft

If you're an agent producing a document, you have three options:

### Option 1: Hand the user a .md file
Just write standard markdown. The user clicks "Import Markdown" in LX Draft and uploads the file. LX Draft wraps it in default frontmatter automatically.

### Option 2: Hand the user a complete .lxdoc file
Write the full file with frontmatter. The user clicks "Import Markdown" → "Upload File" and selects the .lxdoc. It imports as-is.

### Option 3: Use the agent-edit API directly
If you have programmatic access to the LX Draft API, use the **stateless**
content-based endpoint. You pass the FULL current document as `content` and the
new section text as `content_to_apply`; the response returns the rebuilt full
document `content` for you to apply (LX Draft no longer stores documents
server-side, so there is no `:id`):

```
POST /api/agent/edit
Content-Type: application/json

{
  "content": "",
  "section_heading": "3 DFM Review",
  "action": "replace",                  // replace | append | prepend
  "content_to_apply": "New markdown content...",
  "track_changes": true,
  "agent_name": "Your Agent Name"
}
```

Response: `{ ok: true, content: "", section, action, validation }`.
The validator runs server-side; if the edit would make the document invalid you
get a 422 with the issues to correct. Related stateless endpoints:
`POST /api/agent/sections` (`{content}` → list of sections) and
`POST /api/spellcheck` (`{content}`).

## Common mistakes to avoid

Stuff agents have actually done that broke the import or rendering. Don't repeat these:

- **Inventing frontmatter fields** like `layout: "page"`, `page_size: "A4"`, `margins: "standard"`. LX Draft has a fixed schema; unknown fields are silently ignored. If you think you need a layout option, you don't — page geometry is decided by the renderer.
- **Hard-coding numbers in captions.** Write `Components` not `Table 3: Components`. The renderer numbers tables, figures, and equations automatically.
- **Putting the document title in the body** as `# Title`. The title goes in the YAML frontmatter only. Body sections start at `## 1 Section`.
- **Using folder-prefixed image refs** like `![photo](photos/foo.jpg)`. Use `![photo](asset:foo)`. The folder name doesn't survive into the import.
- **Truncating base64 in `document-assets`.** If you find yourself writing a `data:` field by hand, stop. Deliver media as separate files alongside the .lxdoc and let the user import the bundle. LLMs cannot reliably emit hundreds of KB of base64 in one shot — output gets truncated silently.
- **Generating review markers** like `...` or ``. Those are for human review tooling. Agents should never write them manually.
- **Mixing pipe tables and CSV blocks for the same kind of data.** Pick one rule (e.g. "all requirements go in CSV blocks") and stick to it within a document.
- **Skipping heading levels** (`##` → `####`). Breaks the table of contents and the document map.
- **Leaving placeholder text** like "TODO: fill this in" or "[insert diagram here]" in a doc you hand to a human. Either complete it or omit it.

## Validate your output before delivery

LX Draft has a public validation endpoint. Run your `.lxdoc` through it before handing the document to the user — you'll catch malformed YAML, missing required fields, broken asset references, and the rest of the issues listed above.

**From the command line** (Node 18+, no npm install needed; the script lives in the LX Draft repo):

```
node scripts/lint-lxdoc.mjs path/to/your/doc.lxdoc
```

It exits 0 on success and 1 on validation errors, so you can use it in scripts.

**As an HTTP endpoint** (for agents that have internet but not the LX Draft repo):

```
POST https://lxdraft.lx-cloud.com/api/validate-public
Content-Type: text/plain


```

Returns:

```json
{
  "valid": true,
  "issues": [
    { "rule": "V003", "severity": "warning", "message": "...", "location": "..." }
  ]
}
```

`valid: false` means there is at least one error-severity issue. Fix all errors before delivery; warnings are advisory.

## Validation rules to follow

Your output will be validated. To avoid rejection:

- Frontmatter must be valid YAML
- `format: "lxd/1.0"` must be present
- Captions must NOT contain hardcoded numbers ("Table 3:" is wrong — write just "Components")
- Don't manually create review markers
- If you reference an `asset:id`, that asset must be in the document-assets block
- Don't use overlapping comment markers (you shouldn't be writing markers anyway)

## Quick checklist before delivering

- [ ] YAML frontmatter is valid and starts with `format: "lxd/1.0"`
- [ ] Title and revision are set
- [ ] Headings use `## 1 Section` format (number + space + name)
- [ ] Tables use CSV blocks for engineering data, pipe tables only for short inline tables
- [ ] No hardcoded numbers in captions
- [ ] Image references either use `asset:id` (with assets block) or external URLs
- [ ] No review markers (`` etc.) unless you're using the API