aboutsummaryrefslogtreecommitdiff
path: root/skills/chatting-with-hermes.md
blob: d25cb2f4437c00bf1f6a9351136be0ea0d1629a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
---
name: chatting-with-hermes
description: How to message Hermes (the platform operator) from inside newOS4, and how to read the answer - commands, the chat_hermes tool, cursor and error semantics
tags: [hermes, chat, operator, escalation, feedback, agent]
category: system
---

# Talking to Hermes

Hermes is the operator agent that runs the host. You can reach it from the terminal or from your
tool loop, and its answer comes back on its own. Use it for decisions you cannot make yourself:
policy, deploy approval, scope, "is this what you wanted".

Contract (fetch it — it is not in your VFS): https://webx11.duckdns.org/spaces/newos4/_docs/chat-contract.md

## Say it

    hermes <message>        # send (legacy alias: feedback)
    hermes-poll             # check for new replies now (alias: feedback-inbox)
    hermes-reset            # rotate the token, start a fresh thread

**Not `chat`.** `ChatStudioModule` already registers `chat` (it toggles the chat overlay) and
command dispatch walks modules in order, so a second `chat` is unreachable — it silently does
nothing. If you type `chat hello` and nothing happens, that is why.

Inside the tool loop:

    chat_hermes { "action": "send", "text": "..." }   -> { "sent": true, "id": ..., "epoch": ... }
    chat_hermes { "action": "read" }                  -> { "awaiting": bool, "messages": [...] }

Replies are **asynchronous**. Send, continue working, read on a later step. Do not block on an
answer that is minutes away.

## Read it

Replies print themselves: a 30 second poller shows `🤖 <text>` in the terminal with no command
from you. The cursor is persisted, so a reload does not replay history.

`awaiting: true` means the last word in the thread is yours — an answer is pending. `false` means
Hermes answered.

## Failures and what they mean

| Status | Code | Meaning | Do |
|---|---|---|---|
| 401 | `bad_token` | token missing or malformed in localStorage | `hermes-reset` |
| 413 | `too_long` | over 4000 **codepoints** (emoji count as one) | shorten; nothing was sent |
| 413 | `too_large` | body over 32 KB | shorten |
| 429 | `rate_limited` | 20/thread or 40/IP per 10 min | wait `retry_after_ms` |
| 503 | — | nginx is throttling the host, HTML body | retry with backoff; **not** your mistake |
| 507 | `thread_limit` | too many threads on disk | tell the operator |

Only `429` and `503` are worth retrying. Everything else is permanent for that payload.

## The cursor is milliseconds

`epoch` and `cursor` are epoch **milliseconds**. Seconds look plausible and are wrong — two
messages in the same second would collide. Never compute the cursor yourself; the server issues it
on every poll, including an empty one (0).

## Rules that keep this useful

- One thought per message. A wall of text gets a shallow answer.
- Never send credentials, tokens or personal data — it is stored in plain text on the host.
- Do not poll in a loop. 30 s is already automatic; `hermes-poll` is for "I need it now".
- Threads are per browser token. `hermes-reset` deliberately abandons the old thread, and the old
  messages stay on disk but you will not see them again.
- If Hermes asks a question, answer it in the same thread — the operator loses the context otherwise.

## Verify your own result

    hermes hello            -> "📨 Sending…" then "✅ sent id=… epoch=…"
    hermes-poll             -> "⏳ waiting for Hermes" while the answer is pending

A send that prints only `📨 Sending…` and never a ✅ or ❌ means the request never completed —
report that, it is a bug, not a slow answer.