ChatGPT-style automatic titles for every Hermes Agent conversation.
A hook-driven plugin: after every turn it makes sure the conversation has a good title — generated from the whole conversation (not just the first message like Hermes' built-in titler), in the conversation's own language, using your currently active model (no extra API key). Titles you set yourself are never touched.
为 Hermes Agent 打造的 ChatGPT 式自动命名插件:每轮对话结束后自动检查, 没有标题就用整场对话内容生成一个简短自然的标题(而非只看第一句话), 跟随对话语言,使用你当前激活的模型,无需额外 API Key。你手动设置的标题 永不覆盖。
Hermes' built-in auto-titler only looks at the first exchange (500 chars). Two problems:
- It fails silently sometimes — sessions pile up as untitled ("—")
- The title reflects only how the conversation started — a session that began with "hello" but did real work gets titled "英文问候"
session-scribe fixes both:
- Every conversation gets a title — retried on every turn until success
- Whole-conversation awareness — the title describes what actually happened, and improves in accuracy
- User titles are sacred —
/titleor/scribe renametitles are never overwritten - Title auditor —
hermes scribe auditcompares every existing title against its full transcript (dry-run first, then apply) - Optional full reports — the v0.1 report-style summaries still exist,
but only when you ask (
/scribe make)
# 1. Copy the plugin into the Hermes plugins dir
# (Windows: %LOCALAPPDATA%\hermes\plugins\ — Linux/macOS: ~/.hermes/plugins/)
git clone <this-repo> "$HERMES_HOME/plugins/session-scribe"
# or just copy the folder there
# 2. Enable it (plugins are opt-in by default)
hermes plugins enable session-scribe
# 3. Restart your session / gateway. Check:
hermes plugins listOptional config in config.yaml(可选配置):
scribe:
auto_title: true # master switch for hook-driven titling
improve_titles: false # re-title auto-titled sessions when they drift
max_transcript_chars: 12000
max_message_chars: 800
auto_report: false # legacy: auto-write full markdown reportsIn-session slash commands:
/scribe status
/scribe missing [N] sessions WITHOUT a title
/scribe list [N] recent sessions WITH titles
/scribe show <id|title> one session's title + origin
/scribe retitle <id> regenerate a title from the full conversation
/scribe retitle --scan batch-title ALL untitled history
/scribe audit [--apply] check every title vs its conversation
/scribe rename <id> <new> set a title manually
/scribe make [id] full markdown report (opt-in extra)
/scribe on | off toggle auto titling
From a terminal:
hermes scribe status
hermes scribe missing
hermes scribe audit # dry run: show title mismatches
hermes scribe audit --apply # fix them
hermes scribe rename 20260514_222212_b755f7 "正确的新标题"
hermes scribe audit --limit 100 # 1. preview old -> new table
hermes scribe audit --apply --limit 100 # 2. apply the fixesEvery rename is logged to $HERMES_HOME/scribe/scribe.log (old → new), so
changes are always recoverable.
run_agent.py ── on_session_end(session_id, ...) ──▶ hook (every turn)
│ daemon thread
SessionDB.get_messages() ──▶ transcript
│
PluginLlm.complete() ──▶ short title
│
no title? → set it (retries next turn)
user title? → untouched
on_session_endfires at the end of everyrun_conversationcall (CLI + gateway). Work runs in a daemon thread — the agent loop is never blocked.- Titles are generated in the conversation's language.
- Privacy: transcripts go only to your own configured LLM provider.
- Built strictly on the public plugin surface:
register(ctx)+ctx.register_hook/register_command/register_cli_command+agent.plugin_llm.PluginLlm+hermes_state.SessionDB. No core-file patches, per Hermes' plugin rules. max_tokensfor title calls is deliberately generous (700): reasoning models spend tokens thinking first, and a tight budget returns an empty body.<think>blocks are stripped from responses.- LLM calls retry up to 3× on transient errors (main endpoint timeouts) and fail fast on auth errors (fallback-chain keys won't heal on retry).
MIT