> ## Documentation Index
> Fetch the complete documentation index at: https://felimet-hub.jmcores.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 05-4 OpenClaw, Hermes-Agent, and NemoClaw: Three Routes Compared

> A full-dimension comparison of three open-source agent frameworks: positioning, Skill design, memory mechanisms, enterprise readiness, and what you should learn from each.

export const FrameworkMap = ({lang = "zh", title, layers = []}) => {
  const t = lang === "en" ? {
    hint: "Click a module to see details",
    layer: "Layer",
    module: "Module",
    responsibilities: "Responsibilities",
    path: "Key path",
    relations: "Connected to",
    noSelect: "Select a module above"
  } : {
    hint: "點模組卡片查看職責與關係",
    layer: "層",
    module: "模組",
    responsibilities: "職責",
    path: "關鍵路徑",
    relations: "連結到",
    noSelect: "點上方模組查看詳細說明"
  };
  const [selected, setSelected] = useState(null);
  const safe = Array.isArray(layers) ? layers : [];
  const PALETTE = {
    blue: {
      base: "#5b6c8f",
      bg: "#5b6c8f18",
      border: "#5b6c8f55",
      label: "#46587a"
    },
    purple: {
      base: "#8a6f8e",
      bg: "#8a6f8e18",
      border: "#8a6f8e55",
      label: "#6f5673"
    },
    yellow: {
      base: "#c9a35b",
      bg: "#c9a35b18",
      border: "#c9a35b55",
      label: "#9a7a3c"
    },
    green: {
      base: "#8a9a7b",
      bg: "#8a9a7b18",
      border: "#8a9a7b55",
      label: "#6a7a5c"
    },
    teal: {
      base: "#6f9290",
      bg: "#6f929018",
      border: "#6f929055",
      label: "#527472"
    },
    rose: {
      base: "#ab7269",
      bg: "#ab726918",
      border: "#ab726955",
      label: "#8e564e"
    },
    amber: {
      base: "#b9835c",
      bg: "#b9835c18",
      border: "#b9835c55",
      label: "#96683f"
    }
  };
  const ROTATION = ["blue", "purple", "yellow", "green", "teal", "rose"];
  const getColor = (layer, index) => {
    const key = layer.color && PALETTE[layer.color] ? layer.color : ROTATION[index % ROTATION.length];
    return PALETTE[key];
  };
  const sel = (() => {
    if (!selected) return null;
    for (let li = 0; li < safe.length; li++) {
      const layer = safe[li];
      const m = layer.modules.find(m => m.id === selected);
      if (m) return {
        module: m,
        layerLabel: layer.label,
        color: getColor(layer, li)
      };
    }
    return null;
  })();
  const css = `
.fm-root{--fm-bg:#FAF8F3;--fm-surface2:rgba(0,0,0,0.022);
  --fm-border:rgba(0,0,0,0.08);--fm-text:#2b2722;--fm-dim:#6f6a62;
  --fm-faint:#9a9490;--fm-accent:#bf7551;--fm-card-bg:#fff;
  border:1px solid var(--fm-border);border-radius:14px;background:var(--fm-bg);
  color:var(--fm-text);overflow:hidden;font-family:inherit;}
.dark .fm-root{--fm-bg:#1b1a18;--fm-surface2:rgba(255,255,255,0.025);
  --fm-border:rgba(255,255,255,0.07);--fm-text:#e7e3da;
  --fm-dim:#a8a299;--fm-faint:#6a6560;--fm-card-bg:rgba(255,255,255,0.04);}
.fm-head{padding:13px 18px 11px;display:flex;align-items:center;gap:10px;border-bottom:1px solid var(--fm-border);flex-wrap:wrap;}
.fm-head-ic{color:var(--fm-accent);flex-shrink:0;}
.fm-head-title{font-size:14px;font-weight:700;letter-spacing:0.01em;flex:1;}
.fm-head-hint{font-size:11.5px;color:var(--fm-faint);}
.fm-layers{padding:14px 16px 10px;display:flex;flex-direction:column;gap:12px;}
.fm-layer{}
.fm-layer-label{font-size:10.5px;font-weight:700;letter-spacing:0.06em;text-transform:uppercase;
  margin-bottom:7px;display:flex;align-items:center;gap:6px;}
.fm-layer-label::after{content:"";flex:1;height:1px;opacity:0.4;}
.fm-modules{display:flex;flex-wrap:wrap;gap:8px;}
.fm-module{display:flex;flex-direction:column;gap:3px;padding:9px 13px;border-radius:9px;
  border:1px solid var(--fm-border);background:var(--fm-card-bg);cursor:pointer;
  transition:border-color .15s,background .15s,box-shadow .15s;text-align:left;
  min-width:120px;max-width:220px;flex:1 1 120px;}
.fm-mod-name{font-size:13px;font-weight:600;line-height:1.3;color:var(--fm-text);}
.fm-mod-summary{font-size:11.5px;line-height:1.5;color:var(--fm-dim);}
.fm-mod-path{font-size:10.5px;font-family:ui-monospace,"Cascadia Code","Consolas",monospace;
  color:var(--fm-faint);margin-top:2px;word-break:break-all;}
.fm-arrow{display:flex;justify-content:center;padding:2px 0;}
.fm-panel{border-top:1px solid var(--fm-border);padding:14px 18px;background:var(--fm-surface2);min-height:80px;}
.fm-panel-empty{display:flex;align-items:center;justify-content:center;height:60px;
  font-size:12.5px;color:var(--fm-faint);}
.fm-panel-layer{font-size:10.5px;font-weight:700;letter-spacing:0.06em;text-transform:uppercase;
  margin-bottom:5px;}
.fm-panel-name{font-size:16px;font-weight:700;margin-bottom:6px;line-height:1.3;}
.fm-panel-path{font-size:11px;font-family:ui-monospace,"Cascadia Code","Consolas",monospace;
  color:var(--fm-faint);margin-bottom:10px;word-break:break-all;}
.fm-panel-sec{font-size:10.5px;font-weight:700;letter-spacing:0.05em;text-transform:uppercase;
  color:var(--fm-dim);margin-bottom:5px;margin-top:10px;}
.fm-panel-detail{font-size:13.5px;line-height:1.65;color:var(--fm-dim);}
.fm-rels{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px;}
.fm-rel{font-size:11.5px;padding:3px 9px;border-radius:20px;}
@media (max-width:600px){
  .fm-modules{flex-direction:column;}
  .fm-module{max-width:100%;}
  .fm-head-hint{display:none;}
}
`;
  return <div className="fm-root">
      <style>{css}</style>
      <div className="fm-head">
        <svg className="fm-head-ic" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          <rect x="2" y="3" width="20" height="5" rx="2" />
          <rect x="2" y="10" width="20" height="5" rx="2" />
          <rect x="2" y="17" width="20" height="5" rx="2" />
        </svg>
        {title && <span className="fm-head-title">{title}</span>}
        <span className="fm-head-hint">{t.hint}</span>
      </div>

      <div className="fm-layers">
        {safe.map((layer, li) => {
    const c = getColor(layer, li);
    return <div className="fm-layer" key={layer.id || li}>
              <div className="fm-layer-label" style={{
      color: c.label
    }}>
                <span>{layer.label}</span>
                <span style={{
      flex: 1,
      height: "1px",
      background: c.border,
      display: "block"
    }} />
              </div>
              <div className="fm-modules">
                {(layer.modules || []).map(mod => {
      const isActive = selected === mod.id;
      return <button key={mod.id} type="button" className="fm-module" style={isActive ? {
        borderColor: c.base,
        background: c.bg,
        boxShadow: "0 0 0 3px " + c.base + "22"
      } : {}} onMouseEnter={e => {
        if (!isActive) {
          e.currentTarget.style.borderColor = c.base;
          e.currentTarget.style.background = c.bg;
        }
      }} onMouseLeave={e => {
        if (!isActive) {
          e.currentTarget.style.borderColor = "";
          e.currentTarget.style.background = "";
        }
      }} onClick={() => setSelected(selected === mod.id ? null : mod.id)}>
                      <div className="fm-mod-name" style={isActive ? {
        color: c.label
      } : {}}>{mod.name}</div>
                      {mod.summary && <div className="fm-mod-summary">{mod.summary}</div>}
                      {mod.path && <div className="fm-mod-path">{mod.path}</div>}
                    </button>;
    })}
              </div>
              {li < safe.length - 1 && <div className="fm-arrow">
                  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={getColor(safe[li + 1] || layer, li + 1).base} strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" style={{
      opacity: 0.5
    }}>
                    <path d="M12 5v14M5 15l7 7 7-7" />
                  </svg>
                </div>}
            </div>;
  })}
      </div>

      <div className="fm-panel">
        {sel ? <div>
            <div className="fm-panel-layer" style={{
    color: sel.color.label
  }}>{t.layer}: {sel.layerLabel}</div>
            <div className="fm-panel-name">{sel.module.name}</div>
            {sel.module.path && <div className="fm-panel-path">{sel.module.path}</div>}
            {sel.module.detail && <div>
                <div className="fm-panel-sec">{t.responsibilities}</div>
                <div className="fm-panel-detail">{sel.module.detail}</div>
              </div>}
            {sel.module.relations && sel.module.relations.length > 0 && <div>
                <div className="fm-panel-sec">{t.relations}</div>
                <div className="fm-rels">
                  {sel.module.relations.map((r, i) => <span className="fm-rel" key={i} style={{
    background: sel.color.bg,
    color: sel.color.label,
    border: "1px solid " + sel.color.border
  }}>{r.to}{r.label ? " — " + r.label : ""}</span>)}
                </div>
              </div>}
          </div> : <div className="fm-panel-empty">{t.noSelect}</div>}
      </div>
    </div>;
};

export const OptionPicker = ({options = [], lang = "zh", label}) => {
  const t = lang === "en" ? {
    pick: label || "Pick an option to compare",
    rec: "Recommended"
  } : {
    pick: label || "點選項目比較",
    rec: "推薦"
  };
  const opts = Array.isArray(options) ? options : [];
  const [sel, setSel] = useState(0);
  if (opts.length === 0) return null;
  const idx = Math.min(sel, opts.length - 1);
  const cur = opts[idx];
  const css = `
  .op-root{--op-bg:#FAF8F3;--op-surface:rgba(0,0,0,0.025);--op-border:rgba(0,0,0,0.09);--op-text:#2b2722;--op-dim:#6f6a62;--op-faint:#8a8378;--op-accent:#bf7551;border:1px solid var(--op-border);border-radius:14px;background:var(--op-bg);color:var(--op-text);overflow:hidden;}
  .dark .op-root{--op-bg:#1b1a18;--op-surface:rgba(255,255,255,0.03);--op-border:rgba(255,255,255,0.08);--op-text:#e7e3da;--op-dim:#a8a299;--op-faint:#8a8378;--op-accent:#cf8a68;}
  .op-head{padding:12px 16px 11px;border-bottom:1px solid var(--op-border);font-size:12.5px;color:var(--op-dim);display:flex;align-items:center;gap:8px;}
  .op-head-ic{color:var(--op-accent);flex-shrink:0;}
  .op-tabs{display:flex;gap:8px;padding:14px 16px 4px;flex-wrap:wrap;}
  .op-tab{position:relative;flex:1 1 130px;min-width:120px;text-align:left;background:transparent;border:1px solid var(--op-border);border-radius:11px;padding:11px 13px;cursor:pointer;color:inherit;font:inherit;transition:border-color .15s,background .15s,box-shadow .15s;}
  .op-tab:hover{background:var(--op-surface);}
  .op-tab-on{border-color:rgba(191,117,81,.5);background:rgba(191,117,81,.07);box-shadow:0 0 0 3px rgba(191,117,81,.1);}
  .op-tab-name{font-size:14.5px;font-weight:600;line-height:1.3;}
  .op-tab-on .op-tab-name{color:var(--op-accent);}
  .op-badge{display:inline-block;margin-top:6px;font-size:10.5px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;padding:2px 7px;border-radius:20px;background:rgba(191,117,81,.14);color:var(--op-accent);}
  .op-rec{position:absolute;top:10px;right:11px;font-size:10px;font-weight:700;letter-spacing:.3px;text-transform:uppercase;color:var(--op-accent);}
  .op-body{padding:6px 16px 16px;}
  .op-specs{border:1px solid var(--op-border);border-radius:10px;overflow:hidden;margin-bottom:11px;}
  .op-row{display:flex;border-top:1px solid var(--op-border);font-size:13px;}
  .op-row:first-child{border-top:none;}
  .op-k{width:42%;flex-shrink:0;padding:8px 12px;color:var(--op-dim);background:var(--op-surface);}
  .op-v{flex:1 1 0;min-width:0;padding:8px 12px;font-weight:500;}
  .op-note{font-size:13px;line-height:1.6;color:var(--op-dim);padding:0 2px;}
  `;
  return <div className="op-root">
      <style>{css}</style>
      <div className="op-head"><svg className="op-head-ic" xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z" /><path d="m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65" /><path d="m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65" /></svg>{t.pick}</div>
      <div className="op-tabs">
        {opts.map((o, i) => <button key={i} type="button" className={"op-tab" + (i === idx ? " op-tab-on" : "")} onClick={() => setSel(i)}>
            {o.recommend && <span className="op-rec">★ {t.rec}</span>}
            <div className="op-tab-name">{o.name}</div>
            {o.badge && <span className="op-badge">{o.badge}</span>}
          </button>)}
      </div>
      <div className="op-body">
        <div className="op-specs">
          {(cur.specs || []).map((row, i) => <div className="op-row" key={i}>
              <div className="op-k">{row[0]}</div>
              <div className="op-v">{row[1]}</div>
            </div>)}
        </div>
        {cur.note && <div className="op-note">{cur.note}</div>}
      </div>
    </div>;
};

export const LearnerPrimer = ({items = [], lang = "zh"}) => {
  const t = lang === "en" ? {
    title: "Before this unit, be honest with yourself",
    sub: "If you can't answer these, that gap is exactly what this unit closes."
  } : {
    title: "讀這個單元前，先誠實面對",
    sub: "這幾題答不出來，正是這個單元要替你補的洞。"
  };
  const css = `
  .lp-root{--lp-bg:#FAF7F1;--lp-surface:rgba(191,117,81,0.05);--lp-border:rgba(0,0,0,0.09);--lp-edge:rgba(191,117,81,0.42);--lp-text:#2b2722;--lp-dim:#6f6a62;--lp-accent:#bf7551;border:1px solid var(--lp-border);border-left:3px solid var(--lp-edge);border-radius:13px;background:var(--lp-bg);color:var(--lp-text);overflow:hidden;margin:1.25rem 0;}
  .dark .lp-root{--lp-bg:#1b1a18;--lp-surface:rgba(207,138,104,0.07);--lp-border:rgba(255,255,255,0.08);--lp-edge:rgba(207,138,104,0.5);--lp-text:#e7e3da;--lp-dim:#a8a299;--lp-accent:#cf8a68;}
  .lp-head{display:flex;align-items:center;gap:9px;padding:13px 18px 11px;border-bottom:1px solid var(--lp-border);background:var(--lp-surface);}
  .lp-ic{color:var(--lp-accent);flex-shrink:0;}
  .lp-htx{display:flex;flex-direction:column;gap:1px;min-width:0;}
  .lp-title{font-size:14px;font-weight:650;line-height:1.3;letter-spacing:.01em;}
  .lp-sub{font-size:12px;color:var(--lp-dim);line-height:1.4;}
  .lp-list{list-style:none;margin:0;padding:10px 18px 14px;display:flex;flex-direction:column;gap:0;}
  .lp-item{display:flex;align-items:baseline;gap:11px;padding:7px 0;font-size:14px;line-height:1.6;border-top:1px solid var(--lp-border);}
  .lp-item:first-child{border-top:none;}
  .lp-mark{flex-shrink:0;color:var(--lp-accent);font-size:13px;font-weight:700;line-height:1.55;font-variant-numeric:tabular-nums;opacity:.85;}
  .lp-q{flex:1 1 0;min-width:0;color:var(--lp-text);}
  @media (max-width:620px){.lp-head{padding:12px 14px 10px;}.lp-list{padding:8px 14px 12px;}}
  `;
  return <div className="lp-root">
      <style>{css}</style>
      <div className="lp-head">
        <svg className="lp-ic" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10" /><circle cx="12" cy="12" r="6" /><circle cx="12" cy="12" r="2" /></svg>
        <span className="lp-htx">
          <span className="lp-title">{t.title}</span>
          <span className="lp-sub">{t.sub}</span>
        </span>
      </div>
      <ul className="lp-list">
        {items.map((q, i) => <li className="lp-item" key={i}>
            <span className="lp-mark">{String(i + 1).padStart(2, "0")}</span>
            <span className="lp-q">{q}</span>
          </li>)}
      </ul>
    </div>;
};

<LearnerPrimer
  lang="en"
  items={[
"All three frameworks share one design: make personality explicit as version-controlled md files.",
"NemoClaw is a hardened shell -- without an inner agent running, it has no purpose.",
"An md file not in version control is no different from a system prompt string.",
"Copying someone else's SOUL.md imports constraints you don't need.",
"Personal experiments: pick OpenClaw or Hermes. Enterprise always-on: add NemoClaw.",
"Can you see what your agent learned in a PR diff? If not, that's technical debt.",
"Enterprise policy and agent logic belong in separate, independently versioned layers.",
]}
/>

<Info>
  **What this unit solves**

  Three projects ask the same question: "Can I see and version-control what this agent has learned?" But they approach it differently. OpenClaw is a TypeScript personal AI assistant framework that writes every Skill as `skills/<name>/SKILL.md`, making the agent harness readable, version-controlled, and auditable. Hermes-Agent is a self-improving agent built in Python by Nous Research that stores cumulative procedural knowledge in a `skills/` directory and uses `prompt_builder`'s three-layer system prompt assembly (stable, context, volatile) to inject personality, instructions, and memory in a disciplined way. NemoClaw is NVIDIA's reference stack open-sourced in 2026-03 that wraps OpenClaw or Hermes inside an OpenShell sandbox, providing YAML blueprints, network policies, SSRF validation, managed inference, and other hardening layers -- turning a personal agent into a service acceptable to enterprise environments. This unit compares the differences, capabilities, and characteristics of all three, and covers what you should learn from them, what questions to ask yourself, and where things are heading. For a deep dive into NemoClaw, see [05-3](/en/code-agent/case-studies/nemoclaw).
</Info>

## Learning objectives

* [ ] Use a single comparison table to articulate the key differences among the three in positioning, core language, Skill/harness design, memory mechanisms, and enterprise readiness
* [ ] Explain the shared design orientation of all three: making an agent's "planning and personality" explicit as human-readable, version-controlled `.md` files
* [ ] Concretely state what can be learned from each framework and which self-directed questions to ask when putting them into practice
* [ ] Assess the trend toward agent shell standardization and locate where you currently stand
* [ ] Explain the role difference between NemoClaw and OpenClaw / Hermes: agent body vs. hardened shell

***

## 1. Comparison tables: positioning, technology, Skill design, memory, and community

### 1.1 One-sentence positioning for each route

| Project      | One-sentence positioning                                                            | Role                        |
| ------------ | ----------------------------------------------------------------------------------- | --------------------------- |
| OpenClaw     | "A personal daemon that acts for you across 20+ communication channels"             | Agent body (personal)       |
| Hermes-Agent | "A self-improving agent that reassembles its own personality every morning"         | Agent body (personal)       |
| NemoClaw     | "A hardened shell that puts either of the above agents inside an OpenShell sandbox" | Hardened shell (enterprise) |

OpenClaw and Hermes-Agent solve "how the agent does things"; NemoClaw solves "how enterprises can accept an always-on agent." These three are not competing -- they are additive: NemoClaw wraps OpenClaw or Hermes and provides the hardening layer.

### 1.2 Full-dimension comparison

| Dimension             | OpenClaw ([05-1](/en/code-agent/case-studies/openclaw)) | Hermes-Agent ([05-2](/en/code-agent/case-studies/hermes-agent)) | NemoClaw ([05-3](/en/code-agent/case-studies/nemoclaw)) |
| --------------------- | ------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------- |
| Role                  | Agent body (personal)                                   | Agent body (personal)                                           | Hardened shell (enterprise)                             |
| Core language         | TypeScript (Node.js)                                    | Python (`uv` managed)                                           | TypeScript + YAML + Bash                                |
| License               | MIT                                                     | MIT                                                             | Apache 2.0                                              |
| Inference backend     | Multiple providers (Anthropic, OpenAI, etc.)            | Any OpenAI-compatible API                                       | Managed inference + `model-specific-setup` registry     |
| Sandbox               | Optional (`agents.defaults.sandbox`)                    | 6 terminal backend options                                      | Mandatory (OpenShell)                                   |
| Network policy        | Tool level                                              | Tool level                                                      | Blueprint + policy engine                               |
| Skill storage         | `skills/<name>/SKILL.md`                                | `skills/<name>/SKILL.md`                                        | `.agents/skills/` (three-tier audience)                 |
| Skill loading         | Full load                                               | Progressive disclosure (Level 0 / Level 1)                      | Decision tree via `nemoclaw-skills-guide` skill         |
| Memory refinement     | `MEMORY.md`                                             | `MEMORY.md` (frozen snapshot)                                   | Inherited from inner agent                              |
| Detailed log          | `memory/YYYY-MM-DD.md`                                  | SQLite + FTS5                                                   | Inherited from inner agent                              |
| Heartbeat             | `HEARTBEAT.md` + Gateway scheduler                      | Official documentation does not explicitly state                | Inner agent + blueprint control                         |
| Personality file      | `SOUL.md` + `IDENTITY.md`                               | `SOUL.md`                                                       | Inherited from inner agent                              |
| User file             | `USER.md`                                               | `USER.md` (volatile)                                            | Inherited from inner agent                              |
| Tool conventions      | `TOOLS.md`                                              | Merged into `AGENTS.md`                                         | Blueprint declaration                                   |
| Multi-channel routing | 20+ platforms                                           | Telegram, Discord, etc. (adapter pattern)                       | Inherited via OpenClaw inner agent                      |
| Sub-agent delegation  | Via cron / ACP                                          | `delegate_task` (default 3 concurrent)                          | Inherited from inner agent                              |
| Enterprise ready      | No (local-first personal)                               | No (local-first personal)                                       | Yes (policy-as-code + vulnerability disclosure)         |
| Policy expression     | md files                                                | md files                                                        | YAML blueprint + policies/                              |
| Upstream upgrade      | Self-hosted                                             | Self-hosted                                                     | Plugin rather than fork; no rebase needed               |

<FrameworkMap
  lang="en"
  title="OpenClaw Architecture Layers (compact)"
  layers={[
{
  id: "entry",
  color: "blue",
  label: "Entry layer",
  modules: [
    { id: "gateway", name: "Gateway", path: "src/gateway/", summary: "Multi-channel routing and session isolation", detail: "Routes inbound messages from 20+ channels to isolated agent instances. All events flow through the same bus.", relations: [] },
    { id: "heartbeat", name: "Heartbeat", path: "HEARTBEAT.md", summary: "Periodic turn, skipped when file is empty", detail: "Wakes the agent on a schedule without user messages. Skips the model call entirely when HEARTBEAT.md is empty.", relations: [] },
  ],
},
{
  id: "workspace",
  color: "purple",
  label: "Workspace layer",
  modules: [
    { id: "soul", name: "SOUL.md", path: "workspace/", summary: "Persona, tone, boundaries", detail: "High-priority instruction layer injected at every session start.", relations: [] },
    { id: "agents", name: "AGENTS.md", path: "workspace/", summary: "Operational policy and tool conventions", detail: "The 'what to do' instruction layer; also the root-level policy file.", relations: [] },
    { id: "memory", name: "MEMORY.md", path: "workspace/", summary: "Long-term memory distillation", detail: "Loaded at DM session start; auto-truncated when over budget.", relations: [] },
    { id: "user", name: "USER.md", path: "workspace/", summary: "Data about the user", detail: "Name, timezone, preferences; filled incrementally by the agent.", relations: [] },
  ],
},
{
  id: "execution",
  color: "green",
  label: "Execution layer",
  modules: [
    { id: "config", name: "openclaw.json", path: "~/.openclaw/", summary: "Workspace config, model, sandbox options", detail: "Controls workspace path, model selection, and sandbox mode.", relations: [] },
    { id: "skills", name: "skills/", path: "workspace/skills/", summary: "Reusable skills (plugins)", detail: "Versioned, shareable capabilities stored as SKILL.md files.", relations: [] },
  ],
},
]}
/>

<FrameworkMap
  lang="en"
  title="Hermes-Agent Architecture Layers (compact)"
  layers={[
{
  id: "stable",
  color: "teal",
  label: "stable layer",
  modules: [
    { id: "soul", name: "SOUL.md", path: "$HERMES_HOME", summary: "Persona, loaded globally regardless of CWD", detail: "Defines agent identity; highest prefix cache hit rate of the three layers.", relations: [] },
  ],
},
{
  id: "context",
  color: "blue",
  label: "context layer",
  modules: [
    { id: "agents", name: "AGENTS.md", path: "CWD walk to git root", summary: "Project instructions, changes with CWD", detail: "Also accepts .hermes.md and CLAUDE.md; re-fetched when CWD changes.", relations: [] },
  ],
},
{
  id: "volatile",
  color: "purple",
  label: "volatile layer",
  modules: [
    { id: "memory", name: "MEMORY.md", path: "~/.hermes/memories/", summary: "2,200 char limit; frozen snapshot at session start", detail: "Written by the agent via the memory tool; takes effect next session.", relations: [] },
    { id: "user", name: "USER.md", path: "~/.hermes/memories/", summary: "1,375 char limit; user preferences snapshot", detail: "Frozen alongside MEMORY.md at session start; curated not logged.", relations: [] },
  ],
},
{
  id: "infra",
  color: "amber",
  label: "Infrastructure layer",
  modules: [
    { id: "statedb", name: "state.db", path: "~/.hermes/", summary: "SQLite + FTS5 full session history", detail: "Separate from curated memory; searchable via session_search tool.", relations: [] },
    { id: "curator", name: "curator.py", path: "hermes/memory/", summary: "Agent-driven memory curation logic", detail: "Implements the memory tool; no background auto-summarization.", relations: [] },
  ],
},
]}
/>

<FrameworkMap
  lang="en"
  title="NemoClaw Architecture Layers (compact)"
  layers={[
{
  id: "hardened-shell",
  color: "rose",
  label: "Hardened shell layer",
  modules: [
    { id: "cli-core", name: "CLI core", path: "src/lib/", summary: "TypeScript: onboard, credentials, inference, policies, runner", detail: "NemoClaw control plane; exposes nemoclaw.js and nemohermes.js entry points.", relations: [] },
    { id: "blueprint", name: "blueprint.yaml", path: "nemoclaw-blueprint/", summary: "Single source of truth: sandbox, policies, inference routing", detail: "'What ops requires' -- distinct from the agent's own workspace config.", relations: [] },
  ],
},
{
  id: "sandbox",
  color: "amber",
  label: "Sandbox layer",
  modules: [
    { id: "openshell", name: "OpenShell", path: "nemoclaw/src/blueprint/", summary: "Isolated runtime; toolset and network enforced by the shell", detail: "Unit of security auditing; contains prompt injection blast radius.", relations: [] },
    { id: "ssrf", name: "SSRF validation", path: "nemoclaw/src/blueprint/", summary: "Outbound request guard enforced at harness level", detail: "Validates all agent outbound requests against the policy allowlist.", relations: [] },
  ],
},
{
  id: "agent",
  color: "green",
  label: "Agent layer",
  modules: [
    { id: "openclaw-inner", name: "OpenClaw (default)", path: "agents/openclaw/", summary: "Default inner agent; all OpenClaw capabilities preserved", detail: "Commander plugin injects shell commands without forking upstream.", relations: [] },
    { id: "hermes-inner", name: "Hermes (optional)", path: "agents/hermes/", summary: "Python agent; NEMOCLAW_AGENT=hermes to activate", detail: "Both agents share one package install; switch without reinstalling.", relations: [] },
  ],
},
]}
/>

<Tip>
  **Why NemoClaw has so many "inherited from inner agent" entries**

  NemoClaw does not build from scratch -- it puts OpenClaw or Hermes wholesale into an OpenShell sandbox. So OpenClaw's `SOUL.md` mechanism, Hermes's SQLite memory, heartbeat scheduling: all of these are "inherited" from the inner agent. NemoClaw's own strength is in the shell: blueprints, policies, inference routing, and the vulnerability disclosure process.
</Tip>

## 2. Common ground: making planning and orchestration explicit as readable, version-controlled md files

The three projects look technically divergent (TypeScript vs Python vs TypeScript+YAML), but their underlying design philosophy is highly consistent: **pulling an agent's "personality, planning, and orchestration" out of implicit strings or closed-source binaries and putting it into human-readable, diffable, version-controlled `.md` files**.

Concrete manifestations:

* All three use `SKILL.md` as the primary medium for expressing capabilities (YAML frontmatter prefix, Markdown body)
* All three isolate personality (`SOUL.md`) into its own file rather than embedding it in a system prompt string
* All three keep the user side (`USER.md`) and project side (`AGENTS.md`) in separate files
* NemoClaw goes further and makes "enterprise policy" explicit as YAML too (blueprint, policies, model-specific-setup), so the hardening layer also goes through version control and review

The engineering significance of this common ground: once the configuration layer that would normally be buried in a system prompt or in code is pulled into a repo, agent behavior becomes PR-reviewable, diffable, and transferable to the next person. **People are not fixed; config files are. Config files that are version-controlled make agent behavior reproducible across different sessions, machines, and team members**.

<Note>
  **What "how to use a new tool" looks like across the three frameworks**

  Suppose you want to give an agent a "read a PDF report and summarize it" skill:

  ```markdown theme={null}
  # SKILL.md (works for both OpenClaw and Hermes)
  ---
  name: pdf-summarize
  description: Read a PDF report and produce a 5-point summary
  ---

  ## When to use
  When the user provides a PDF file path and requests a summary.

  ## How to do it
  1. Extract text from each page with pdfplumber
  2. Count tokens with tiktoken
  3. If over 8k tokens, chunk first then summarize
  4. Output 5 bullet points

  ## What not to do
  - Do not upload PDF content to any external API
  - Do not assume the user's research domain
  ```

  This file is readable by all three frameworks, version-controllable in all three, and discussable in a PR review in all three. The difference is that NemoClaw adds a blueprint declaration stating "which internal APIs this skill can call, and which external hosts it cannot reach."
</Note>

## 3. What to learn: harness externalization, reproducibility, auditability

Five design principles worth internalizing from these three frameworks:

* **Skill as code**: Writing an agent's operational procedures as `.md` and committing them to version control -- just as writing tests as `.spec` files -- is the minimum viable practice for engineering agent behavior. `SKILL.md` is in the same category as "an agent's unit test"
* **Memory has a lifecycle**: Hermes-Agent's `curator` only archives, never deletes; pinned Skills are exempt from automatic transitions. This design prevents the agent from silently forgetting critical knowledge. OpenClaw's `MEMORY.md` + `memory/YYYY-MM-DD.md` layering follows the same lifecycle thinking
* **Tool allowlists isolate background tasks**: The evaluation agent forked by Hermes-Agent's `background_review.py` (per official documentation describing this as the background-task isolation mechanism) can only call memory and Skill management tools. NemoClaw's SSRF validation + network policies embody the same isolation philosophy: keeping "what can be acted upon" and "what is being acted upon" separately auditable
* **`.plans/` or blueprint as decision log**: Keeping feature planning documents in the repository means future readers (including agents) can see "why this was designed this way" and not just "what was implemented." NemoClaw's `nemoclaw-blueprint/blueprint.yaml` is the hardened version of this idea
* **Shell as policy**: NemoClaw moves security decisions such as "can this reach the internet?" from agent code into the shell (YAML blueprint) for enforcement, completely decoupling agent logic from security policy. This is the cleanest solution for scenarios where "agent logic upgrades frequently but enterprise policy cannot move"

<Warning>
  **Do not copy blindly**

  Someone else's `.md` reflects someone else's workflow. OpenClaw's `SOUL.md` belongs to the OpenClaw team; Hermes-Agent's `MEMORY.md` frozen-snapshot assumptions belong to Hermes-Agent. **Copying directly often imports constraints you do not need, and may even introduce security risks** (see [03-3 Security, Privacy, and Supply Chain Risks](/en/code-agent/judgment/security-privacy-supply-chain)). Understand "why it was designed this way" before deciding whether to adopt the design.
</Warning>

## 4. Questions to ask yourself: is your agent configuration scattered implicitly or made explicit in files

Translate the shared design of these three frameworks into self-directed audit questions:

* Is your current agent behavior scattered across system prompt strings, or do you have versioned `SKILL.md` files?
* Can you see "what new behavior the agent learned" in a Pull Request diff?
* Does background memory updating have an auditable boundary, or does it silently consume the main flow's context?
* If your agent configuration were handed off to another person, could they understand the entire harness in five minutes?
* When your agent upgrades its upstream, will the hardening layer or customizations be preserved as-is, or must they be rebased?
* Are your "can it reach the internet?" and "can it read this directory?" decisions at the code level or the policy level (policy-as-code)?

If you answered "no" to two or more of the first three questions, you are in a state where "agent behavior is neither reproducible nor auditable" -- which is exactly the problem OpenClaw, Hermes, and NemoClaw are built to solve.

## 5. Where things are heading: agent shell standardization, md files as personality and orchestration carriers

Several trends worth watching (as of 2026-05 / 2026-06):

* **`SKILL.md` + YAML frontmatter is becoming the de facto format**. OpenClaw, Hermes-Agent, Claude Code skills, and the agentskills.io specification are all converging on this direction (agentskills.io specification as of 2026-05; whether a formal cross-framework standardization body or RFC exists, check the agentskills.io official page). In the near term, a "minimum compatible `SKILL.md` subset across frameworks" is likely to emerge
* **Planning documents are becoming RAG inputs that agents can query**. Files in `.plans/` directories let an agent be asked "why was this designed this way" -- the simplest source of self-explanation capability for an agent
* **NemoClaw pushes the trend one step further**. It makes "enterprise policy" explicit as version-controllable YAML too (blueprint, policies, model-specific-setup), pushing the hardening layer from "every agent doing its own thing" toward "reference stack + policy-as-code." **NemoClaw's plugin-not-fork approach to upgrading upstream OpenClaw -- where the hardening layer doesn't need to be rebased on upgrade -- is likely to become the template for other personal agent frameworks entering enterprise environments**
* **Future infrastructure directions**: CI testing of agent behavior (OpenClaw already has `.github/codeql/` for boundary quality scanning), automated Skill lifecycle management (the curator pattern), policy testing (NemoClaw's preflight), and security audit units (the OpenShell sandbox boundary)

<Note>
  **These are observations, not predictions**

  "Format convergence" and "no rebase needed for the hardening layer on upgrade" are two things that can be verified today; the other trends are still evolving. Use them as a sense of direction when designing your own agent configuration, not as inviolable mandates.
</Note>

## 6. One everyday analogy

The three frameworks are like three styles of having a working assistant:

* **OpenClaw** is like a pocket procedures manual: you write every SOP into it, and it follows the manual. **The manual is yours (version-controlled); it is just the executor**
* **Hermes-Agent** is like an intern with a learning journal: every morning it reconstitutes itself from three documents (`SOUL.md` + `MEMORY.md` + `USER.md`), writes in its journal after work, and reads it tomorrow. **The journal is being written but does not take effect immediately; the discipline trades for overhead**
* **NemoClaw** is like putting either type of robot inside a reinforced glass display case: the robot itself has not changed (OpenClaw is still OpenClaw, Hermes is still Hermes), but the case determines what it can touch, what it cannot, who can see it, and who it can see. **The case's policy (YAML blueprint) is version-controlled, and the robot's personality (SOUL.md) is version-controlled too -- the two layers are managed independently**

Which one you choose depends on your scenario: SOP discipline, growth potential, or enterprise acceptability. Most people start with OpenClaw or Hermes, then add NemoClaw when they hit an enterprise or always-on requirement.

***

## Selection guide

<OptionPicker
  lang="en"
  label="Pick your scenario to see the recommended stack"
  options={[
{
  name: "Personal experimentation",
  badge: "Fastest to start",
  specs: [
    ["Recommended stack", "Bare OpenClaw or bare Hermes"],
    ["Core language", "TypeScript (OpenClaw) or Python (Hermes)"],
    ["Sandbox", "Optional, not enforced"],
    ["Memory", "MEMORY.md + log layering"],
    ["Policy expression", "md files; version control is sufficient"],
    ["Onboarding cost", "Low -- just clone and run"],
  ],
  note: "Personal assistant, side projects, quick validation of agent behavior. NemoClaw is not needed; an enterprise policy layer would be overhead.",
},
{
  name: "Multi-model experimentation",
  badge: "Highest flexibility",
  specs: [
    ["Recommended stack", "Hermes-Agent (any OpenAI-compatible API)"],
    ["Core language", "Python (uv managed)"],
    ["Sandbox", "6 terminal backend options"],
    ["Memory", "SQLite + FTS5; lifecycle managed by curator"],
    ["Skill loading", "Progressive disclosure (Level 0 / Level 1)"],
    ["Backend switching", "Change the API endpoint; no framework changes"],
  ],
  note: "Scenarios that need A/B testing across Anthropic, OpenAI, and local models. Hermes's backend-agnostic design lets you focus on Skill design rather than adapter layers.",
},
{
  name: "Enterprise always-on",
  recommend: true,
  specs: [
    ["Recommended stack", "OpenClaw or Hermes + NemoClaw shell"],
    ["Sandbox", "Mandatory (OpenShell)"],
    ["Network policy", "YAML blueprint + policy engine"],
    ["Upgrade path", "Plugin; hardening layer needs no rebase"],
    ["Security audit", "SSRF validation + vulnerability disclosure process"],
    ["Enterprise ready", "Policy-as-code; version-controlled audit trail"],
  ],
  note: "Production environments that require always-on operation, IT auditability, and clearly defined security boundaries. Agent logic (SOUL.md) and enterprise policy (blueprint) are managed in separate layers that can each upgrade independently.",
},
]}
/>

***

## Hands-on exercises

* **Compare Skills across frameworks**: Clone both OpenClaw and Hermes-Agent, locate each one's Skill directory, and compare the frontmatter structure and body style of an existing `SKILL.md`. Answer: "Can Skills from these two frameworks be ported to each other?" Experiment: put the simplest possible `SKILL.md` into OpenClaw's `skills/` and Hermes's `skills/` and check whether it gets loaded at startup.
* **Externalize your own agent configuration**: Pick three operational procedures you currently express as system prompt strings and try rewriting them as a `SKILL.md` draft (YAML frontmatter + Markdown body). Add it to version control, open a PR to review it yourself, and check whether the diff is the kind of "small, focused change" you expected.
* **Read a NemoClaw blueprint**: Clone the NemoClaw repository, read `nemoclaw-blueprint/blueprint.yaml` and one example from `nemoclaw-blueprint/policies/`, and absorb the shape of policy-as-code. Ask yourself: does your company (or lab) have an equivalent practice of "making policy explicit in files"?

## Common pitfalls

* **Thinking "I have a `.md` file" equals "I have version control"**: Writing a `SKILL.md` but not committing it to Git, or overwriting it every time without leaving a diff, is the same as not externalizing it. **An md file not in version control is no different from a system prompt string**
* **Conflating "memory (personal preferences and facts)" with "Skill (reproducible operational procedures)"**: Hermes-Agent's memory management explicitly evaluates these two categories separately and they should not be merged. Personal preferences go into `MEMORY.md` / `USER.md`; operational procedures go into `SKILL.md`
* **Misreading Hermes-Agent's self-improvement capability as "the agent will autonomously change its own behavior in unpredictable ways"**: In practice, `SOUL.md` frozen snapshots, curator-only-archives behavior, and tool allowlist isolation are all guardrails that actively constrain unexpected mutations. **Self-improvement does not equal unpredictability**
* **Thinking NemoClaw replaces OpenClaw or Hermes**: NemoClaw is a hardened shell with no `AIAgent` main loop of its own. Without OpenClaw or Hermes running inside it, NemoClaw has no purpose
* **Copying someone else's `SOUL.md` or `SKILL.md`**: See the warning in Section 3 -- someone else's configuration reflects their own workflow and constraints

## Self-check

<Check>
  **The bar for passing this unit**

  1. Without looking at the documentation, can you fill in a three-column table (OpenClaw, Hermes-Agent, your current agent) covering: Skill storage location, memory lifecycle design, and background evaluation mechanism?
  2. Can you articulate the role difference among OpenClaw, Hermes-Agent, and NemoClaw? (Hint: which are agent bodies, and which is the hardened shell?)
  3. Can you see "what new behavior the agent learned" in a Pull Request diff? If not, is the most opaque part technical debt or an intentional decision?
  4. Is your workflow "personal experimentation," "always-on daemon," or "enterprise production"? Which combination does that point to (bare OpenClaw / bare Hermes / OpenClaw + NemoClaw / Hermes + NemoClaw)?
</Check>

## Sources and further reading

Factual claims are grounded in official documentation; fast-changing items are annotated as of 2026-05.

<div className="references">
  * \[1] OpenClaw, "openclaw/openclaw," GitHub. [https://github.com/openclaw/openclaw](https://github.com/openclaw/openclaw) (as of 2026-05)

  * \[2] OpenClaw, "openclaw\.ai," Official website. [https://openclaw.ai](https://openclaw.ai) (as of 2026-05)

  * \[3] Nous Research, "NousResearch/hermes-agent," GitHub. [https://github.com/NousResearch/hermes-agent](https://github.com/NousResearch/hermes-agent) (as of 2026-05)

  * \[4] Nous Research, "Hermes-Agent Documentation," hermes-agent.nousresearch.com. [https://hermes-agent.nousresearch.com/docs/](https://hermes-agent.nousresearch.com/docs/) (as of 2026-05)

  * \[5] NVIDIA, "NVIDIA/NemoClaw," GitHub. [https://github.com/NVIDIA/NemoClaw](https://github.com/NVIDIA/NemoClaw) (as of 2026-06)

  * \[6] NVIDIA, "NemoClaw Documentation," docs.nvidia.com. [https://docs.nvidia.com/nemoclaw/latest/](https://docs.nvidia.com/nemoclaw/latest/) (as of 2026-06)

  * \[7] agentskills.io, "Open Specification," agentskills.io. [https://agentskills.io/specification](https://agentskills.io/specification) (as of 2026-05)
</div>

* Deep dives: [05-1 OpenClaw dissection](/en/code-agent/case-studies/openclaw), [05-2 Hermes-Agent dissection](/en/code-agent/case-studies/hermes-agent), [05-3 NemoClaw dissection](/en/code-agent/case-studies/nemoclaw)
* Threat model behind the security boundaries: [03-3 Security, Privacy, and Supply Chain Risks](/en/code-agent/judgment/security-privacy-supply-chain)
