AI Templates (Superadmin)¶
The AI Templates page (Settings → AI Templates) lets a superadmin manage every prompt Patcherly sends to the AI model when it analyzes errors and proposes fixes. The runtime always uses the active row in the PostgreSQL ai_prompt_templates table; the Markdown files under config/ai_templates/ in the repo seed that table on first install and act as the file-based fallback when the database is briefly unreachable.
This page covers what you can do from the dashboard, what is protected and why, and how to recover when a save can’t reach the disk (Render web service without a Disk, read-only filesystem, etc.).
Selection precedence (what the runtime picks)¶
Patcherly resolves the prompt to use for each error in this order:
- Exact match —
(language, framework), e.g. Django Default for a Django error. - Language default —
(language, NULL)withis_default: true, e.g. Python Default. Used when no framework template matches. - Universal Default — language-agnostic,
is_universal: true. Used when neither a framework- nor a language-specific template applies. Always present on a healthy install. - Inline emergency stub — last-resort, used only when both the DB load and the file fallback failed at the same time (a misconfiguration to fix promptly).
So a missing framework template falls through to the language default; a missing language default falls through to the universal. You don’t need a template for every framework — only the language default and the universal are mandatory.
Badges¶
Each row in the table tells you at a glance how it participates in selection:
- Universal — the one language-agnostic ultimate fallback. Cannot be deleted.
- Default — the canonical row for its
(language, framework)slot. - File — a matching
.mdfile exists on disk inconfig/ai_templates/(orAI_TEMPLATES_DIR). - DB only — the row was created from the dashboard and no file is on disk yet. Click Download to save the file to your repo so it ships with the next deploy.
Actions¶
Every row exposes these actions:
- Edit / Save — open the editor modal. The body (
template),version, andis_defaultare always editable.languageandframeworkare locked for the Universal Default. - Set as default — promote this row to be the default for its
(language, framework)slot. The previous default in the same slot is demoted in the same transaction. Hidden on the Universal Default (it’s always-default by design). - Reset to default — restore the row to the body shipped in
config/ai_templates/. Only available when a matching file exists on disk (the File badge is showing). - Download — always available. Returns the current DB state of the template as a Markdown file with YAML frontmatter — exactly what the file-write would have produced. Drop it into
config/ai_templates/<language>/(or the universal at the top level) and commit so other installs pick it up. - Delete — removes the row from the DB and best-effort removes the matching file. Disabled with a tooltip when:
- The row is the Universal Default (always protected).
- The row is the sole language default for its language. Promote another
<language>template to default first via Set as default, then this one becomes deletable.
Framework defaults are never delete-protected — when missing, runtime auto-falls-back to the language default (and that to the universal).
How edits flow¶
When you save, create, or delete a template from the dashboard:
- Database write is the primary effect — your change is live immediately.
- File write-back is best-effort. Patcherly tries to write (or delete) the matching
.mdfile underconfig/ai_templates/(or whereverAI_TEMPLATES_DIRpoints). On success you’ll see a success toast. - If the file write fails (read-only filesystem, missing directory, permission denied), Patcherly shows a warning toast with the exact error and a Download Template File button. The DB save is not rolled back — the file is just a snapshot for the repo.
- You commit the file to the repo so future installs (and CI) pick it up.
Persistence on Render production: the
config/ai_templates/folder lives on the API container’s ephemeral filesystem. To make UI edits survive a redeploy without manual commits, attach a Render Disk and setAI_TEMPLATES_DIR=/data/ai_templatesinPatcherlyENV_PROD. On first boot Patcherly hydrates the configured directory from the committed defaults if it’s empty.
Universal Default — what makes it special¶
The Universal Default is a single, language-agnostic prompt that fires when no other template matches. It’s protected so a misclick can’t leave the analyzer without any prompt:
- Cannot be deleted from the dashboard (the API returns 409 with a clear message).
is_universalcannot be toggled through the API — server strips inbound changes to this flag.languageandframeworkcannot be edited — they must staynull.name,template,version,is_defaultare editable like any other row.
A PostgreSQL partial unique index enforces at most one universal row in the database. If you ever need to swap the Universal Default to a brand-new copy, edit the existing row’s body — don’t create a second universal.
Required slot tokens¶
Every template body must contain these three placeholders verbatim:
{prior_successful_patches}— bullet list of prior fixes that worked for similar errors in this tenant.{prior_failed_patches}— bullet list of prior fixes that failed (so the model avoids them).{error_context}— the rendered error context (traceback, file path, error message, etc.).
The editor warns you if you save without one of these. CI (tests/unit/test_ai_prompt_slots.py) also enforces the invariant on every PR.
Common recovery scenarios¶
- “File write failed” — click the Download Template File button in the warning toast, place the file under the path shown in the toast, and commit it.
- “Cannot delete the only default template for
<language>” — create or pick another template for the same language, click Set as default on it, then delete the old one. - “The Universal Default cannot be deleted” — by design. Edit it instead.
- An operator deleted a framework template by mistake — runtime now falls back to the language default; redeploy the latest repo (where the
.mdfile still lives) or recreate the row from the file via the dashboard.
Where to read more¶
- File format and slug rules:
config/ai_templates/README.md. - Selection logic and runtime details:
docs/ai/AI_SERVICES.md(operator docs). - API surface:
docs/api/api.md→ AI Template Management. - Database migration that introduced this model: Alembic revision
009_ai_templates_is_default_universal.