hermes-labyrinth-observability
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseHermes Labyrinth Observability Plugin
Hermes Labyrinth 可观测性插件
Skill by ara.so — Hermes Skills collection.
Hermes Labyrinth is a read-only observability plugin for Hermes Agent that provides detailed monitoring of autonomous agent execution. It visualizes agent "journeys" as sequences of "crossings" (prompts, tool calls, results, failures, model switches, subagents) and generates exportable reports with built-in secret redaction.
由ara.so开发的Skill —— 属于Hermes Skills集合。
Hermes Labyrinth是一款面向Hermes Agent的只读可观测性插件,可对自主Agent的执行过程进行详细监控。它将Agent的“运行流程”可视化为一系列“节点交互”(提示词、工具调用、结果、失败、模型切换、子Agent),并生成内置敏感信息脱敏功能的可导出报告。
Installation
安装
Install into the Hermes user plugin directory:
bash
mkdir -p ~/.hermes/plugins
git clone https://github.com/stainlu/hermes-labyrinth.git ~/.hermes/plugins/hermes-labyrinthAfter installation, restart the Hermes dashboard:
bash
hermes dashboardThe Labyrinth tab will appear in the dashboard UI at .
http://127.0.0.1:9119将插件安装到Hermes用户插件目录:
bash
mkdir -p ~/.hermes/plugins
git clone https://github.com/stainlu/hermes-labyrinth.git ~/.hermes/plugins/hermes-labyrinth安装完成后,重启Hermes仪表盘:
bash
hermes dashboard仪表盘UI的Labyrinth标签页将在地址显示。
http://127.0.0.1:9119Docker Installation
Docker 安装
For Docker-based Hermes installations, mount the plugin directory:
bash
mkdir -p ~/.hermes/plugins
git clone https://github.com/stainlu/hermes-labyrinth.git ~/.hermes/plugins/hermes-labyrinth
cd ~/.hermes/plugins/hermes-labyrinth
git checkout v0.1.3 # Pin to reviewed versionMount the Hermes home directory into your container and restart the dashboard.
对于基于Docker的Hermes安装,需挂载插件目录:
bash
mkdir -p ~/.hermes/plugins
git clone https://github.com/stainlu/hermes-labyrinth.git ~/.hermes/plugins/hermes-labyrinth
cd ~/.hermes/plugins/hermes-labyrinth
git checkout v0.1.3 # 固定到已审核版本将Hermes主目录挂载到容器中,然后重启仪表盘。
Plugin Management
插件管理
Rescan Plugins (Frontend Only)
重新扫描插件(仅前端)
Refresh discovered frontend manifests without full restart:
bash
curl http://127.0.0.1:9119/api/dashboard/plugins/rescanNote: Backend API changes require a full dashboard restart.
无需完全重启即可刷新已发现的前端清单:
bash
curl http://127.0.0.1:9119/api/dashboard/plugins/rescan注意: 后端API变更需要完全重启仪表盘。
Disable/Remove Plugin
禁用/移除插件
bash
hermes plugins disable hermes-labyrinth
rm -rf ~/.hermes/plugins/hermes-labyrinth
curl http://127.0.0.1:9119/api/dashboard/plugins/rescanbash
hermes plugins disable hermes-labyrinth
rm -rf ~/.hermes/plugins/hermes-labyrinth
curl http://127.0.0.1:9119/api/dashboard/plugins/rescanAPI Reference
API 参考
All endpoints are read-only and include automatic secret redaction.
所有端点均为只读,并包含自动敏感信息脱敏功能。
Health Check
健康检查
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/healthReturns plugin status and Hermes state accessibility.
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/health返回插件状态及Hermes状态的可访问性。
List Journeys
列出运行流程
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeysReturns recent CLI, dashboard, gateway, cron, and delegated agent sessions.
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeys返回近期的CLI、仪表盘、网关、定时任务及委托Agent会话。
Get Journey Details
获取运行流程详情
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeys/{journey_id}Returns metadata for a specific journey including start time, status, and model usage.
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeys/{journey_id}返回特定运行流程的元数据,包括开始时间、状态和模型使用情况。
Get Journey Crossings
获取运行流程节点交互
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeys/{journey_id}/crossingsReturns ordered sequence of crossings (messages, tool calls, results) for a journey.
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeys/{journey_id}/crossings返回运行流程的节点交互有序序列(消息、工具调用、结果)。
Get Skills Inventory
获取Skill清单
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/skillsReturns:
- : effective skills loaded
skills - : expected user-over-bundled overrides
shadowed - : true duplicate diagnostics
duplicates - : skill scan errors
errors
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/skills返回:
- : 已加载的有效Skill
skills - : 用户覆盖内置Skill的预期情况
shadowed - : 重复项诊断结果
duplicates - : Skill扫描错误
errors
Get Cron Configuration
获取定时任务配置
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/cronReturns scheduled autonomy jobs, next run times, last failures, and working directories.
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/cron返回已调度的自主任务、下次运行时间、最近失败记录及工作目录。
Get Guideposts
获取观测要点
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/guidepostsReturns generated observations backed by local evidence across journeys.
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/guideposts返回基于各运行流程本地证据生成的观测结果。
Export Reports
导出报告
JSON format:
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/reports/{journey_id}.json > journey.jsonMarkdown format:
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/reports/{journey_id}.md > journey.mdBoth formats include automatic secret redaction.
JSON格式:
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/reports/{journey_id}.json > journey.jsonMarkdown格式:
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/reports/{journey_id}.md > journey.md两种格式均包含自动敏感信息脱敏功能。
Python Plugin API Extension
Python 插件API扩展
Hermes Labyrinth extends the dashboard with custom backend routes. The core implementation is in .
dashboard/plugin_api.pyHermes Labyrinth通过自定义后端路由扩展仪表盘功能。核心实现位于。
dashboard/plugin_api.pyExample: Custom API Route
示例:自定义API路由
python
from fastapi import APIRouter, HTTPException
from typing import Dict, Any
import os
router = APIRouter(prefix="/api/plugins/hermes-labyrinth")
@router.get("/custom-endpoint")
async def custom_endpoint() -> Dict[str, Any]:
"""Example custom endpoint for plugin."""
hermes_home = os.environ.get("HERMES_HOME", os.path.expanduser("~/.hermes"))
# Read-only access to Hermes state
state_db = os.path.join(hermes_home, "state.db")
if not os.path.exists(state_db):
raise HTTPException(status_code=503, detail="Hermes state unavailable")
return {
"status": "ok",
"hermes_home": hermes_home
}python
from fastapi import APIRouter, HTTPException
from typing import Dict, Any
import os
router = APIRouter(prefix="/api/plugins/hermes-labyrinth")
@router.get("/custom-endpoint")
async def custom_endpoint() -> Dict[str, Any]:
"""Example custom endpoint for plugin."""
hermes_home = os.environ.get("HERMES_HOME", os.path.expanduser("~/.hermes"))
# Read-only access to Hermes state
state_db = os.path.join(hermes_home, "state.db")
if not os.path.exists(state_db):
raise HTTPException(status_code=503, detail="Hermes state unavailable")
return {
"status": "ok",
"hermes_home": hermes_home
}Accessing Hermes State
访问Hermes状态
The plugin reads from:
- : Sessions and messages (SQLite)
~/.hermes/state.db - : User and bundled skills
~/.hermes/skills/ - : Scheduled job configurations
~/.hermes/cron/
python
import sqlite3
import os
def query_journeys(hermes_home: str):
"""Query recent sessions from Hermes state.db"""
state_db = os.path.join(hermes_home, "state.db")
conn = sqlite3.connect(state_db)
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
cursor.execute("""
SELECT session_id, created_at, updated_at, status, model
FROM sessions
ORDER BY updated_at DESC
LIMIT 100
""")
sessions = [dict(row) for row in cursor.fetchall()]
conn.close()
return sessions插件读取以下位置的信息:
- : 会话和消息(SQLite)
~/.hermes/state.db - : 用户及内置Skill
~/.hermes/skills/ - : 调度任务配置
~/.hermes/cron/
python
import sqlite3
import os
def query_journeys(hermes_home: str):
"""Query recent sessions from Hermes state.db"""
state_db = os.path.join(hermes_home, "state.db")
conn = sqlite3.connect(state_db)
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
cursor.execute("""
SELECT session_id, created_at, updated_at, status, model
FROM sessions
ORDER BY updated_at DESC
LIMIT 100
""")
sessions = [dict(row) for row in cursor.fetchall()]
conn.close()
return sessionsFrontend Development
前端开发
The dashboard UI is built from modular JavaScript components.
仪表盘UI由模块化JavaScript组件构建。
Build Process
构建流程
bash
npm run buildGenerates:
- : Combined JS from
dashboard/dist/labyrinth-bundle.jssrc/parts/*.js - : Copied from
dashboard/dist/labyrinth.csssrc/labyrinth.css - : GitHub Pages demo with content hashes
index.html
bash
npm run build生成:
- : 来自
dashboard/dist/labyrinth-bundle.js的合并JS文件src/parts/*.js - : 复制自
dashboard/dist/labyrinth.csssrc/labyrinth.css - : 带有内容哈希的GitHub Pages演示页面
index.html
Development Workflow
开发工作流
bash
undefinedbash
undefinedBuild and verify
构建并验证
npm run build
npm run check
npm run build
npm run check
Run smoke tests
运行冒烟测试
npm run smoke
npm run smoke
Test live demo
测试在线演示
npm run smoke:live
undefinednpm run smoke:live
undefinedFrontend Structure
前端结构
javascript
// src/parts/01-state.js - Global state management
const LabyrinthState = {
journeys: [],
selectedJourney: null,
crossings: [],
mode: 'chronological'
};
// src/parts/02-api.js - API client
async function fetchJourneys() {
const response = await fetch('/api/plugins/hermes-labyrinth/journeys');
return response.json();
}
// src/parts/03-components.js - UI components
function renderJourneyCard(journey) {
return `
<div class="journey-card" data-id="${journey.id}">
<h3>${escapeHtml(journey.title)}</h3>
<time>${new Date(journey.created_at * 1000).toLocaleString()}</time>
</div>
`;
}javascript
// src/parts/01-state.js - 全局状态管理
const LabyrinthState = {
journeys: [],
selectedJourney: null,
crossings: [],
mode: 'chronological'
};
// src/parts/02-api.js - API客户端
async function fetchJourneys() {
const response = await fetch('/api/plugins/hermes-labyrinth/journeys');
return response.json();
}
// src/parts/03-components.js - UI组件
function renderJourneyCard(journey) {
return `
<div class="journey-card" data-id="${journey.id}">
<h3>${escapeHtml(journey.title)}</h3>
<time>${new Date(journey.created_at * 1000).toLocaleString()}</time>
</div>
`;
}Configuration
配置
Optional Theme
可选主题
bash
mkdir -p ~/.hermes/dashboard-themes
cp ~/.hermes/plugins/hermes-labyrinth/theme/hermes-labyrinth.yaml ~/.hermes/dashboard-themes/bash
mkdir -p ~/.hermes/dashboard-themes
cp ~/.hermes/plugins/hermes-labyrinth/theme/hermes-labyrinth.yaml ~/.hermes/dashboard-themes/Plugin Manifest
插件清单
Located at :
dashboard/manifest.jsonjson
{
"name": "hermes-labyrinth",
"version": "0.1.3",
"title": "Labyrinth",
"description": "Agent journey observability",
"entry_js": "dist/labyrinth-bundle.js",
"entry_css": "dist/labyrinth.css",
"api_module": "plugin_api"
}位于:
dashboard/manifest.jsonjson
{
"name": "hermes-labyrinth",
"version": "0.1.3",
"title": "Labyrinth",
"description": "Agent journey observability",
"entry_js": "dist/labyrinth-bundle.js",
"entry_css": "dist/labyrinth.css",
"api_module": "plugin_api"
}Common Patterns
常见用法
Filtering Journeys by Status
按状态过滤运行流程
bash
undefinedbash
undefinedGet all journeys and filter with jq
获取所有运行流程并使用jq过滤
curl -s http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeys |
jq '.journeys[] | select(.status == "completed")'
jq '.journeys[] | select(.status == "completed")'
undefinedcurl -s http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeys |
jq '.journeys[] | select(.status == "completed")'
jq '.journeys[] | select(.status == "completed")'
undefinedAnalyzing Tool Call Patterns
分析工具调用模式
bash
undefinedbash
undefinedGet crossings and count tool types
获取节点交互并统计工具类型
curl -s http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeys/{journey_id}/crossings |
jq '.crossings[] | select(.type == "tool_call") | .tool_name' |
sort | uniq -c
jq '.crossings[] | select(.type == "tool_call") | .tool_name' |
sort | uniq -c
undefinedcurl -s http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeys/{journey_id}/crossings |
jq '.crossings[] | select(.type == "tool_call") | .tool_name' |
sort | uniq -c
jq '.crossings[] | select(.type == "tool_call") | .tool_name' |
sort | uniq -c
undefinedExporting Multiple Journeys
导出多个运行流程
bash
undefinedbash
undefinedExport last 10 journeys as JSON
导出最近10个运行流程为JSON格式
curl -s http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeys |
jq -r '.journeys[].id' | head -10 | while read id; do curl -s "http://127.0.0.1:9119/api/plugins/hermes-labyrinth/reports/$id.json" > "journey_$id.json" done
jq -r '.journeys[].id' | head -10 | while read id; do curl -s "http://127.0.0.1:9119/api/plugins/hermes-labyrinth/reports/$id.json" > "journey_$id.json" done
undefinedcurl -s http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeys |
jq -r '.journeys[].id' | head -10 | while read id; do curl -s "http://127.0.0.1:9119/api/plugins/hermes-labyrinth/reports/$id.json" > "journey_$id.json" done
jq -r '.journeys[].id' | head -10 | while read id; do curl -s "http://127.0.0.1:9119/api/plugins/hermes-labyrinth/reports/$id.json" > "journey_$id.json" done
undefinedMonitoring Agent Failures
监控Agent失败情况
bash
undefinedbash
undefinedList failed journeys with error details
列出失败的运行流程及错误详情
curl -s http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeys |
jq '.journeys[] | select(.status == "failed") | {id, error, updated_at}'
jq '.journeys[] | select(.status == "failed") | {id, error, updated_at}'
undefinedcurl -s http://127.0.0.1:9119/api/plugins/hermes-labyrinth/journeys |
jq '.journeys[] | select(.status == "failed") | {id, error, updated_at}'
jq '.journeys[] | select(.status == "failed") | {id, error, updated_at}'
undefinedSecurity and Redaction
安全与脱敏
Labyrinth applies Hermes core secret redaction to all outputs:
python
from hermes.redactor import redact_secrets
def safe_export(content: str) -> str:
"""Apply redaction before export."""
try:
return redact_secrets(content)
except Exception:
# Fail closed if redactor unavailable
return "[redaction unavailable]"Labyrinth对所有输出应用Hermes核心敏感信息脱敏功能:
python
from hermes.redactor import redact_secrets
def safe_export(content: str) -> str:
"""Apply redaction before export."""
try:
return redact_secrets(content)
except Exception:
# 若脱敏工具不可用则关闭导出
return "[redaction unavailable]"Verification Before Production
生产环境前验证
Test redaction with dummy secrets:
bash
undefined使用模拟敏感信息测试脱敏功能:
bash
undefinedCreate test journey with dummy API keys in prompts/outputs
创建测试运行流程,在提示词/输出中包含模拟API密钥
hermes chat "Test: sk-dummy-key-12345"
hermes chat "Test: sk-dummy-key-12345"
Verify redaction in UI and exports
在UI和导出内容中验证脱敏效果
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/reports/{journey_id}.json | grep "sk-dummy"
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/reports/{journey_id}.json | grep "sk-dummy"
Should return nothing if redaction works
若脱敏生效则无返回结果
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/reports/{journey_id}.md | grep "sk-dummy"
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/reports/{journey_id}.md | grep "sk-dummy"
Should return nothing if redaction works
若脱敏生效则无返回结果
undefinedundefinedTesting
测试
Run Full Test Suite
运行完整测试套件
bash
npm testIncludes:
- Build reproducibility checks
- JavaScript/Python parse validation
- API normalization fixture tests
- Headless Chrome smoke tests
bash
npm test包括:
- 构建可重复性检查
- JavaScript/Python解析验证
- API标准化 fixture测试
- 无头Chrome冒烟测试
Backend API Tests
后端API测试
bash
python3 scripts/test-plugin-api.pyTests timestamp normalization, redaction, and data structure handling.
bash
python3 scripts/test-plugin-api.py测试时间戳标准化、脱敏及数据结构处理。
Manual Smoke Test
手动冒烟测试
bash
npm run smokeRuns headless Chrome against built demo:
- Map mode switching
- Route navigation
- Search functionality
- Dataset switching
- Threshold filtering
bash
npm run smoke针对构建好的演示页面运行无头Chrome测试:
- 地图模式切换
- 路由导航
- 搜索功能
- 数据集切换
- 阈值过滤
Troubleshooting
故障排查
Plugin Not Appearing in Dashboard
插件未在仪表盘显示
- Verify installation path:
bash
ls -la ~/.hermes/plugins/hermes-labyrinth/dashboard/manifest.json- Restart dashboard (rescan doesn't mount new Python routes):
bash
undefined- 验证安装路径:
bash
ls -la ~/.hermes/plugins/hermes-labyrinth/dashboard/manifest.json- 重启仪表盘(重新扫描不会挂载新的Python路由):
bash
undefinedStop dashboard
停止仪表盘
hermes dashboard stop
hermes dashboard stop
Start dashboard
启动仪表盘
hermes dashboard
3. Check dashboard logs for plugin API import errors.hermes dashboard
3. 检查仪表盘日志中的插件API导入错误。Backend/API Diagnostic in UI
UI中显示后端/API诊断
This means the Python API routes failed to load:
- Restart dashboard completely (not just rescan)
- Check Python imports:
bash
python3 -c "import sys; sys.path.insert(0, '$HOME/.hermes/plugins/hermes-labyrinth/dashboard'); import plugin_api"- Verify Hermes home exists:
bash
ls -la ~/.hermes/state.db这表示Python API路由加载失败:
- 完全重启仪表盘(不仅仅是重新扫描)
- 检查Python导入:
bash
python3 -c "import sys; sys.path.insert(0, '$HOME/.hermes/plugins/hermes-labyrinth/dashboard'); import plugin_api"- 验证Hermes主目录存在:
bash
ls -la ~/.hermes/state.dbRedaction Unavailable Error
脱敏不可用错误
If reports show :
[redaction unavailable]- Verify Hermes core is installed properly
- Check redactor import:
python
from hermes.redactor import redact_secrets- This is a fail-closed safety mechanism — plugin won't export unredacted content
若报告显示:
[redaction unavailable]- 验证Hermes核心组件已正确安装
- 检查脱敏工具导入:
python
from hermes.redactor import redact_secrets- 这是一个安全关闭机制——插件不会导出未脱敏的内容
Empty Journeys List
运行流程列表为空
- Verify agent sessions exist:
bash
sqlite3 ~/.hermes/state.db "SELECT COUNT(*) FROM sessions;"- Check file permissions:
bash
ls -la ~/.hermes/state.db- Run health check:
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/health- 验证Agent会话存在:
bash
sqlite3 ~/.hermes/state.db "SELECT COUNT(*) FROM sessions;"- 检查文件权限:
bash
ls -la ~/.hermes/state.db- 运行健康检查:
bash
curl http://127.0.0.1:9119/api/plugins/hermes-labyrinth/healthBuild Failures
构建失败
bash
undefinedbash
undefinedClean and rebuild
清理并重新构建
rm -rf dashboard/dist index.html
npm run build
npm run check
undefinedrm -rf dashboard/dist index.html
npm run build
npm run check
undefinedDevelopment References
开发参考
- Live demo: https://stainlu.github.io/hermes-labyrinth/
- Hermes Agent: https://github.com/NousResearch/hermes-agent
- Plugin docs: ,
docs/CONCEPT.md,docs/DESIGN_BRIEF.mddocs/FUNCTIONAL_SPEC.md - License: MIT
- 在线演示: https://stainlu.github.io/hermes-labyrinth/
- Hermes Agent: https://github.com/NousResearch/hermes-agent
- 插件文档: ,
docs/CONCEPT.md,docs/DESIGN_BRIEF.mddocs/FUNCTIONAL_SPEC.md - 许可证: MIT