Document YAML Schema
Document YAML files define how documents are rendered in the Loopstack Studio interface.
Top-Level Properties
type (optional)
type: documentIdentifies this configuration as a document. Default: document.
description (optional)
description: 'Contains structured meeting notes with action items'tags (optional)
Labels for categorizing and filtering documents:
tags: - meeting-notes - processedui
Defines how the document renders in the UI.
UI Widgets
Form Widget
ui: widgets: - widget: form options: order: [date, summary, participants, actionItems] properties: date: title: Date summary: title: Summary widget: textarea participants: title: Participants collapsed: true items: title: Participant actionItems: title: Action Items collapsed: true items: title: Action Item actions: - type: button transition: confirm label: 'Confirm'Form Field Properties
| Property | Type | Description |
|---|---|---|
widget |
string |
Widget type (see below) |
label |
string |
Field label |
title |
string |
Section title |
description |
string |
Field description |
placeholder |
string |
Placeholder text |
help |
string |
Help text below the field |
rows |
number |
Visible rows (for textarea) |
inline |
boolean |
Display field inline |
readonly |
boolean |
Make field read-only |
hidden |
boolean |
Hide the field |
disabled |
boolean |
Disable interaction |
collapsed |
boolean |
Collapse arrays/objects by default |
fixed |
boolean |
Fixed field |
order |
string[] |
Display order of nested fields |
enumOptions |
array |
Options for select/radio widgets |
items |
object |
UI config for array items |
properties |
object |
UI config for nested object fields |
Widget Types
| Widget | Description |
|---|---|
text |
Single-line text input (default) |
textarea |
Multi-line text area |
select |
Dropdown select |
radio |
Radio button group |
checkbox |
Checkbox |
switch |
Toggle switch |
slider |
Numeric slider |
code-view |
Code editor with syntax highlighting |
enumOptions
For select and radio widgets:
language: title: Language widget: select enumOptions: - label: Python value: python - label: JavaScript value: javascriptOr as simple strings:
enumOptions: - python - javascript - javaActions
Buttons that trigger wait: true transitions:
actions: - type: button transition: confirm # Must match the method name label: 'Confirm' - type: button transition: reject label: 'Reject'Document-Type Options
internal — Framework-internal documents
Declare internal: true directly on the @Document decorator to mark every instance of this type as framework plumbing. Internal documents are persisted server-side and still readable by code that queries the document store (e.g. LLM providers building conversation history), but they’re excluded from API responses and live updates — Studio never sees them.
@Document({ schema: LlmContextSchema, internal: true, tags: ['message'],})export class LlmContextDocument { /* ... */}The built-in LlmContextDocument uses exactly this combination so LLM context messages reach the model but never render in the chat UI.
Meta Properties
Loopstack splits document metadata into two kinds: static meta (declared once on @Document({ meta }) and applied to every instance) and dynamic meta (passed per-call via documentStore.save(…, { meta }) and persisted on that specific document row).
Static Meta — @Document({ meta })
Declared on the decorator. Applies to every instance of this document type.
@Document({ schema: ReportSchema, meta: { mimeType: 'text/markdown', level: 'info' },})export class ReportDocument { /* ... */}| Property | Type | Description |
|---|---|---|
mimeType |
string |
MIME type hint used by Studio for rendering/downloads (see below for the list). |
level |
'debug' | 'info' | 'warning' | 'error' |
Severity tag. Studio may style documents based on this. |
enableAtPlaces |
string[] |
Extra places where documents of this type stay active, in addition to the place each was saved at. |
hideAtPlaces |
string[] |
Hide this document type when the workflow is at one of these places. |
A document is active at the place it was saved at — its transition’s target place — and at every place in enableAtPlaces. Only active, visible documents are candidates for the prompt a waiting run shows; see Prompt Selection Rules.
Dynamic Meta — documentStore.save(…, { meta })
Set per call. Persisted on the specific document row.
await this.documentStore.save(MyDocument, content, { key: 'doc-1', meta: { invalidate: false } });| Property | Type | Description |
|---|---|---|
invalidate |
boolean |
Opt-out of replacement. Default behavior (omitted/true) invalidates the previous version when reusing the same key. Set to false to keep both. |
data |
any |
Arbitrary per-instance metadata bag for user-defined data. Not used by the framework. |
streaming |
boolean |
Frontend-managed. Set by Studio during LLM streaming to indicate this document is still being filled in. Not typically set by backend code. |
streamReadyForFinal |
boolean |
Frontend-managed. Companion to streaming — marks the stream complete and the final version ready to persist. Not typically set by backend code. |
Supported MIME Types
text/plain, text/html, text/markdown, text/css, text/xml, application/json, application/javascript, application/typescript, application/yaml, application/xml
Complete Example
type: documentdescription: 'Generated code file'tags: - code - generatedui: widgets: - widget: form options: order: [filename, description, code] properties: filename: title: File Name readonly: true description: title: Description readonly: true widget: textarea code: title: Code widget: code-view actions: - type: button transition: confirm label: 'Accept'