remove: BOOT.md built-in hook (#17093)
BOOT.md was merged in PR #3733 before the feature was ready — the built-in hook spawned a bare AIAgent() with no model/runtime kwargs, which immediately 401s on any provider with a custom endpoint. Three separate community PRs (#5240, #12514, #14992) tried to paper over it. Remove the BOOT.md hook entirely and its user-facing docs/tips. Keep the gateway/builtin_hooks/ package and the HookRegistry._register_builtin_hooks() hook-point intact as the extension surface for future always-on gateway hooks. Closes #5239. Co-authored-by: teknium1 <teknium@users.noreply.github.com>
This commit is contained in:
parent
b5128a751b
commit
b53a091b97
@ -38,7 +38,7 @@ hermes-agent/
|
|||||||
│ │ # homeassistant, signal, matrix, mattermost, email, sms,
|
│ │ # homeassistant, signal, matrix, mattermost, email, sms,
|
||||||
│ │ # dingtalk, wecom, weixin, feishu, qqbot, bluebubbles,
|
│ │ # dingtalk, wecom, weixin, feishu, qqbot, bluebubbles,
|
||||||
│ │ # webhook, api_server, ...). See ADDING_A_PLATFORM.md.
|
│ │ # webhook, api_server, ...). See ADDING_A_PLATFORM.md.
|
||||||
│ └── builtin_hooks/ # Always-registered gateway hooks (boot-md, ...)
|
│ └── builtin_hooks/ # Extension point for always-registered gateway hooks (none shipped)
|
||||||
├── plugins/ # Plugin system (see "Plugins" section below)
|
├── plugins/ # Plugin system (see "Plugins" section below)
|
||||||
│ ├── memory/ # Memory-provider plugins (honcho, mem0, supermemory, ...)
|
│ ├── memory/ # Memory-provider plugins (honcho, mem0, supermemory, ...)
|
||||||
│ ├── context_engine/ # Context-engine plugins
|
│ ├── context_engine/ # Context-engine plugins
|
||||||
|
|||||||
@ -1,85 +0,0 @@
|
|||||||
"""Built-in boot-md hook — run ~/.hermes/BOOT.md on gateway startup.
|
|
||||||
|
|
||||||
This hook is always registered. It silently skips if no BOOT.md exists.
|
|
||||||
To activate, create ``~/.hermes/BOOT.md`` with instructions for the
|
|
||||||
agent to execute on every gateway restart.
|
|
||||||
|
|
||||||
Example BOOT.md::
|
|
||||||
|
|
||||||
# Startup Checklist
|
|
||||||
|
|
||||||
1. Check if any cron jobs failed overnight
|
|
||||||
2. Send a status update to Discord #general
|
|
||||||
3. If there are errors in /opt/app/deploy.log, summarize them
|
|
||||||
|
|
||||||
The agent runs in a background thread so it doesn't block gateway
|
|
||||||
startup. If nothing needs attention, it replies with [SILENT] to
|
|
||||||
suppress delivery.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import threading
|
|
||||||
|
|
||||||
logger = logging.getLogger("hooks.boot-md")
|
|
||||||
|
|
||||||
from hermes_constants import get_hermes_home
|
|
||||||
HERMES_HOME = get_hermes_home()
|
|
||||||
BOOT_FILE = HERMES_HOME / "BOOT.md"
|
|
||||||
|
|
||||||
|
|
||||||
def _build_boot_prompt(content: str) -> str:
|
|
||||||
"""Wrap BOOT.md content in a system-level instruction."""
|
|
||||||
return (
|
|
||||||
"You are running a startup boot checklist. Follow the BOOT.md "
|
|
||||||
"instructions below exactly.\n\n"
|
|
||||||
"---\n"
|
|
||||||
f"{content}\n"
|
|
||||||
"---\n\n"
|
|
||||||
"Execute each instruction. If you need to send a message to a "
|
|
||||||
"platform, use the send_message tool.\n"
|
|
||||||
"If nothing needs attention and there is nothing to report, "
|
|
||||||
"reply with ONLY: [SILENT]"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _run_boot_agent(content: str) -> None:
|
|
||||||
"""Spawn a one-shot agent session to execute the boot instructions."""
|
|
||||||
try:
|
|
||||||
from run_agent import AIAgent
|
|
||||||
|
|
||||||
prompt = _build_boot_prompt(content)
|
|
||||||
agent = AIAgent(
|
|
||||||
quiet_mode=True,
|
|
||||||
skip_context_files=True,
|
|
||||||
skip_memory=True,
|
|
||||||
max_iterations=20,
|
|
||||||
)
|
|
||||||
result = agent.run_conversation(prompt)
|
|
||||||
response = result.get("final_response", "")
|
|
||||||
if response and "[SILENT]" not in response:
|
|
||||||
logger.info("boot-md completed: %s", response[:200])
|
|
||||||
else:
|
|
||||||
logger.info("boot-md completed (nothing to report)")
|
|
||||||
except Exception as e:
|
|
||||||
logger.error("boot-md agent failed: %s", e)
|
|
||||||
|
|
||||||
|
|
||||||
async def handle(event_type: str, context: dict) -> None:
|
|
||||||
"""Gateway startup handler — run BOOT.md if it exists."""
|
|
||||||
if not BOOT_FILE.exists():
|
|
||||||
return
|
|
||||||
|
|
||||||
content = BOOT_FILE.read_text(encoding="utf-8").strip()
|
|
||||||
if not content:
|
|
||||||
return
|
|
||||||
|
|
||||||
logger.info("Running BOOT.md (%d chars)", len(content))
|
|
||||||
|
|
||||||
# Run in a background thread so we don't block gateway startup.
|
|
||||||
thread = threading.Thread(
|
|
||||||
target=_run_boot_agent,
|
|
||||||
args=(content,),
|
|
||||||
name="boot-md",
|
|
||||||
daemon=True,
|
|
||||||
)
|
|
||||||
thread.start()
|
|
||||||
@ -52,19 +52,13 @@ class HookRegistry:
|
|||||||
return list(self._loaded_hooks)
|
return list(self._loaded_hooks)
|
||||||
|
|
||||||
def _register_builtin_hooks(self) -> None:
|
def _register_builtin_hooks(self) -> None:
|
||||||
"""Register built-in hooks that are always active."""
|
"""Register built-in hooks that are always active.
|
||||||
try:
|
|
||||||
from gateway.builtin_hooks.boot_md import handle as boot_md_handle
|
|
||||||
|
|
||||||
self._handlers.setdefault("gateway:startup", []).append(boot_md_handle)
|
Currently empty — no shipped built-in hooks. Kept as the extension
|
||||||
self._loaded_hooks.append({
|
point for future always-on gateway hooks so they drop in without
|
||||||
"name": "boot-md",
|
re-plumbing discover_and_load().
|
||||||
"description": "Run ~/.hermes/BOOT.md on gateway startup",
|
"""
|
||||||
"events": ["gateway:startup"],
|
return
|
||||||
"path": "(builtin)",
|
|
||||||
})
|
|
||||||
except Exception as e:
|
|
||||||
print(f"[hooks] Could not load built-in boot-md hook: {e}", flush=True)
|
|
||||||
|
|
||||||
def discover_and_load(self) -> None:
|
def discover_and_load(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -263,7 +263,6 @@ TIPS = [
|
|||||||
"hermes status --deep runs deeper diagnostic checks across all components.",
|
"hermes status --deep runs deeper diagnostic checks across all components.",
|
||||||
|
|
||||||
# --- Hidden Gems & Power-User Tricks ---
|
# --- Hidden Gems & Power-User Tricks ---
|
||||||
"BOOT.md at ~/.hermes/BOOT.md runs automatically on every gateway start — use it for startup checks.",
|
|
||||||
"Cron jobs can attach a Python script (--script) whose stdout is injected into the prompt as context.",
|
"Cron jobs can attach a Python script (--script) whose stdout is injected into the prompt as context.",
|
||||||
"Cron scripts live in ~/.hermes/scripts/ and run before the agent — perfect for data collection pipelines.",
|
"Cron scripts live in ~/.hermes/scripts/ and run before the agent — perfect for data collection pipelines.",
|
||||||
"prefill_messages_file in config.yaml injects few-shot examples into every API call, never saved to history.",
|
"prefill_messages_file in config.yaml injects few-shot examples into every API call, never saved to history.",
|
||||||
|
|||||||
@ -116,7 +116,7 @@ hermes-agent/
|
|||||||
│ ├── hooks.py # Hook discovery and lifecycle events
|
│ ├── hooks.py # Hook discovery and lifecycle events
|
||||||
│ ├── mirror.py # Cross-session message mirroring
|
│ ├── mirror.py # Cross-session message mirroring
|
||||||
│ ├── status.py # Token locks, profile-scoped process tracking
|
│ ├── status.py # Token locks, profile-scoped process tracking
|
||||||
│ ├── builtin_hooks/ # Always-registered hooks
|
│ ├── builtin_hooks/ # Extension point for always-registered hooks (none shipped)
|
||||||
│ └── platforms/ # 18 adapters: telegram, discord, slack, whatsapp,
|
│ └── platforms/ # 18 adapters: telegram, discord, slack, whatsapp,
|
||||||
│ # signal, matrix, mattermost, email, sms,
|
│ # signal, matrix, mattermost, email, sms,
|
||||||
│ # dingtalk, feishu, wecom, wecom_callback, weixin,
|
│ # dingtalk, feishu, wecom, wecom_callback, weixin,
|
||||||
|
|||||||
@ -20,7 +20,7 @@ The messaging gateway is the long-running process that connects Hermes to 14+ ex
|
|||||||
| `gateway/hooks.py` | Hook discovery, loading, and lifecycle event dispatch |
|
| `gateway/hooks.py` | Hook discovery, loading, and lifecycle event dispatch |
|
||||||
| `gateway/mirror.py` | Cross-session message mirroring for `send_message` |
|
| `gateway/mirror.py` | Cross-session message mirroring for `send_message` |
|
||||||
| `gateway/status.py` | Token lock management for profile-scoped gateway instances |
|
| `gateway/status.py` | Token lock management for profile-scoped gateway instances |
|
||||||
| `gateway/builtin_hooks/` | Always-registered hooks (e.g., BOOT.md system prompt hook) |
|
| `gateway/builtin_hooks/` | Extension point for always-registered hooks (none shipped) |
|
||||||
| `gateway/platforms/` | Platform adapters (one per messaging platform) |
|
| `gateway/platforms/` | Platform adapters (one per messaging platform) |
|
||||||
|
|
||||||
## Architecture Overview
|
## Architecture Overview
|
||||||
|
|||||||
@ -89,26 +89,6 @@ Handlers registered for `command:*` fire for any `command:` event (`command:mode
|
|||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
#### Boot Checklist (BOOT.md) — Built-in
|
|
||||||
|
|
||||||
The gateway ships with a built-in `boot-md` hook that looks for `~/.hermes/BOOT.md` on every startup. If the file exists, the agent runs its instructions in a background session. No installation needed — just create the file.
|
|
||||||
|
|
||||||
**Create `~/.hermes/BOOT.md`:**
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
# Startup Checklist
|
|
||||||
|
|
||||||
1. Check if any cron jobs failed overnight — run `hermes cron list`
|
|
||||||
2. Send a message to Discord #general saying "Gateway restarted, all systems go"
|
|
||||||
3. Check if /opt/app/deploy.log has any errors from the last 24 hours
|
|
||||||
```
|
|
||||||
|
|
||||||
The agent runs these instructions in a background thread so it doesn't block gateway startup. If nothing needs attention, the agent replies with `[SILENT]` and no message is delivered.
|
|
||||||
|
|
||||||
:::tip
|
|
||||||
No BOOT.md? The hook silently skips — zero overhead. Create the file whenever you need startup automation, delete it when you don't.
|
|
||||||
:::
|
|
||||||
|
|
||||||
#### Telegram Alert on Long Tasks
|
#### Telegram Alert on Long Tasks
|
||||||
|
|
||||||
Send yourself a message when the agent takes more than 10 steps:
|
Send yourself a message when the agent takes more than 10 steps:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user