Reference format for the Demo Agent scene pages in Wiki.js. Scenes live under
/agents/hermes/demo_scenes/. The Hermes demo-agent skill parses a scene and drives a live, headed browser through it (Keycloak SSO, per-role isolated sessions, screenshots, view/403 assertions, live pause/Q&A/notes).
A scene page has three required sections (## Target, ## Users, ## Steps)
and one optional section (## Conduct) that plans how the agent conducts
itself during a live presentation.
# Demo Scene: <Title>
> <one-line pitch for the audience>
## Target
- URL: https://test-client-dental.dental.veripath.co.uk
## Conduct
- audience: marketing + development
- tone: professional, concise, invites questions
- invite_questions: true
- mutation_allowed: false
- reseed: docker exec dental_app python manage.py seed_dental_demo --tenant test-client-dental --reset
## Users
- RECEPTION: reception.test-client-dental / test123
- DENTIST: dentist.test-client-dental / test123
## Steps
1. USER: RECEPTION
2. ACTION: NAVIGATE -> {URL}
3. ACTION: KEYCLOAK_LOGIN -> RECEPTION
4. ACTION: VERIFY_VIEW -> /dental/practices/
5. ACTION: SCREENSHOT -> reception_practices
6. ACTION: PAUSE_AND_DISCUSS -> This is the practice list. Questions?
Conventions
## Target — the app to drive. The token {URL} in any step is replaced with this value.## Conduct (optional) — presentation plan for live demos: audience,tone, invite_questions (true/false), mutation_allowed, and an optionalreseed shell command run automatically before the demo. Guides the agent's## Users — one line per role: - ROLE: username / password. ROLE is a short uppercase label used by USER: and KEYCLOAK_LOGIN:. Passwords are test/demo credentials only.## Steps — a numbered list. Every line is either USER: or ACTION:.NOTE: lines are presentation narration — read them for the audience, log them, but take no browser action.| Action | Arguments | Behaviour |
|---|---|---|
USER |
<ROLE> |
Switch to the role. Each role gets a fresh, isolated browser context (clean cookies — Keycloak sessions never leak between roles). |
NAVIGATE |
<URL or {URL}/path> |
Go to the URL and wait for the page to settle. |
KEYCLOAK_LOGIN |
<ROLE> |
Ensure on the Keycloak login screen, fill #username/#password from the role, click the sign-in button, wait for the redirect back to the app. |
TYPE |
<selector> -> <value> |
Fill a field. Value can be plain text, {URL}, {ROLE.username} / {ROLE.password}, or a relative date token (see below). |
CLICK |
<CSS selector> or visible-text description |
Click an element. Prefer visible text (e.g. the first claim row in the FP17 list) when no stable selector exists. |
SCREENSHOT |
<step_name> |
Capture the current view, upload to Wiki.js assets, and embed it in the run report. |
VERIFY_VIEW |
<url-substring> |
Assert the current URL contains the substring. Fail the run otherwise. |
VERIFY_TEXT |
<text-substring> |
Assert the visible page text contains the substring. Fail the run otherwise. |
ASSERT_NO_403 |
— | Assert the most recent navigation did not return 403 and no permission-denied text is visible. |
EXPECT_403 |
— | Assert the current view did return 403 / shows permission-denied text. Used to deliberately demonstrate RBAC blocks. |
WAIT_MS |
<milliseconds> |
Optional explicit pause for slow renders. |
NOTE |
<text> |
Narration only — also posted to the live chat. |
PAUSE_AND_DISCUSS |
<prompt> |
Live-interactive. Agent narrates the prompt, then visibly pauses (panel + viewer show a "⏸ Waiting for questions" banner with the prompt), answers questions in the chat, and auto-continues after ~3 min if idle — it never looks like a crash. |
ASK_AUDIENCE |
<question> |
Live-interactive. Agent poses the question, visibly pauses, and responds to each answer (auto-continues after ~2 min). |
Dates in demos should never be hardcoded — they rot between runs. In TYPE
values (and NAVIGATE paths), use tokens the agent resolves just-in-time:
| Token | Meaning | Example resolved |
|---|---|---|
TODAY |
today | 2026-08-04 |
TOMORROW |
tomorrow | 2026-08-05 |
TODAY+2 |
2 days from today | 2026-08-06 |
NEXT_TUESDAY |
next Tuesday | 2026-08-11 |
TODAY+2 14:30 |
date + time (datetime-local) |
2026-08-06T14:30 |
Resolved by python3 /opt/hermes-demo/date_resolve.py "<token>". If the helper
echoes the input unchanged, it is not a token — use it literally.
Scenes run as two-way presentations. While the agent operates the app it
also polls a control channel (control.json in the run directory) and:
RUN_DIR/notes.md and, if configured, thetodo_feedback_log.md).The control panel and shareable viewer link both expose Pause/Resume/Stop and a
Live Q&A box. One demo runs at a time on the shared display.
mutation_allowed: true, add a reseed command, and say so in the scene description.EXPECT_403 to showcase role-based access control positively (e.g. receptionist → /dental/financial/).VERIFY_VIEW right after each login so a Keycloak/session regression fails the run loudly instead of silently.PAUSE_AND_DISCUSS after landing on key screens to invite live questions.