用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/lukemcqueen/hermes-cortex --skill pgmq-consumer-patterns命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Cross-server agent health monitoring using binary status vectors — deploy health endpoints on each agent, poll from orchestrator, alert on state transitions.
Wire a self-hosted Langfuse instance to Hermes Agent — generate API keys, configure env vars, enable the bundled plugin, install SDK, and verify traces flow.
Use before enforcement code changes or shared-repo commits.
基于 SOC 职业分类
正在显示 SKILL.md
| name | pgmq-consumer-patterns |
| description | Use when fixing bus consumers or false-unreachable agents. |
| version | 1.0.0 |
| author | Hermes Cortex |
| metadata | {"hermes":{"tags":["bus","pgmq","consumers","migration","health"],"related_skills":["cortex-bus","cortex-bus-automation","agent-health-monitoring"]}} |
Class-level patterns for building and debugging PGMQ bus consumers, learned from the inbox→PGMQ migration (2026-08). Applies to any queue where one process drains and others need the data.
Rule: Any queue that one cron drains is invisible to other consumers. PGMQ
read pops only pending messages; a consumer that runs after the drainer
will find the queue empty every time. Never have a second consumer race the
drainer on the live queue — especially an hourly consumer vs a 10-minute
drainer.
Correct design:
producer ──send──> queue ──drainer (every 10m)──> archive
└── persist latest per key ──> state.json
consumer (hourly) ──reads state.json──> data
consumer fallback: bus_read(queue, vt=60) peek for not-yet-drained pings
Example (health pings, fixed 2026-08-04, commit 87df0c73):
orch-clean-health-queue.py drains inbox_health_check every 10m; while
archiving it persists each agent's latest vector+ts to
~/.hermes-cortex/state/inbox-health-state.json and updates last-seen.json.orch-health-report.py reads that state file; live bus_read is only a
fallback for pings the drainer hasn't caught yet.Symptoms of violating this rule: "agent 🔴 unreachable despite healthy
pushes", stale last-seen.json for days/weeks, queue depth near 0 at consumer
time.
Rule: When a transport migrates (file inbox → PGMQ bus, HTTP → gRPC, etc.), the old endpoint often disappears with no error to callers. Any consumer still hitting the retired surface gets a silent 404 → returns None → downstream false alarms. Docs and skills lag too.
Sweep checklist (grep the whole repo, not just the obvious dirs):
grep -rn "api/inbox\|api/delete\|MOSES_INBOX_URL\|moses-inbox.conf" ops/ scripts/ skills/ docs/
Also grep for removed script names (e.g. orch-team-health) — docs reference
them long after deletion.
Verify claims against LIVE code before fixing: the proposal said a skill was
stale; confirmation required checking (a) the deployed bus server's route table
(no /api/inbox), (b) the actual push script's endpoint, (c) which consumer
still called the old API, (d) whether the referenced poller was removed from the
repo (git log --diff-filter=D).
After a consumer fix, prove the full path with real messages:
bus_send("inbox_health_check", {"from": "<agent>", "subject": "health", "body": "{...}"})CORTEX_REPO and
PYTHONPATH=ops/scripts — direct python3 path/to/script.py from another
cwd fails the hermes_paths import).Rule: A mirror/forwarder failure alert disappearing does NOT mean the peer delivery succeeded. Any consumer that takes the same message off the source queue makes the next mirror tick silent.
Verified example (2026-08-07, orch-bus-forwarder-sync): the alert
⚠️ LOCAL→PEER: 1 failed • inbox_orchestrator/ee8d75afb2 fired on 2 ticks for
a kustos PROPOSAL, then stopped — not because the peer received it, but
because the backup orchestrator's agent-message-handler polls the shared
inbox_orchestrator directly and archived the message from the source queue
(bus.archives.archived_by='esther', 3 min after enqueue). The mirror never
delivered it.
Correct diagnosis:
~/.hermes/cron/output/<job_id>/):
one message alerting 2–3 ticks then silent = consumed or transient; the
same message alerting EVERY tick = persistent auth/ACL problem.bus.archive() INSERTs into bus.archives
then DELETEs from bus.messages — archived rows persist with
archived_at + archived_by. archived_by=esther on inbox_orchestrator
= backup consumed directly, never mirrored. bus.delete() hard-purges with
zero trace; bus.recover_timeouts() never touches fresh pending
main-queue messages.queue/dkey[-10:],
dkey = corr:<correlation_id> or
hash:<sha256(json.dumps(body, sort_keys=True, default=str))[:32]>. A hash
ID is computed at runtime and matches NOTHING in the DB — recompute it over
candidate archived bodies and compare the tail. Corr-based IDs ARE
searchable via the correlation_id column.Full worked example (timeline, SQL queries, hash-recompute snippet):
references/forwarder-failure-diagnosis.md.
PYTHONPATH from
build_subprocess_env(); a bare python3 script.py from a random cwd will
ModuleNotFoundError: hermes_paths. Reproduce the cron env
(CORTEX_REPO=~/hermes-cortex PYTHONPATH=~/hermes-cortex/ops/scripts).cortex-update.sh, then verify the deployed file (SOURCE header differs
from repo raw MD5 — hash comparison must strip the header).