MDMA
Markdown Document with Mounted Applications
Interactive documents from Markdown. Built for next gen-apps
🌐 Website · 🚀 Live Demo · 📖 Docs · 💬 Discord · 🤗 Model
Why MDMA?
AI conversations today are plain text — the user reads a response and manually acts on it. MDMA changes that. When an LLM knows the MDMA spec, it can respond with interactive components (forms, tables, approval gates) instead of just text. The conversation becomes actionable: the user fills out a form, approves a step, or reviews structured data — all inline, with a predictable schema that your app already knows how to render and process.
No custom UI per use case. No parsing free-form text. The AI generates structured, validated components and your frontend renders them instantly.
What is MDMA?
MDMA extends Markdown with interactive components defined in fenced mdma code blocks. A regular Markdown file becomes an interactive application:
# Patient Intake
```mdma
type: form
id: intake-form
fields:
- name: patient-name
type: text
label: "Full Name"
required: true
sensitive: true
- name: email
type: email
label: "Email"
required: true
sensitive: true
- name: reason
type: textarea
label: "Reason for Visit"
required: true
onSubmit: submit-intake
```
```mdma
type: button
id: submit-btn
text: "Submit Intake Form"
variant: primary
onAction: submit
```
Speed comparison
Same scenario, two models. GPT-5.5 and our own hosted MDMA-IL model.
Our model is available on Hugging Face: MobileReality/mdma-gemma4-26b-dsl-unsloth-v1
| GPT-5.5 | Our own hosted model |
|---|---|
![]() |
![]() |
MDMA_AUTHOR prompt matrix
Each cell shows the pass rate of the model-specialized MDMA_AUTHOR prompt variant on the listed eval suite.
✅ 100% on the suite.
🟡 Scoring between 80–99% on the suite.
🔴 Scoring below 80% on the suite.
| Variant | one-shot | one-shot with custom prompt | conversation | specific flow of conversation |
|---|---|---|---|---|
| OpenAI | ||||
gpt-5.6-sol |
✅ | ✅ | ✅ | ✅ |
gpt-5.6-terra |
✅ | ✅ | ✅ | ✅ |
gpt-5.6-luna |
✅ | ✅ | ✅ | ✅ |
gpt-5.5 |
✅ | ✅ | ✅ | ✅ |
gpt-5.4 |
✅ | ✅ † | ✅ † | ✅ † |
gpt-5.4-mini |
✅ | ✅ | ✅ * | ✅ * |
gpt-5.4-nano |
✅ | ✅ | ✅ * | ✅ * |
gpt-5.2 |
✅ | ✅ | ✅ | ✅ |
gpt-5.1 |
✅ | ✅ | ✅ | ✅ |
gpt-5 [i] |
✅ | ✅ | ✅ | ✅ |
gpt-5-mini [i] |
✅ | ✅ | ✅ * | ✅ * |
gpt-5-nano [i] |
✅ | ✅ | 🟡 * | 🟡 * |
gpt-4.1 |
✅ | ✅ | ✅ | ✅ |
gpt-4.1-mini |
✅ | ✅ | ✅ * | ✅ * |
gpt-4.1-nano |
✅ | ✅ | ✅ * | 🟡 * |
| Anthropic | ||||
claude-opus-4.8 |
✅ | ✅ | ✅ | ✅ |
claude-opus-4.7 |
✅ | ✅ | ✅ | ✅ |
claude-opus-4.6 |
✅ | ✅ | ✅ | ✅ |
claude-sonnet-4.6 |
✅ | ✅ | ✅ | ✅ |
claude-haiku-4.5 |
✅ | ✅ | ✅ * | ✅ * |
claude-fable-5 |
✅ | ✅ | ✅ | ✅ |
gemini-3.5-flash |
✅ | ✅ | ✅ | ✅ |
gemini-3.1-pro-preview |
✅ | ✅ | ✅ | 🟡 ‡ |
gemini-3.1-pro-preview-customtools |
✅ | ✅ | ✅ | ✅ |
gemini-3.1-flash-lite-preview |
✅ | ✅ | ✅ * | ✅ * |
gemini-3-flash-preview |
✅ | ✅ | ✅ * | ✅ * |
gemini-2.5-pro |
✅ | ✅ | ✅ | ✅ |
gemini-2.5-flash |
✅ | ✅ | ✅ * | ✅ * |
gemini-2.5-flash-lite |
✅ | ✅ | ✅ * | ✅ * |
| xAI | ||||
grok-4.3 [i] |
🟡 | 🔴 | 🔴 | 🔴 |
grok-4.20 |
✅ | ✅ | ✅ | ✅ |
grok-4.5 |
✅ | ✅ | ✅ | ✅ |
| Zhipu (z.ai) | ||||
glm-4-plus |
TBD | TBD | TBD | TBD |
| Moonshot | ||||
kimi-k2 |
TBD | TBD | TBD | TBD |
| Alibaba | ||||
qwen3-max |
TBD | TBD | TBD | TBD |
| MiniMax | ||||
minimax-m1 |
TBD | TBD | TBD | TBD |
| Other | ||||
| model | — | — | — | — |
Don't see your model? Add a prompt variant under
packages/prompt-pack/src/prompts/mdma-author//and open a PR — we'll run the eval suite and add it to this table.
† gpt-5.4 intermittent duplication bug — gpt-5.4 passes one-shot evals reliably but shows a non-deterministic output duplication in multi-turn, custom-prompt, and flow evals (~7–15% of runs). The model generates a complete, correct response and then immediately re-emits the entire output verbatim, causing [duplicate-ids] validation errors. This is a known model-level issue unrelated to the prompt variant. See the OpenAI community thread for details. If this affects your use case, prefer gpt-5.5 or gpt-5.2.
‡ gemini-3.1-pro-preview stochastic preamble loop — on ~7–15% of flow-eval runs, the model emits a chain-of-thought as visible Markdown prose (e.g. **Investigating Production Errors** repeated 3–5 times) instead of opening a ```mdma block, producing either [yaml-correctness: outside fenced block] or [duplicate-ids] errors. Per Google's official Gemini 3 prompting guide, this is a model-level behavior driven by temperature/sampling — prompt-level fixes shift which test loops rather than eliminating the loops. If deterministic flow output matters, prefer gemini-2.5-pro for production multi-step flows.
* Smaller / lower-tier models from any lab (OpenAI mini · nano, Anthropic Haiku, Google Gemini Flash, etc.) pass our eval suites, which exercise short, structured test cases. In longer real-world conversations they tend to hallucinate, forget earlier turns, or drift from the spec. For production use that involves multi-turn dialogue or stateful flows, prefer the flagship-tier model from the same family.
[i] Noticeably slow response times — single-turn responses commonly take tens of seconds and full eval runs measure in minutes.
MDMA_FIXER prompt matrix
Each cell shows the pass rate of the model-specialized MDMA_FIXER prompt variant on the single-block fixer eval (16 tests covering structural fixes, bindings, PII, forms, tables/charts, approvals, and custom-component extraction). The fixer is what powers automatic repair of LLM output that fails validate() — every supported model lands at ✅ via model-tailored inline guards (no-leading-separator, preserve-input-structure, table-key-direction, replace-all-placeholders, fix-all-listed-errors, etc.).
✅ 100% on the single-block fixer eval (16/16).
| Variant | single-block fixer | notes for testing |
|---|---|---|
| OpenAI | ||
gpt-5.6-sol |
✅ | |
gpt-5.6-terra |
✅ | |
gpt-5.6-luna |
✅ | |
gpt-5.5 |
✅ | |
gpt-5.4 |
✅ | |
gpt-5.4-mini |
✅ | |
gpt-5.4-nano |
✅ | |
gpt-5.2 |
✅ | |
gpt-5.1 |
✅ | |
gpt-5 |
✅ | |
gpt-5-mini |
✅ | |
gpt-5-nano |
✅ | |
gpt-4.1 |
✅ | |
gpt-4.1-mini |
✅ | |
gpt-4.1-nano |
✅ | |
| Anthropic | ||
claude-opus-4.8 |
✅ | |
claude-opus-4.7 |
✅ | |
claude-opus-4.6 |
✅ | |
claude-sonnet |
✅ | catch-all variant — matches claude-sonnet-4-5, claude-sonnet-4-6, etc. |
claude-haiku |
✅ | |
claude-fable-5 |
✅ ‡ | requires reasoning.exclude: true (wired in evals/promptfooconfig.fixer.js) |
gemini-3.5-flash |
✅ ‡ | requires reasoning.exclude: true; adds an inline no-leading-separator guard |
gemini-3.1-pro-preview |
✅ ‡ | requires OpenRouter reasoning.exclude: true (already wired in evals/promptfooconfig.fixer.js) |
gemini-3.1-pro-preview-customtools |
✅ ‡ | same reasoning.exclude requirement |
gemini-3.1-flash-lite-preview |
✅ | |
gemini-3-flash-preview |
✅ | |
gemini-2.5-pro |
✅ ‡ | same reasoning.exclude requirement |
gemini-2.5-flash |
✅ | |
gemini-2.5-flash-lite |
✅ | |
| xAI | ||
grok-4.3 |
✅ ‡ | minimal prompt + reasoning.exclude: true — extra framing regresses Grok 4.3 |
grok-4.20 |
✅ | |
grok-4.5 |
✅ ‡ | requires reasoning.exclude: true (hidden-reasoning model) |
‡ Reasoning-token leak suppression — for reasoning-flavoured Gemini Pro variants and Grok 4.3, the fixer would otherwise see visible "Thinking: Topic" prose prepended to every response. The eval config sets passthrough.reasoning.exclude: true (and the demo's usePreviewValidation does the same per-provid

