From OpenClaw to Hermes The Migration That Changed Everything

OpenClaw Series · Part 6

From OpenClaw to Hermes
The Migration That Changed Everything

Five parts in, the agent worked. Then the framework moved on — and so did we. Here's why we migrated, what broke, what we kept, and what Hermes does differently.

🥧Raspberry Pi 5 · HAOS
Hermes Agent · NousResearch
🧠DeepSeek Flash · Official API
📡Telegram · Interface
📌
New to Hermes? Start with the install guide first This article covers the migration from OpenClaw to Hermes. If you haven't installed Hermes Agent on Home Assistant OS yet, begin with Part 6a — How to Install Hermes Agent on HAOS (Raspberry Pi 5) — then come back here for the migration walkthrough.

OpenClaw Worked. Until It Didn't.

Parts 1 through 5 of this series document one of the more satisfying DIY AI builds you can run at home: a Raspberry Pi 5 inside Home Assistant OS, running OpenClaw as an always-on agent, reachable via Telegram, with a full suite of Python scripts doing the actual portfolio intelligence work on the a regional stock exchange.

It worked. Daily portfolio alerts, trade signals, and swap analysis. GitHub sync at midnight. All of it running on a $80 computer consuming roughly 5W of power, with zero cloud dependency and zero recurring cost beyond a small LLM API budget.

"The LLM never touched the data. It just ran the script and forwarded the output. That was the whole architecture insight."

OpenClaw's design was elegant for that pattern: define a SKILL.md, list your Telegram trigger phrases, point at a bash command, done. For a portfolio intelligence agent that just needs to run Python scripts on demand, it was close to ideal.

Then the paths started breaking. The framework updated. The skill resolution changed. And we found ourselves spending more time maintaining compatibility than building new capabilities.

Why Hermes — and Why Now

Hermes Agent (NousResearch) had been on the radar for a while. The difference in philosophy is immediately visible: where OpenClaw uses a registry-based skill system with SKILL.md files and a clawhub package manager, Hermes treats the agent's file system as the interface. You write shell scripts. You define trigger mappings. The agent runs them.

For a setup like ours — where the intelligence is entirely in Python scripts and the LLM is just a dispatcher — Hermes is a better architectural match. There's less framework overhead between a Telegram message and a Python execution.

Key Difference OpenClaw: SKILL.md → clawhub registry → LLM skill resolution → bash.
Hermes: SOUL.md identity + direct script table → bash. Fewer moving parts.

The other factor was SOUL.md. In OpenClaw, persona lived loosely inside MEMORY.md and the agent's configuration. Hermes makes identity a first-class concern — SOUL.md is slot #1 in every system prompt, loaded fresh on every message. For an agent that a real person talks to daily via Telegram, that matters.

OpenClaw vs Hermes — What Changed

Dimension OpenClaw (Before) Hermes (After)
Framework openclawd.ai — Node.js, clawhub registry hermes-agent (NousResearch) — file-first, shell-native
Skill definition SKILL.md + clawhub install Shell scripts + SOUL.md command table
Persona MEMORY.md + agent config SOUL.md — slot #1 in system prompt, loaded fresh every message
LLM backend Gemini free tier → Claude (rate limited) → custom provider DeepSeek Flash via official DeepSeek API
Script paths /config/clawd/skills/portfolio-tracker/ /config/.hermes/scripts/ + skills/openclaw-imports/
Memory MEMORY.md + my-portfolio.json MEMORY.md + state.db (SQLite FTS) + USER.md
Trigger reliability Dependent on LLM following SKILL.md pattern Command table in SOUL.md — direct execution, no ambiguity
Interface Telegram via OpenClaw add-on Telegram via Hermes channel config

The Migration, Step by Step

The actual migration was less dramatic than the decision. The Python scripts are framework-agnostic — they don't know or care whether OpenClaw or Hermes invokes them. The work was path reconciliation and identity rebuild.

01
Install Hermes Agent on HAOS
Hermes runs as a Home Assistant add-on. Install via the add-on store or manual repository add. HERMES_HOME lands at /config/.hermes/ — everything lives there. Full install walkthrough: Part 6a — Hermes Install Guide.
02
Copy Python scripts into Hermes skills
Scripts moved from /config/clawd/skills/portfolio-tracker/ to /config/.hermes/skills/openclaw-imports/portfolio-tracker/. The folder name "openclaw-imports" was intentional — a breadcrumb acknowledging where they came from.
03
Write wrapper shell scripts
Hermes works best with simple shell scripts as execution targets. Create /config/.hermes/scripts/signals-top.sh, portfolio-update.sh, etc. — each just calls the Python script with the right arguments and path.
04
Update all hardcoded paths in Python scripts
Memory files (my-portfolio.json, yield-cache.json, etc.) moved to /config/.hermes/memory/. A one-line sed pass on each script handles most of it. Always grep after to confirm no old paths remain.
05
Write SOUL.md
This is the step that feels different from OpenClaw. SOUL.md is not configuration — it's identity. Write who the agent is, what tone it uses, what commands it executes immediately without discussion, and what it never does. Get this right and every conversation feels intentional.
06
Configure DeepSeek Flash as the LLM backend
DeepSeek Flash via the official API is fast, cheap, and capable enough for script dispatch. In Hermes: configure via openclaw configure → Model → Custom Provider (OpenAI-compatible) → DeepSeek endpoint. Add API key to providers.env.
07
Update GitHub sync scripts
The pull-from-github.sh script now also copies SOUL.md from the repo root to /config/.hermes/SOUL.md after every pull — so persona updates are version-controlled and deploy with one Telegram command.
08
Test every Telegram command
One by one: "signals top", "portfolio now", "swap signals", "pull from github". The terminal output in Telegram should show the python3 invocation with the correct new path. If it shows the old /config/clawd path, the SOUL.md command table has a stale entry.
⚠️
The Path Gotcha When Hermes shows 💻 terminal: "python3 /config/old-path/skills/por..." in Telegram, it means the command table in SOUL.md still has the old path. Fix SOUL.md, not the scripts. The command table is what Hermes reads first.

What SOUL.md Actually Does

Every framework has some version of a system prompt. Hermes makes it explicit, editable, and version-controllable. SOUL.md is loaded as slot #1 in every system prompt — before memory, before skills, before anything else. It answers the question: who is this agent?

The command table inside SOUL.md is the most operationally important section. It's not documentation — it's instruction. When the agent sees "signals top", it doesn't reason about what that might mean. The table says: run this script, immediately, no discussion.

~/.hermes/SOUL.md
# Hermes — Agent Identity

You are Hermes, a personal AI agent running on a Raspberry Pi 5
inside Home Assistant OS. Fast, sharp, always in service of your owner.

## Critical Instructions
When the user says "signals top" — immediately run the bash script
via terminal tool. Never suggest alternatives. Never use web_search.

## Tool Commands — Execute Immediately
| signals top   | bash /config/.hermes/scripts/signals-top.sh  |
| portfolio now | bash /config/.hermes/scripts/portfolio-update.sh |
| swap signals  | bash /config/.hermes/scripts/swap-signals.sh   |

## Voice
Concise. Direct. No filler. Numbers matter. Arabic-friendly.
Never say "Great question!" or "As an AI..."
💡
Version Control Your Soul Keep SOUL.md in your GitHub repo and copy it to HERMES_HOME on every pull. Your agent's identity is now a versioned artifact — you can diff who Hermes was last month versus today.

Why DeepSeek Flash for This Use Case

The LLM journey in this project has been honest about cost. We started on Claude (rate-limited on the free tier), moved to Gemini free tier, tried a local Qwen3:8B via Ollama on a PC at [local network IP], and went through several authentication debugging sessions with OpenClaw's provider system.

DeepSeek Flash via the official API is the current answer — and it's a good one for this specific use case. Here's the honest breakdown:

ADVANTAGE 01
Cost per token
DeepSeek Flash is among the cheapest frontier-class APIs available. For a portfolio agent that mostly dispatches scripts and forwards output, the monthly cost is negligible.
ADVANTAGE 02
Script dispatch quality
The task of reading a command table and running a shell script does not require a large model. DeepSeek Flash follows the SOUL.md command table reliably. That's all we need from the LLM layer.
ADVANTAGE 03
No rate limit friction
Unlike the Claude free tier, there's no daily ceiling that stops the agent mid-day. The portfolio check runs at a fixed time each trading day — it can't fail because of a rate limit.
FUTURE PATH
Claude Sonnet 4.6 when ready
For complex reasoning tasks — multi-step portfolio analysis, Home Assistant automation logic, nuanced decisions — Claude Sonnet 4.6 is the planned upgrade. The switch is one config change when budget allows.

Six Lessons from the Migration

LESSON 01
The scripts outlive the framework
portfolio.py, signals.py, swap_signals.py — none of them changed during the migration. Framework-agnostic Python is the most durable part of this stack. Write scripts first, framework second.
LESSON 02
Hardcoded paths are migration debt
Every /config/clawd/ path in a Python script was work during migration. Use config variables at the top of every script, not inline paths. One change point, not twenty.
LESSON 03
SOUL.md is the most important file
Get the command table right and 90% of Telegram interactions just work. Get it wrong and you're debugging why the agent searched the web instead of running signals.py.
LESSON 04
HERMES_HOME is /config/.hermes on HAOS
Not ~/.hermes. Not /home/user/.hermes. The Docker container resolves ~ to /config. Confirm with echo $HERMES_HOME before editing any path.
LESSON 05
Version control your identity
SOUL.md in GitHub, pulled to HERMES_HOME on every sync. Your agent's personality is now a versioned artifact. You can roll back to a previous persona if something goes wrong.
LESSON 06
The LLM is the least interesting part
Gemini, Claude, DeepSeek, local Qwen3 — we ran this agent on all of them. The portfolio intelligence quality didn't change. The Python scripts were always doing the real work.

How This Project Evolved

Part 1 — Install OpenClaw on HAOS
Raspberry Pi 5, Home Assistant OS, OpenClaw add-on, Telegram integration, first Claude API connection.
Part 2 — Portfolio Tracker Skill
portfolio.py, live prices via yfinance, bucket alerts, daily cron at a scheduled time each trading day.
Part 3 — Google Sheets Sync
sync_portfolio.py pulling live holdings from Google Sheets → JSON. Service account auth, no OAuth dance.
Part 4 — Signals + Swap Analysis
signals.py (buy/sell scoring), swap_signals.py (position improvement ranking), --top/--top3/4/5 flags, SKILL.md trigger table.
Part 5 — GitHub Backup + LLM Switching
SSH deploy keys, sync-to-github.sh, llm-switch utility, Gemini free tier as the daily driver.
Part 6 — Migration to Hermes (You Are Here)
New framework, SOUL.md identity, DeepSeek Flash backend, path reconciliation, Hermes on HAOS.
Part 7 — Claude Sonnet 4.6 + Advanced Reasoning
Switching to Anthropic for complex tasks. Multi-step portfolio analysis, HA automation logic, richer Telegram conversations.

The Migration Guide in Brief

If you built the OpenClaw setup from Parts 1–5 and want to follow the migration to Hermes, here's what you need:

Step 1 — Confirm HERMES_HOME
# In HA SSH terminal
echo $HERMES_HOME
# Should return: /config/.hermes
ls /config/.hermes/
Step 2 — Fix stale paths in SOUL.md command table
# If Telegram shows old /config/clawd paths:
# Edit /config/.hermes/SOUL.md command table
# Update each script path to the correct location
grep "python3" /config/.hermes/SOUL.md
Step 3 — Fix paths inside Python scripts
sed -i 's|/config/clawd/memory|/config/.hermes/memory|g' \
  /config/.hermes/skills/openclaw-imports/portfolio-tracker/signals.py

# Verify
grep "/config/clawd" /config/.hermes/skills/openclaw-imports/portfolio-tracker/signals.py
Step 4 — Add SOUL.md to GitHub sync
# Add to pull-from-github.sh after git pull:
cp /config/your-repo/SOUL.md /config/.hermes/SOUL.md
echo "SOUL.md synced"
Verification Test Send "signals top" in Telegram. The terminal output should show the correct path (/config/.hermes/scripts/signals-top.sh or equivalent). If it shows any old path, trace it back to the SOUL.md command table.

Comments