Skip to main content

hermes-labyrinth-observability

Read-only observability dashboard plugin for Hermes Agent — journeys, crossings, guideposts, and reports.

설치로 이동

소스 정보

저장소
reason-machines/trending-skills
최근 소스 활동
2026년 5월 1일 01:44
감지된 SKILL.md 언어
영어
스타
80
포크
15

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
hermes-labyrinth-observability
description
Read-only observability dashboard plugin for Hermes Agent — journeys, crossings, guideposts, and reports.
triggers
["add hermes labyrinth to my agent setup","how do I observe my hermes agent runs","install hermes labyrinth plugin","view agent journey crossings dashboard","export hermes agent report","debug autonomous agent with labyrinth","set up hermes observability plugin","how do I read hermes labyrinth API"]
# Hermes Labyrinth > Skill by [ara.so](https://ara.so) — Daily 2026 Skills collection. Hermes Labyrinth is a **read-only observability dashboard plugin** for [Hermes Agent](https://github.com/NousResearch/hermes-agent). It turns autonomous agent runs into a navigable map of **crossings** (prompts, tool calls, tool results, failures, model switches, subagents, approvals, memory hits, redactions, context compression, cron runs) with exportable evidence. It is not a chat UI — it is a black-box recorder for agents moving through unknown work. --- ## Install ### Plugin Directory Install ```bash mkdir -p ~/.hermes/plugins git clone https://github.com/stainlu/hermes-labyrinth.git ~/.hermes/plugins/hermes-labyrinth ``` Start or restart the Hermes dashboard: ```bash hermes dashboard ``` If the dashboard is already running, rescan plugins without restarting: ```bash curl http://127.0.0.1:9119/api/dashboard/plugins/rescan ``` Open the dashboard in your browser and select the **Labyrinth** tab. ### Optional Theme ```bash mkdir -p ~/.hermes/dashboard-themes cp ~/.hermes/plugins/hermes-labyrinth/theme/hermes-labyrinth.yaml ~/.hermes/dashboard-themes/ ``` --- ## What Labyrinth Tracks | View | Contents | |---|---| | **Journey index** | Recent CLI, dashboard, gateway, cron, and delegated work | | **Labyrinth map** | Ordered crossings through a selected agent journey | | **Inspector** | Input, output, duration, status, evidence, guideposts per crossing | | **Guideposts** | Generated observations backed by local evidence | | **Skill atlas** | Bundled, optional, external, and user skill inventory | | **Cron gate** | Scheduled autonomy, next runs, last failures, workdirs | | **Model ferry** | Model/provider transitions across sessions | | **Reports** | Redacted Markdown and JSON exports for one journey | --- ## API Surface All endpoints are read-only. The plugin API is served by Hermes dashboard at: ``` http://127.0.0.1:9119/api/plugins/hermes-labyrinth/ ``` ### Endpoints ``` GET /api/plugins/hermes-labyrinth/health GET /api/plugins/hermes-labyrinth/journeys GET /api/plugins/hermes-labyrinth/journeys/{journey_id} GET /api/plugins/hermes-labyrinth/journeys/{journey_id}/crossings GET /api/plugins/hermes-labyrinth/skills GET /api/plugins/hermes-labyrinth/cron GET /api/plugins/hermes-labyrinth/guideposts GET /api/plugins/hermes-labyrinth/reports/{journey_id}.json GET /api/plugins/hermes-labyrinth/reports/{journey_id}.md ``` ### Example: Fetch All Journeys ```bash curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeys | jq . ``` ### Example: Fetch Crossings for a Journey ```bash JOURNEY_ID="your-journey-id" curl "http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeys/${JOURNEY_ID}/crossings" | jq . ``` ### Example: Export a Journey Report as Markdown ```bash JOURNEY_ID="your-journey-id" curl "http://127.0.0.1:9119/api/plugins/hermes-labyrinth/reports/${JOURNEY_ID}.md" > report.md ``` ### Example: Export a Journey Report as JSON ```bash JOURNEY_ID="your-journey-id" curl "http://127.0.0.1:9119/api/plugins/hermes-labyrinth/reports/${JOURNEY_ID}.json" > report.json ``` ### Example: Health Check ```bash curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/health ``` --- ## Python API Client Examples The plugin backend lives at `dashboard/plugin_api.py`. You can also call the HTTP API from any language. Here are Python examples: ```python import urllib.request import json BASE = "http://127.0.0.1:9119/api/plugins/hermes-labyrinth" def get_journeys(): with urllib.request.urlopen(f"{BASE}/journeys") as r: return json.loads(r.read()) def get_crossings(journey_id: str): with urllib.request.urlopen(f"{BASE}/journeys/{journey_id}/crossings") as r: return json.loads(r.read()) def get_report_json(journey_id: str): with urllib.request.urlopen(f"{BASE}/reports/{journey_id}.json") as r: return json.loads(r.read()) def get_report_md(journey_id: str) -> str: with urllib.request.urlopen(f"{BASE}/reports/{journey_id}.md") as r: return r.read().decode("utf-8") # Usage journeys = get_journeys() for j in journeys: print(j["id"], j.get("status"), j.get("started_at")) ``` ### Iterate Crossings and Inspect Tool Calls ```python import urllib.request import json BASE = "http://127.0.0.1:9119/api/plugins/hermes-labyrinth" def inspect_tool_crossings(journey_id: str): with urllib.request.urlopen(f"{BASE}/journeys/{journey_id}/crossings") as r: crossings = json.loads(r.read()) for crossing in crossings: if crossing.get("type") == "tool_call": print(f"Tool: {crossing['tool']}") print(f" Status: {crossing.get('status')}") print(f" Duration: {crossing.get('duration_ms')}ms") print(f" Input: {json.dumps(crossing.get('input', {}))[:200]}") print() inspect_tool_crossings("your-journey-id") ``` ### Download and Save All Reports for Recent Journeys ```python import urllib.request import json import pathlib BASE = "http://127.0.0.1:9119/api/plugins/hermes-labyrinth" OUT = pathlib.Path("./labyrinth-reports") OUT.mkdir(exist_ok=True) with urllib.request.urlopen(f"{BASE}/journeys") as r: journeys = json.loads(r.read()) for j in journeys[:10]: # last 10 journeys jid = j["id"] try: with urllib.request.urlopen(f"{BASE}/reports/{jid}.json") as r: (OUT / f"{jid}.json").write_bytes(r.read()) with urllib.request.urlopen(f"{BASE}/reports/{jid}.md") as r: (OUT / f"{jid}.md").write_bytes(r.read()) print(f"Saved reports for {jid}") except Exception as e: print(f"Failed {jid}: {e}") ``` --- ## JavaScript / Frontend API Examples The frontend plugin bundle lives in `dashboard/dist/`. If you're extending the UI or writing a custom integration: ```javascript const BASE = "http://127.0.0.1:9119/api/plugins/hermes-labyrinth"; async function fetchJourneys() { const res = await fetch(`${BASE}/journeys`); if (!res.ok) throw new Error(`HTTP ${res.status}`); return res.json(); } async function fetchCrossings(journeyId) { const res = await fetch(`${BASE}/journeys/${journeyId}/crossings`); if (!res.ok) throw new Error(`HTTP ${res.status}`); return res.json(); } async function fetchReportMarkdown(journeyId) { const res = await fetch(`${BASE}/reports/${journeyId}.md`); if (!res.ok) throw new Error(`HTTP ${res.status}`); return res.text(); } // Example: log all failed crossings in the most recent journey async function logFailures() { const journeys = await fetchJourneys(); if (!journeys.length) return; const crossings = await fetchCrossings(journeys[0].id); const failed = crossings.filter(c => c.status === "failure" || c.status === "error"); console.table(failed.map(c => ({ type: c.type, tool: c.tool ?? "-", duration_ms: c.duration_ms, error: c.error?.slice(0, 120), }))); } logFailures(); ``` --- ## Build & Development The frontend is built from `src/parts/*.js` + `src/labyrinth.css` into `dashboard/dist/`. The demo `index.html` is generated with content-hash query strings. ```bash # Build dashboard/dist and index.html npm run build # Run reproducibility and parse checks npm run check # Run browser smoke tests (headless Chrome) npm run smoke # Smoke-test the deployed GitHub Pages demo npm run smoke:live # Run all tests (build checks, fixture tests, smoke) npm test ``` ### Full Test Suite ```bash npm test ``` Runs: - Reproducible build checks for `dashboard/dist` and `index.html` - Frontend JavaScript parse checks - Backend Python parse checks - API normalization fixture tests (including numeric Hermes timestamps) - Packed-artifact and dead-control regressions - Headless Chrome smoke coverage for map modes, route changes, search, dataset switching, and threshold filter --- ## Repository Layout ``` . ├── dashboard/ │ ├── manifest.json # Hermes dashboard plugin manifest │ ├── plugin_api.py # Read-only API over local Hermes state │ └── dist/ # Generated dashboard plugin bundle ├── docs/ │ ├── CONCEPT.md │ ├── DESIGN_BRIEF.md │ └── FUNCTIONAL_SPEC.md ├── scripts/ │ ├── build-plugin.mjs # Builds dashboard/dist and index.html │ ├── smoke-demo.mjs # Browser smoke test for public demo │ ├── test-plugin-api.py # Fixture tests for API normalization │ └── verify.mjs # Local verification checks ├── src/ │ ├── demo/ # GitHub Pages demo source │ ├── parts/ # Ordered frontend source chunks │ └── labyrinth.css # Frontend CSS source ├── theme/ │ └── hermes-labyrinth.yaml ├── index.html # Generated GitHub Pages demo └── package.json ``` --- ## Architecture ``` Hermes local state ├─ state.db sessions/messages ├─ skills directories └─ cron config ↓ dashboard/plugin_api.py ↓ /api/plugins/hermes-labyrinth/* ↓ src/parts/*.js + src/labyrinth.css ↓ npm run build dashboard/dist/* ↓ Hermes dashboard tab: Labyrinth ``` --- ## Data Policy (Important) - **Read-only by design**: does not start, stop, resume, mutate, or create Hermes sessions. - **Secret redaction**: applied to previews and reports. - **Unknown fields**: stay unknown — not silently dropped. - **Reports**: generated from local Hermes state only. - **Public demo**: uses sample/mocked data — not live telemetry. --- ## Common Patterns ### Check Plugin Health Before Querying ```python import urllib.request, json def is_labyrinth_healthy() -> bool: try: with urllib.request.urlopen( "http://127.0.0.1:9119/api/plugins/hermes-labyrinth/health", timeout=3 ) as r: data = json.loads(r.read()) return data.get("status") == "ok" except Exception: return False if not is_labyrinth_healthy(): print("Labyrinth plugin not reachable — is `hermes dashboard` running?") ``` ### Filter Journeys by Type ```python import urllib.request, json BASE = "http://127.0.0.1:9119/api/plugins/hermes-labyrinth" with urllib.request.urlopen(f"{BASE}/journeys") as r: journeys = json.loads(r.read()) # Filter to only cron-triggered journeys cron_journeys = [j for j in journeys if j.get("origin") == "cron"] # Filter to only failed journeys failed_journeys = [j for j in journeys if j.get("status") in ("failure", "error")] ``` ### Summarize Crossing Types in a Journey ```python from collections import Counter import urllib.request, json BASE = "http://127.0.0.1:9119/api/plugins/hermes-labyrinth" def summarize_journey(journey_id: str): with urllib.request.urlopen(f"{BASE}/journeys/{journey_id}/crossings") as r: crossings = json.loads(r.read()) counts = Counter(c.get("type", "unknown") for c in crossings) total_ms = sum(c.get("duration_ms", 0) for c in crossings) print(f"Journey {journey_id}: {len(crossings)} crossings, {total_ms}ms total") for ctype, n in counts.most_common():
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기