Hermes

Route Hermes command approvals and kanban block/review pauses into the HITLy inbox.

Hermes Agent is a Python agent. HITLy does not run inside Hermes — a drop-in plugin POSTs pauses to HITLy, and applies the decision on the Hermes host.

Hermes “personas” are named profiles (~/.hermes/profiles/<name>/, each with its own SOUL.md). Cron is only one unattended runner.

How it works with HITLy

Command approval (CLI, gateway, /background)

Dangerous terminal / execute_code calls pause in Hermes tools/approval.py. Selecting security.approval.transport: hitly replaces the built-in prompt (including Telegram /approve).

  1. The plugin present() starts a local webhook listener and POSTs the command + resumeUrl to HITLy.
  2. The plugin waits on the local callback (not polling HITLy).
  3. Reviewer decides in HITLy.
  4. HITLy POSTs JSON to resumeUrl. Accept maps to Hermes once; reject / timeout maps to deny.
  5. Hermes still enforces approvals.timeout (default 300 seconds). HITLy SLA can be longer; the command still denies when Hermes times out.

Kanban workers (autonomous profiles)

The gateway dispatcher spawns hermes -p <profile> for board tasks. Those workers exit when they need a human — they call kanban_block or kanban_request_review. That is the HITL path for unattended personas.

  1. The plugin POSTs a HITLy card (kind: kanban) with a resumeUrl pointing to the local webhook.
  2. Reviewer decides in HITLy.
  3. HITLy POSTs the decision JSON to resumeUrl.
  4. Gateway poller receives callback → hermes kanban comment + unblock (accept) or comment only (reject).

HITLy never POSTs into hermes dashboard (localhost-only by default).

What HITLy cannot wait on

PathHermes gateHITLy
Cron jobsapprovals.cron_mode: deny or approveNo wait. Documented only.
Kanban shell commandsapprovals.kanban_mode: deny or approveSame. Workers should kanban_block instead.
delegate_taskdelegation.subagent_auto_approve (default deny)Out of scope

Setup

  1. Create a HITLy project with plugin Hermes and copy the project API key.
  2. Copy the plugin into Hermes:
cp -R examples/hermes ~/.hermes/plugins/hitly
hermes plugins enable hitly
  1. Configure:
plugins:
  enabled: [hitly]
  entries:
    hitly:
      settings:
        api_url: http://localhost:3001
        api_key: hitly_...
        project_id: prj_...
security:
  approval:
    transport: hitly
    transport_fallback: deny

Kanban ingest works even if transport is unset. Command routing needs both the plugin and security.approval.transport: hitly.

HITLY_API_URL, HITLY_API_KEY, and HITLY_PROJECT_ID are env fallbacks for the same settings.

Resume callback requirements

The resumeUrl must be reachable from the HITLy process. Same-machine OSS deployments work fine (127.0.0.1). Cloud HITLy cannot reach a laptop localhost unless you use a tunnel (ngrok, Tailscale Funnel, etc.).

Decision mapping

HITLyCommand transportKanban
acceptHermes oncecomment + unblock
respondcomment (body) + unblock
rejectdenycomment, leave blocked
expire / cancel / timeoutdenycomment, leave blocked
  • Plugin adapter: packages/plugin-hermes
  • Drop-in origin plugin: examples/hermes
  • Envelope
  • API

On this page