How to run, watch, administer and extend live, interactive application demos. Step-by-step usage is on Live Demos — How to Use; this page covers operations, architecture and administration. Companion to Demo Library and the Scene Format.
/agents/hermes/demo_runs/<scene>/<timestamp>, the Demo Library index is updated, and the recording appears on the public Demos page.On failure, an error page is written to /agents/hermes/demo_errors/<scene>_<timestamp> with the stack trace and a remediation checklist — OpenCode picks these up to fix the cause.
Watching demos — three ways: (1) watch live in the control panel via the 👁 Watch here button (embedded noVNC feed); (2) share the shareable link (signed, no login) with an audience — they can also ask questions; (3) re-watch any completed run any time on the public Demos page (MP4, no auth).
Scenes are two-way presentations, not batch runs. While Hermes drives the
real app it polls a control channel (RUN_DIR/control.json) and:
RUN_DIR/notes.md and, if an OpenCode workspace was<workspace>/todo_feedback_log.md for developmentThe scene page's optional ## Conduct section plans how the agent presents
(audience, tone, whether it invites questions, mutation allowed, reseed). See
Scene Format.
Scenes never hardcode dates. TYPE values may use TODAY, TOMORROW,
TODAY+N, NEXT_<DAY> (optionally with a time, e.g. TODAY+2 14:30), resolved
just-in-time for datetime-local fields.
| Piece | Where | Role |
|---|---|---|
| Scene pages | Wiki.js /agents/hermes/demo_scenes/* |
The script a demo runs (Target / Conduct / Users / Steps) |
| demo-agent skill | /root/.hermes/skills/veripath/demo-agent/SKILL.md |
Tells Hermes how to execute a scene (browser, Keycloak, screenshots, assertions, control channel, report) |
| Trigger server | /opt/hermes-demo/demo_server.py (systemd hermes-demo) |
Gated API + control panel; spawns hermes -z, tracks runs, updates the wiki |
| Control channel | /opt/hermes-demo/control_check.py, control_respond.py, date_resolve.py |
The live Pause/Q&A/notes bridge between the audience and the running agent |
| Virtual display | Xvfb :99 + x11vnc + noVNC (systemd hermes-demo-{xvfb,vnc,novnc}) |
The live, watchable browser surface |
| Reverse proxy | nginx demo.veripath.co.uk → 127.0.0.1:5001 + noVNC :6080 |
TLS, basic-auth gate, websocket bridge |
/, /api/*): HTTP basic auth at nginx, plus a per-request X-Demo-Token (injected by nginx only after basic auth passes)./run/<id>?tk=<sig>): no basic auth — gated by a signed, time-stable token in the URL. Share only with the intended audience. The viewer can also pause/resume and ask questions./vnc/*): reachable only via a viewer page (no direct public links).Add a scene — author a page under /agents/hermes/demo_scenes/ using the Scene Format, then add its metadata to /opt/hermes-demo/scenes.json (title, path, purpose, optional reseed) and it appears in the control panel.
Reseed demo data before stateful scenes — scenes that submit data (e.g. booking appointments) mutate the client DB; either set reseed in scenes.json (runs automatically before the demo) or run manually:
docker exec dental_app python manage.py seed_dental_demo --tenant test-client-dental --reset
Re-run and repeatability — only one demo runs at a time (single shared display). The control panel shows the active run with Pause/Resume/Stop.
Error reports → OpenCode — each failure writes an error page; the section below lists the usual causes.
| Item | Path |
|---|---|
| Skill | /root/.hermes/skills/veripath/demo-agent/SKILL.md |
| Server | /opt/hermes-demo/demo_server.py |
| Scenes registry | /opt/hermes-demo/scenes.json |
| Control channel helpers | /opt/hermes-demo/control_check.py, control_respond.py, date_resolve.py |
| Runs + screenshots | /opt/hermes-demo/runs/* |
| API token | /opt/hermes-demo/token |
| Viewer signing secret | /opt/hermes-demo/secret |
| Screenshot helper | /opt/hermes-demo/screenshot.py |
| nginx site | /etc/nginx/sites-available/demo.veripath.co.uk.conf |
| Systemd units | hermes-demo, hermes-demo-xvfb, hermes-demo-vnc, hermes-demo-novnc |
agent.max_turns in /root/.hermes/config.yaml; raise it (default set to 2000 for interactive runs).RUNNING state and the agent is at a step boundary (it polls between steps); it answers promptly during PAUSE_AND_DISCUSS.core/middleware.py ROLE_REQUIREMENTS.demo.veripath.co.uk points here and a Let's Encrypt cert is issued, the site uses a self-signed placeholder.If a demo or the live viewer misbehaves, capture exactly what happened instead of
guessing:
registered → running → finished), viewer page loads, /run/ chat &/opt/hermes-demo/trace.log (tail -f to watch live)/opt/hermes-demo/runs/<run_id>/trace.logGET /api/diag?limit=400 (X-Demo-Token) returns recent trace eventshermes-demo-vnc-trace tails the x11vnc logtrace.log. This is how you can tellTypical pattern to check when "the viewing popup opens then closes":
run registered / run running — the demo started.viewer page_loaded — someone opened the shareable link.vnc_page_loaded + vnc client_connected — noVNC loaded and the VNC streamvnc client_disconnected — the VNC stream dropped (browser tab closed,