4.2 KiB
Agent Setup Prompt
The agent setup prompt is an HTML banner shown above the bash setup commands
on the /setup page. It is intended for organisation-specific operational notes
that every new analyst should read before running the bootstrap script —
for example: VPN requirements, support channel, data classification reminder,
or platform-specific prerequisites.
Default behaviour
No banner is shown by default. The /setup page renders only the standard
install steps until an admin configures an override.
Customising per instance
Admins configure the banner via:
- Admin UI:
/admin/agent-prompt— Jinja2 HTML editor with a placeholder cheatsheet, live preview, and save/reset actions. - REST API:
GET /api/admin/welcome-template— returns{content, updated_at, updated_by}.contentisnullwhen no override is set (default = no banner).PUT /api/admin/welcome-templatewith body{"content": "..."}— validates Jinja2 syntax and renders against a stub context before persisting. Returns400on syntax errors or unknown placeholders.DELETE /api/admin/welcome-template— clears the override; no banner shown.POST /api/admin/welcome-template/previewwith body{"content": "..."}— renders arbitrary content against the calling admin's live context without persisting. Used by the editor's Preview button.
The override lives in system.duckdb (table welcome_template, singleton
row id=1). The DELETE endpoint NULLs content; the audit trail
(updated_at, updated_by) is preserved.
Template language
Jinja2 with autoescape=False and
StrictUndefined. Autoescape is off because the rendered output is composed
into the surrounding /setup template which applies HTML escaping where
needed via | e; doubling the escape would corrupt characters like & or <
inside code blocks. All four render sites (PUT validation, preview endpoint,
/setup page render, render_agent_prompt_banner) share the same setting,
so the editor's preview matches what analysts see live. Any typo in a
placeholder name raises an error at PUT validation time rather than silently
emitting an empty string — the editor reports the error immediately so the
admin can fix it before saving.
Available placeholders
| Placeholder | Type | Notes |
|---|---|---|
instance.name |
string | instance.name in instance.yaml |
instance.subtitle |
string | instance.subtitle in instance.yaml |
server.url |
string | Full server URL at render time |
server.hostname |
string | Host part only |
user |
object or null |
null for anonymous /setup visitors |
user.id |
string | Authenticated user ID |
user.email |
string | Authenticated user email |
user.name |
string | Authenticated user display name |
user.is_admin |
bool | Whether the user is in the Admin group |
user.groups |
list[str] | User's group names |
now |
datetime (UTC, tz-aware) | Server time at render |
today |
string (YYYY-MM-DD) |
Server date |
Anonymous visitors: user is null on /setup when the visitor is not
signed in. Guard any user-specific content with {% if user %}…{% endif %}.
Security
Output is HTML-sanitized after Jinja2 render as a defense-in-depth measure:
<script>…</script>blocks are stripped.<iframe>…</iframe>elements are stripped.on*=event handler attributes (e.g.onclick=,onload=) are stripped.javascript:anddata:URI schemes inhref/src/actionattributes are replaced with#.
Admins are trusted, but this prevents accidental XSS from copy-pasted snippets
reaching the public /setup page.
Example: VPN and support banner
<strong>Before you start:</strong> This server is on the corporate VPN.
Connect to <code>vpn.example.com</code> before running the install command.
{% if user %}
<br>Signed in as <strong>{{ user.email }}</strong> —
<a href="https://support.example.com">open a ticket</a> if you need help.
{% endif %}
Resetting to no banner
Click Reset to default in the admin UI, or call
DELETE /api/admin/welcome-template. The /setup page will show only the
standard install steps with no banner above them.