aboutsummaryrefslogtreecommitdiff
path: root/skills/chatting-with-hermes.md
diff options
context:
space:
mode:
Diffstat (limited to 'skills/chatting-with-hermes.md')
-rw-r--r--skills/chatting-with-hermes.md76
1 files changed, 76 insertions, 0 deletions
diff --git a/skills/chatting-with-hermes.md b/skills/chatting-with-hermes.md
new file mode 100644
index 0000000..0bc246a
--- /dev/null
+++ b/skills/chatting-with-hermes.md
@@ -0,0 +1,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: `/_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.