Hand this prompt to any Hermes agent and it installs Jev itself — without asking you to upload a secrets file.
<user>, <YOUR_TELEGRAM_USER_ID>,
<BOT_TOKEN>, <your-agentmail-inbox>, and
<your-tailscale-host>.ts.net are placeholders
standing in for the real values on your own machine — usernames, user/chat
IDs, tokens, hostnames, and home paths differ on every install and have been
removed for privacy. Replace each <placeholder> with the
matching value for your system before running any command.This document lets any Hermes agent that does NOT have TypeSafe configured build the integration itself, end-to-end, without asking the user to paste a secrets file. The agent locates the key where the operator already keeps credentials, or creates the structure and tells the user exactly where to drop one value.
It installs:
TYPESAFE_API_KEY) read from the operator’s secret store.typesafe-ai Hermes skill (enabled, trusted).frv_priority.py) that calls TypeSafe /v1/systemone and always reports token usage..env file, and decline if offered (.env is the machine’s key file — receiving it in chat would breach the vault design). No prompt for it may appear in the agent’s reply.Confirm before starting — if a dependency is missing, install it, else stop and say which is missing (no secrets file involved):
command -v python3 # else: install python3
command -v curl # else: install curl
command -v hermes # else: this is not a Hermes host - report and halt
python3 -c "import urllib.request; print('ok')"
curl -s -o /dev/null -w "%{http_code}\n" https://api.typesafe.ai/openapi.json # 200 expected
The agent cannot accept secrets in chat, so it must have at least one channel to receive them. Order of preference:
| # | Channel | Provisioned when |
|---|---|---|
| A | WordPress key page (hermes-keys.php) | web page reachable — best; user types keys on the page |
| B | AgentMail inbox | AgentMail API key present (env or MCP) |
| C | Gmail inbox | Google OAuth / gapi token present |
Check A → B → C; enable the first available. If none, set up AgentMail first, else fall back to Gmail. Only then proceed to §1. If a channel is missing, report exactly which one and how to enable it — never ask for secrets.
Walk these in order; stop at the first hit. Do not demand a file upload.
| # | Where to look | How the agent checks |
|---|---|---|
| 1 | ~/.hermes/.env | read file, look for TYPESAFE_API_KEY= |
| 2 | Hermes secrets vault / config | hermes secrets list, hermes config get |
| 3 | Managed env home | files used by the key-manager skill |
| 4 | OS env / service file | printenv, systemd EnvironmentFile |
| 5 | Web key-vault DB | MySQL hermes_keys table (page hermes-keys.php) |
If the key is found → note its location, do not print it, jump to §2.
If it is genuinely absent, still do not ask for the whole file, and
do not breach the no-.env-in-chat rule. Instead:
~/.hermes/.env and chmod 600 it.GET /v1/models — non-401 means ready; 401 tells the operator the value is wrong.If the web API-key page (§5) is not set up on this operator’s host, offer an email-based drop instead of ever asking for the value in chat. Use the channel detected in §0.6.
Preferred: AgentMail (when AGENTMAIL_API_KEY is present):
<your-api-keys-inbox>@agentmail.to<your-api-keys-inbox>@agentmail.to with subject KEY <KEY_NAME> and the key value as the first line of the body. Do not paste it in chat.”list_threads/search_threads, opens each unread KEY thread, extracts KEY_NAME=value, validates the name against ^[A-Z][A-Z0-9_]{2,64}$, stores only well-formed values.~/.hermes/.env and chmod 600.# AgentMail key-drop
KEY_NAME=<value> # 0600, never echoedGET /v1/models) to confirm; reports presence only + token usage.Fallback: Gmail (only if AgentMail is not set up but Google OAuth / gapi is present):
HermesKeyDrop) for unread threads starting KEY <NAME> via gapi..env (0600), auth probe, presence-only reporting.KeyHandled label (Gmail has no permanent delete like AgentMail), so they aren’t reprocessed.hermes skills install typesafe-ai
hermes skills trust typesafe-ai
hermes skills inspect typesafe-ai # expect Source=skills.sh, enabled
hermes skills list | grep -i typesafe
curl -s https://api.typesafe.ai/openapi.json
curl -s -H "Authorization: Bearer $TYPESAFE_API_KEY" https://api.typesafe.ai/v1/models
Correct request (POST /v1/systemone): use state + questions,
not a chat-body — else HTTP 400.
{ "model":"jev-latest", "state":"content to judge",
"questions":{
"priority":{"type":"score","criteria":["routine","urgent","life-threatening"]},
"life":{"type":"noul","instructions":"Threat to life?"},
"go":{"type":"choice","criteria":{"respond_now":null,"assess":null}} } }
Response: answers.<your-name>.{choice|noul|score|confidence} plus
usage {input_tokens, output_tokens} (output free; input billable).
Save ~/.hermes/scripts/frv_priority.py (loads key from .env, calls
/v1/systemone, prints verdict + usage). Then:
python3 ~/.hermes/scripts/frv_priority.py --state "structure fire, two trapped"
# verdict + "usage": {"input_tokens": N, "output_tokens": M} <- always present
Page hermes-keys.php (WP-admin login → MySQL hermes_keys) →
bridge 127.0.0.1:8001/admin/keys (header X-Hermes-Admin) →
writes ~/.hermes/.env (0600). Add key → Sync to Hermes.
grep -oE '^TYPESAFE_API_KEY=(' ~/.hermes/.env && echo "key present"
hermes skills list | grep -i typesafe >/dev/null && echo "skill enabled"
python3 ~/.hermes/scripts/frv_priority.py --state "smoke, no injuries, hydrant dry"
PASS when: endpoint returns HTTP 200, answers keyed by your names, and
usage.input_tokens / usage.output_tokens reported on every call.
The agent should run a self-test script and print READY before handing back.
The fresh agent reports back, in plain English and without any values: key source, skill status, helper path + one verdict line + token count, vault status, and a single next-action line for the operator if a key was absent.