transform.template fills a DOCX or XLSX template with data from previous steps.
Use it when the workflow should produce a filled Office document from extracted
or transformed data: engagement letters, invoice summaries, approval packets, or
customer-facing reports.
Two template systems
Eigenpal has two separate template systems. They share DOCX/XLSX placeholder syntax, but use different storage and references.transform.template only accepts workspace template IDs (tmpl_...). Git-backed
templates under agents/<agent>/templates/<slug>/ and shared packages under
resources/templates/<slug>/ do not receive a tmpl_... ID and cannot be
referenced by this step. File IDs (file_...) are not valid templateId
values.
Runtime agents fill Git templates with the baked-in fill-template platform
skill (vars, then fill). Author those templates in Git source — not through
the Studio Templates page.
Workspace templates for this step
Manage workspace templates in Studio or througheigenpal workflow templates
(upload, list, inspect, replace, delete, smoke-fill). Small files can use
multipart upload; the CLI and SDKs negotiate the Files direct-upload flow
before creating the tmpl_... resource.
../ and symlink escapes are rejected unless you pass
--allow-external-templates. eigenpal workflow push validates the workflow
and version first, then uploads unmatched files as new tmpl_... resources
(or reuses an existing tmpl_... / tmpr_... when the SHA-256 matches).
Shared template pointers are not moved. If publish fails, those new uploads
are deleted. The YAML on disk is not rewritten:
tmpl_... resource. Its immutable
revision objects remain, so pinned workflows continue to execute; unpinned
workflows can no longer resolve the deleted logical ID.
Office file vs workflow YAML. Placeholders in the DOCX/XLSX file use
single braces: {client_name}. Double braces ({{client_name}}) are Liquid
syntax for workflow YAML data mapping only. Putting {{field}} in an XLSX
file leaves leftover braces in the output; upload warns and fill fails until
you switch the spreadsheet to {field}.
DOCX uses {placeholder} syntax. Placeholders are auto-detected on upload.
Supports loops ({#items}...{/items}) and nested access ({user.name}).
Missing-value highlighting (highlightNotFound) applies to DOCX only.
XLSX uses {placeholder} and table row syntax ({table:array.prop}).
XLSX templates are preview-only in Studio (no in-app editor). Tokens are
auto-discovered from spreadsheet text on upload. Loop sections and
missing-value highlighting are DOCX-only; XLSX
ignores highlightNotFound and notFoundText. Every sheet is filled. Null or
blank values become empty cells. Numbers and booleans keep spreadsheet types.
Formulas already in the template stay formulas; on {table:...} expansion they
are copied with the prototype’s references (not Excel fill-down). Substituted
strings that start with =, +, -, or @ stay text so they cannot become
formulas. Static cells on a {table:...} prototype row are copied onto each
generated row.
{table:array.prop} in the prototype row.
The matching data key must be an array of objects. Copy this as-is and
replace the tmpl_... ID and step names:
{report_title} in a header cell and this prototype
row (it expands to one output row per subject):
subjects must look like
[{ "first_name": "Ada", "last_name": "Lovelace" }, { "first_name": "Alan", "last_name": "Turing" }].
Configuration
Configuration goes inside the step’swith: block.
string
Workspace template ID (tmpl_…) from the Templates table (DOCX or XLSX). Git agent templates cannot be referenced here. File IDs (file_…) are not accepted. Mutually exclusive with
template.string
Local DOCX or XLSX path relative to the workflow YAML (e.g. ./templates/foo.xlsx). CLI push keeps the real path inside the workflow project unless you pass —allow-external-templates, uploads unmatched files as new tmpl_ resources, and does not rewrite the source YAML. Mutually exclusive with templateId.
string
Immutable template revision ID (tmpr_…). Pin this when executions must keep using the same template bytes after replacements. Requires templateId; local
template paths are pinned automatically on push.record<string, unknown>
required
Data object to merge into template. Each key must be explicitly defined - cannot pass a whole object as single expression.
string
Output filename - supports {{field}} syntax; .docx or .xlsx extension is added if omitted
boolean
default:"true"
Highlight missing variables with red-colored text in the output document (DOCX only; ignored for XLSX)
string
default:"NOT FOUND"
Text to display for missing variables when highlightNotFound is enabled (DOCX only; ignored for XLSX)
Output
File ID from files table