Reframe README around the real bottleneck (human coordination, not engineering ability) with the "five-minute meeting" cost story; rewrite the demo script to match. Update gemini/livekit/mongodb/digitalocean specs to reflect shipped code (Gemini Live agent, TTS, embeddings, Lyria via Interactions API; current API routes; hermes_jobs collections). Add hermes.md. Rename graph.md -> cont_learning.md. Remove outdated/dead docs (agent-learning scaffolding, graph-discovery, handoffs, superpowers, idea/plan/demo-setup) and the bundled LiveKit starter under examples/. Rewire CLAUDE.md doc-first gate off the deleted PLAN.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LuV8W8oNYRsDWKoqK8Mkqc
4.1 KiB
Hermes Spec
Status: active / matches code.
"Hermes" is PodMan's action layer — the part that turns a detected problem into something a teammate sees, hears, or gets done. It spans three things:
- Interventions — cards, messages, and urgent voice in the pod room.
- Async jobs — longer tasks delegated from the live conversation agent.
- Ops watchdog — keeps the production services healthy.
The LiveKit identity for the main agent is podman-hermes.
1. Interventions
Code: backend/src/agent/podman.ts, backend/src/action/hermes.ts,
backend/src/voice/live.ts.
When the agent detects a collision, it runs the learning loop (recall → policy
gate; see docs/cont_learning.md) and then publishes the least intrusive
intervention that fits:
- Card / message — a data-channel packet on the
podman.interventiontopic (publishHermesIntervention/publishHermesMessage). Default path. - Urgent voice — only for
criticalcollisions.speak()generates Gemini TTS audio and publishes it as a LiveKit audio track.
Intervention text is short and deterministic (template, not an LLM call):
Conflict: alice + bob both on detector.ts (unpushed). Seen before. The spoken
line is phrased for natural TTS prosody. Each intervention is persisted to the
interventions collection; the teammate's accept/dismiss returns via
POST /api/outcome.
A per-pod cooldown (NUDGE_COOLDOWN_MS, default 3 min) and a single-shot
"active conflict" guard prevent repeat nagging; a conflict re-arms once it
resolves.
2. Async Hermes jobs
Code: backend/src/hermes/jobs.ts. Storage: hermes_jobs +
hermes_job_events (see docs/mongodb.md).
The live conversation agent can hand a longer task to Hermes via its
delegate_to_hermes tool. Lifecycle:
queued → running → (waiting_for_confirmation) → completed | aborted | failed
createHermesJob() records the job, emits an accepted event, and kicks off
runHermesJob() in the background. The runner gathers context and runs scoped,
read-mostly steps based on the prompt and success criteria:
- always:
git status --short --branch,git diff --stat - if the ask mentions GitHub: a repo reachability check via the GitHub API
- if it mentions Mongo/memory/telemetry: collection counts
- if it mentions build/test/typecheck/broken:
pnpm typecheck
Confirmation gate: if riskLevel === 'deploy_allowed' and
requiresConfirmation, the job parks at waiting_for_confirmation instead of
acting. Abort: abortHermesJob() signals the runner's AbortController.
Every step appends a hermes_job_event (redacted + truncated), which is both
stored and published live to the room as a HERMES_JOB_EVENT data message from a
short-lived podman-hermes-job-* identity. The conversation UI streams these via
GET /api/.../hermes-job/events/stream.
Endpoints: POST /api/internal/hermes/jobs,
GET /api/internal/hermes/jobs/:jobId, .../abort, .../events,
.../events/stream, plus the pod-scoped .../live-conversation/:sessionId/hermes-job.
3. Ops watchdog
Code: scripts/hermes-watchdog.mjs, scripts/hermes-sync-deploy.mjs,
scripts/hermes-notify.mjs. Detail: docs/digitalocean.md.
systemd supervises the app processes; Hermes owns the loop around them:
pnpm hermes:watchdogchecks systemd services, public routes,/health,/api/pods, andpnpm deploy:doctor. Failures trigger targeted restarts.podman-hermes-watchdog.timerruns it every 5 minutes.podman-hermes-sync-deploy.timerpollsorigin/mainevery 2 minutes and, on a clean tree, fast-forwards, builds, publishesfrontend/dist, restarts API/agent/Caddy, and runs the strict watchdog.- Reports go to
/var/log/podman/hermes-watchdog-latest.json; setPODMAN_ALERT_WEBHOOK_URLto forward failures to Discord/Slack/webhook.
What Hermes is NOT
- Not an autonomous code-writing agent. Job steps are scoped, read-mostly checks; deploy-level actions require explicit confirmation.
- Not a second collision detector. Detection is deterministic
(
collision/detector.ts); Hermes only acts on the result.