On this page9 sections
Customization: declared on your
BasePromptsubclass viastatic sectionsandstatic fieldGroups. This chapter is the reference for those two structures. See Prompt Creation for how a strategy (stateless / hybrid / stateful) consumes them.
Sections & Field Groups
Sections and field groups are the two halves of mcp-rune’s prompt structure. Sections define the user-facing workflow — how an LLM walks the user through a creation or update flow. Field groups define validation — which fields belong together and what rules apply. They live side by side in every prompt class, and the framework derives field tables, flow diagrams, and per-section docs from both.
This guide is the reference for how the two work together. For the strategy that consumes them (stateless / hybrid / stateful), see the Prompt Creation guide.
Why sections?
- Separation of concerns — display structure (sections) vs validation structure (fieldGroups)
- Scalability — add new fieldGroups to existing sections without changing the user-facing workflow
- Flexibility — multiple fieldGroups can be grouped under one section
- Single source of truth — section titles and descriptions defined once
The relationship is one-section-to-many-groups, with fields mapped at the group level:
Left column is what the LLM walks the user through; right column is what validateSection evaluates. A section can carry one or many field groups — that’s how a “Timing” section can host both a “when” group and a “duration” group without changing the user-facing flow.
Sections vs FieldGroups
| Aspect | Sections | FieldGroups |
|---|---|---|
| Purpose | User-facing workflow | Validation & technical organization |
| Contains | title, description, required, groups[] | fields[], required, conditional, validateSection |
| Used by | .flowDiagram() (flow-diagram generator), StatefulFormStrategy.getSections() | StatefulFormStrategy.validateSection(), getProgress() |
| Granularity | Coarse (user journey) | Fine (field validation) |
Defining sections
static sections = {
basics: {
title: 'Basic Information',
description: 'Title and description for the activity',
required: true,
groups: ['basics'],
content: {
intro: 'The title and description that identify the activity.'
}
},
classification: {
title: 'Classification',
description: 'Theme and category for organizing the activity',
required: true,
groups: ['classification'],
content: {
notes: [
'Use `find_records(model: "theme")` to find the theme',
'Use `find_records(model: "category")` to find the category'
]
}
},
timing: {
title: 'Timing',
description: 'When the activity occurred and how long it lasted',
required: false,
groups: ['timing'],
content: {
intro: 'When the activity occurred and how long it lasted.'
}
}
}static sections = {
basics: {
title: 'Basic Information',
description: 'Title and description for the activity',
required: true,
groups: ['basics'],
content: {
intro: 'The title and description that identify the activity.'
}
},
classification: {
title: 'Classification',
description: 'Theme and category for organizing the activity',
required: true,
groups: ['classification'],
content: {
notes: [
'Use `find_records(model: "theme")` to find the theme',
'Use `find_records(model: "category")` to find the category'
]
}
},
timing: {
title: 'Timing',
description: 'When the activity occurred and how long it lasted',
required: false,
groups: ['timing'],
content: {
intro: 'When the activity occurred and how long it lasted.'
}
}
}Section content enrichment
Sections support a content property with intro and notes that are automatically rendered in the generated section documentation. Use these to add domain-specific context without writing custom section generator methods.
| Property | Type | Description |
|---|---|---|
content.intro | string | Introductory text rendered at the top of the section, before the field table. Supports full markdown. |
content.notes | string[] | Array of notes rendered as a bullet list after the field table and enum tables. |
askPrompt | string | Custom prompt shown as “Ask the user: …” at the end of the section. |
How it works: When .allSections() or .section() renders a section, it automatically:
- Adds
content.introbefore the field table - Generates the field table from
fieldDefinitions - Generates enum tables for any field with
enumDescriptions - Adds
content.notesas a bullet list - Adds the
askPromptprompt
Key principle: Prefer content.intro and content.notes over custom generateSectionXDocumentation() methods. This keeps domain content in configuration and lets the framework auto-generate field tables and enum tables alongside it.
Per-group content (multi-group sections)
When a section contains multiple groups (groups: ['group_a', 'group_b']), each group can have its own context (display name) and content: { intro, notes } defined in fieldGroups. The generator renders each group as a ### sub-section with its own field table.
Key behaviors:
contextdefaults to title-cased group name if absent (snake_case_name→ “Snake Case Name”)- Groups without
contentrender just a heading and field table (no intro/notes) - Single-group sections are completely unchanged — they read from
section.contentas before contextandcontenton fieldGroups are ignored byStatefulFormStrategy(no breaking changes to validation)
Defining fieldGroups (simplified)
With sections as first-class citizens, fieldGroups focus on validation:
static fieldGroups = {
basics: {
fields: ['title', 'description'],
context: 'Basic Information',
required: true,
description: 'Title and description for the activity'
},
classification: {
fields: ['theme_id', 'category_id'],
context: 'Classification',
required: true,
description: 'Theme and category for organizing the activity'
}
}static fieldGroups = {
basics: {
fields: ['title', 'description'],
context: 'Basic Information',
required: true,
description: 'Title and description for the activity'
},
classification: {
fields: ['theme_id', 'category_id'],
context: 'Classification',
required: true,
description: 'Theme and category for organizing the activity'
}
}Section helper methods
BasePrompt keeps a small set of section-related statics:
| Method | Description |
|---|---|
getSectionForGroup(groupName) | Reverse lookup: find which section a group belongs to |
getDefaults() | Collect default values across all field definitions |
getStrategyIntro() | Strategy-specific description fragment for static description |
For section enumeration with metadata (fields, numbering, progress), use StatefulFormStrategy.getSections(PromptClass) from the Stateful Strategies guide.
Flow diagram generation
The builder’s .flowDiagram() step (backed by generateFlowDiagram in generators/flow-diagram-generator.ts) uses sections to create a compact flow overview:
// Auto-generated from sections config
**Flow:** (● required, ○ optional)
● 1. BASIC INFORMATION - title, description
● 2. CLASSIFICATION - theme_id, category_id
○ 3. TIMING - started_at, ended_at, duration_minutes
○ 4. RESOURCES - book_ids, notes_generated
● 5. SUMMARY// Auto-generated from sections config
**Flow:** (● required, ○ optional)
● 1. BASIC INFORMATION - title, description
● 2. CLASSIFICATION - theme_id, category_id
○ 3. TIMING - started_at, ended_at, duration_minutes
○ 4. RESOURCES - book_ids, notes_generated
● 5. SUMMARYSee also
- Prompt Creation guide — the strategies (stateless / hybrid / stateful) that consume these sections.
- Stateful Strategies guide — per-section validation and progress tracking on top of this structure.
- Prompt Derivation Framework guide — Layer 2 of the derivation pipeline where this content is consumed.