Skip to content

Commit 42421b4

Browse files
authored
Skip Hermes onboarding for managed agents (#46)
1 parent beba33e commit 42421b4

4 files changed

Lines changed: 79 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ versions are optional; date-stamped sections are fine for in-flight work.
99

1010
## 2026-07-22
1111

12+
### Managed Hermes first-message behavior
13+
14+
PerkOS-managed Hermes agents now skip the upstream first-contact introduction
15+
and profile-building offer by default. A user's first channel message is
16+
answered directly, so requests such as “give me a short description” are not
17+
expanded with `/help` instructions or an unrelated profile prompt. The behavior
18+
is isolated behind `PERKOS_DISABLE_FIRST_MESSAGE_ONBOARDING=true` and can be
19+
overridden for self-hosted deployments. The image build applies a narrow,
20+
fail-fast runtime patch and stops if its upstream anchor changes.
21+
1222
### OpenClaw container healthcheck port alignment
1323

1424
The OpenClaw image now exposes and probes port `3000`, matching the rendered

images/hermes/Dockerfile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,17 @@ RUN apt-get update && \
4444
rm -rf /var/lib/apt/lists/*
4545

4646
COPY config/hermes.template.yaml /opt/perkos/hermes.template.yaml
47+
COPY patch-managed-runtime.py /opt/perkos/patch-managed-runtime.py
4748
COPY docker-entrypoint.sh /usr/local/bin/perkos-entrypoint.sh
4849
COPY snapshot.sh /usr/local/bin/perkos-snapshot.sh
4950
COPY restore.sh /usr/local/bin/perkos-restore.sh
5051
COPY perkos-render-profiles.py /usr/local/bin/perkos-render-profiles.py
5152
RUN chmod 755 /usr/local/bin/perkos-entrypoint.sh \
5253
/usr/local/bin/perkos-snapshot.sh \
5354
/usr/local/bin/perkos-restore.sh \
54-
/usr/local/bin/perkos-render-profiles.py
55+
/usr/local/bin/perkos-render-profiles.py && \
56+
python3 /opt/perkos/patch-managed-runtime.py && \
57+
python3 -m py_compile /opt/hermes/gateway/run.py
5558

5659
# PerkOS Assistant content — SOUL (persona) + runbook (FAQ knowledge).
5760
# Used only when the container is provisioned as the platform identity
@@ -101,7 +104,8 @@ ENV PATH="/opt/hermes/.venv/bin:${PATH}"
101104

102105
# Defaults — overridable at runtime via -e.
103106
ENV PERKOS_LLM_BASE_URL=https://api.llm.perkos.xyz/v1 \
104-
PERKOS_LLM_DEFAULT_MODEL=kimi-k2.6:cloud
107+
PERKOS_LLM_DEFAULT_MODEL=kimi-k2.6:cloud \
108+
PERKOS_DISABLE_FIRST_MESSAGE_ONBOARDING=true
105109

106110
# Our entrypoint runs FIRST (renders config, copies skill + platform
107111
# plugin into HERMES_HOME), then forks upstream's docker/entrypoint.sh
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env python3
2+
"""Apply narrow, fail-fast PerkOS behavior patches to upstream Hermes."""
3+
4+
from pathlib import Path
5+
6+
7+
GATEWAY_RUN = Path("/opt/hermes/gateway/run.py")
8+
FIRST_MESSAGE_GUARD = (
9+
"if not history and not await self.async_session_store.has_any_sessions():"
10+
)
11+
MANAGED_FIRST_MESSAGE_GUARD = """if (
12+
not _perkos_env_flag_disabled("PERKOS_DISABLE_FIRST_MESSAGE_ONBOARDING")
13+
and not history
14+
and not await self.async_session_store.has_any_sessions()
15+
):"""
16+
HELPER_ANCHOR = "logger = logging.getLogger(__name__)"
17+
HELPER = """
18+
19+
def _perkos_env_flag_disabled(name: str) -> bool:
20+
\"\"\"Return true when a PerkOS-managed upstream behavior is disabled.\"\"\"
21+
return os.getenv(name, \"\").strip().lower() in {\"1\", \"true\", \"yes\", \"on\"}
22+
"""
23+
24+
25+
def replace_exactly_once(source: str, needle: str, replacement: str, label: str) -> str:
26+
count = source.count(needle)
27+
if count != 1:
28+
raise RuntimeError(
29+
f"{label}: expected exactly one upstream anchor, found {count}; "
30+
"review the Hermes update before publishing this image"
31+
)
32+
return source.replace(needle, replacement, 1)
33+
34+
35+
source = GATEWAY_RUN.read_text(encoding="utf-8")
36+
source = replace_exactly_once(
37+
source,
38+
HELPER_ANCHOR,
39+
HELPER_ANCHOR + HELPER,
40+
"managed first-message helper",
41+
)
42+
source = replace_exactly_once(
43+
source,
44+
FIRST_MESSAGE_GUARD,
45+
MANAGED_FIRST_MESSAGE_GUARD,
46+
"managed first-message guard",
47+
)
48+
GATEWAY_RUN.write_text(source, encoding="utf-8")

tests/hermes/smoke.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,21 @@ else
247247
fail "config.yaml missing the PerkOS fast-response policy"
248248
fi
249249

250+
if docker exec "$CONTAINER" sh -lc \
251+
'test "$PERKOS_DISABLE_FIRST_MESSAGE_ONBOARDING" = true'; then
252+
pass "managed agents disable upstream first-message onboarding by default"
253+
else
254+
fail "managed first-message onboarding flag is not enabled"
255+
fi
256+
257+
if docker exec "$CONTAINER" grep -q \
258+
'not _perkos_env_flag_disabled("PERKOS_DISABLE_FIRST_MESSAGE_ONBOARDING")' \
259+
/opt/hermes/gateway/run.py; then
260+
pass "gateway source honors the managed first-message flag"
261+
else
262+
fail "managed first-message runtime guard is missing"
263+
fi
264+
250265
if echo "$config" | grep -A8 '^ telegram:' | grep -q "interim_assistant_messages: false"; then
251266
pass "telegram suppresses permanent interim assistant messages"
252267
else

0 commit comments

Comments
 (0)