Skip to content

Commit 67dcadf

Browse files
geekypunkclaude
andauthored
fix(agent): pin hermes-agent and hermes-webui to release tags (#68)
Follow-up to #67, which fixed the *transient* half of the agent build's fragility. This fixes the *silent* half. ## Problem Both install paths tracked **moving branches**: | path | before | behaviour | |---|---|---| | `agent/Dockerfile` | `AGENT_RUNTIME_REF=main`, `AGENT_API_REF=master` | whatever the branch points at today | | `scripts/self-host/setup-agent.sh` | `git clone --depth 1 "$repo"` — **no ref at all** | default-branch HEAD | An upstream commit can therefore change what the agent image contains, and break it, **with no change on our side**. That is precisely the failure mode the `mcp>=1.0,<2` pin four lines below in the same file exists to prevent — left wide open one layer up. `CLAUDE.md` already states the rule (*"PINNED for reproducibility ... Bump deliberately and re-validate"*); this repo just wasn't following it. ## Change Pinned to the current release pair: ``` hermes-agent v2026.8.18 -> e624e9f hermes-webui v0.52.76 -> 3c9304a ``` **This is a behaviour change, not a no-op.** Both branches had already moved past their latest tag — `main` was at `1f234a1`, `master` at `63a562f` — so this rolls the runtime back from branch HEAD to the tagged release. Reviewers should weigh that deliberately rather than read "pinning" as cosmetic. **Both files change together on purpose.** Pinning only the Dockerfile would leave host installs on branch HEAD and container installs on a tag, so a bug would reproduce on one path and not the other. The Dockerfile comment already asserted the two tracked each other — that assertion was false, and this makes it true. `ensure_clone` still returns early when a checkout already exists, so an install predating this keeps its current ref. Silently deleting a user's agent directory to change a version isn't this script's call — but the message now says the ref was left alone instead of implying it was applied. ## Verification - [x] Both tags clone at the **exact expected SHAs**, with `pyproject.toml` and `requirements.txt` present - [x] `setup-agent.sh` passes `bash -n` - [ ] CI `docker compose build` green — proves the pinned refs *build* - [ ] **Agent smoke test — not covered by CI, and required before merge** That last box is the important one. Per `CLAUDE.md`'s own anti-patterns, *"a dashboard that is HTML and long proves nothing"* and presence ≠ compatibility: a green `docker compose build` proves these refs compile and install, **not** that the agent answers. Since this moves the runtime to a different commit than what's been running, someone should confirm the Agent tab returns a real answer (not "I'm blocked") against a pinned image before this lands. I can't run that from here. ## Ordering note Independent of #67 — different lines of `agent/Dockerfile`, no conflict expected — but #67 should land first so the retry protects these clones too. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 1fbaaf1 commit 67dcadf

2 files changed

Lines changed: 31 additions & 10 deletions

File tree

agent/Dockerfile

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,20 @@ RUN curl -fsSL https://astral.sh/uv/install.sh | sh \
3737

3838
WORKDIR /opt/deepsql-agent
3939

40-
# Upstream runtime clones. Refs are overridable at build time; defaults track
41-
# what scripts/self-host/setup-agent.sh installs for host-based installs.
40+
# Upstream runtime clones, PINNED to release tags. Overridable at build time;
41+
# defaults track what scripts/self-host/setup-agent.sh installs, so a container
42+
# install and a host install get the identical runtime pair.
43+
#
44+
# These were `main` and `master` — moving branches. That meant an upstream commit
45+
# could change what this image contains, and break it, with no change on our side:
46+
# exactly the failure the `mcp>=1.0,<2` pin below exists to prevent, left open one
47+
# layer up. The webui couples to the agent by direct import, so the two move
48+
# together — bump them as a PAIR and re-validate the agent actually answers, not
49+
# merely that the image builds.
4250
ARG AGENT_RUNTIME_REPO=https://github.com/NousResearch/hermes-agent.git
43-
ARG AGENT_RUNTIME_REF=main
51+
ARG AGENT_RUNTIME_REF=v2026.8.18
4452
ARG AGENT_API_REPO=https://github.com/nesquena/hermes-webui.git
45-
ARG AGENT_API_REF=master
53+
ARG AGENT_API_REF=v0.52.76
4654

4755
# Runtime engine (Python agent)
4856
RUN git clone --depth 1 --branch "${AGENT_RUNTIME_REF}" "${AGENT_RUNTIME_REPO}" runtime \

scripts/self-host/setup-agent.sh

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ AGENT_DIR="${HERMES_AGENT_DIR:-$HERMES_HOME/hermes-agent}"
2828
WEBUI_DIR="${HERMES_WEBUI_DIR:-$HERMES_HOME/hermes-webui}"
2929
AGENT_REPO="${HERMES_AGENT_REPO:-https://github.com/NousResearch/hermes-agent.git}"
3030
WEBUI_REPO="${HERMES_WEBUI_REPO:-https://github.com/nesquena/hermes-webui.git}"
31+
# Pinned to the same release tags as agent/Dockerfile. A host install and a
32+
# container install must yield the same runtime pair, or a bug reproduces on one
33+
# path and not the other. Bump both files together.
34+
AGENT_REF="${HERMES_AGENT_REF:-v2026.8.18}"
35+
WEBUI_REF="${HERMES_WEBUI_REF:-v0.52.76}"
3136
WEBUI_PORT="${HERMES_WEBUI_PORT:-8787}"
3237
# Default to loopback so a bare self-host install does not expose the Agent API
3338
# on the WAN (nginx /agent-api already gates via auth_request). Override to
@@ -57,14 +62,22 @@ resolve_venv_python() {
5762
}
5863

5964
ensure_clone() {
60-
local dir="$1" repo="$2" label="$3"
65+
local dir="$1" repo="$2" label="$3" ref="$4"
6166
if [[ -d "$dir/.git" ]]; then
62-
echo "$label already present at $dir"
67+
# Note: an install that predates pinning keeps whatever ref it already has.
68+
# Re-pinning an existing checkout is deliberately not automatic — deleting a
69+
# user's agent directory to change a version is not this script's call.
70+
echo "$label already present at $dir (ref unchanged; delete the directory to re-pin)"
6371
return 0
6472
fi
65-
echo "→ Cloning $label into $dir"
73+
echo "→ Cloning $label at $ref into $dir"
6674
mkdir -p "$(dirname "$dir")"
67-
git clone --depth 1 "$repo" "$dir"
75+
if ! git clone --depth 1 --branch "$ref" "$repo" "$dir"; then
76+
echo "Error: could not clone $label at pinned ref '$ref' from $repo." >&2
77+
echo " If that tag was removed upstream, pick a current one and update" >&2
78+
echo " BOTH this script and agent/Dockerfile — they must stay in step." >&2
79+
return 1
80+
fi
6881
}
6982

7083
ensure_agent_venv() {
@@ -412,8 +425,8 @@ require_command node
412425
require_command python3
413426

414427
mkdir -p "$HERMES_HOME"
415-
ensure_clone "$AGENT_DIR" "$AGENT_REPO" "hermes-agent"
416-
ensure_clone "$WEBUI_DIR" "$WEBUI_REPO" "hermes-webui"
428+
ensure_clone "$AGENT_DIR" "$AGENT_REPO" "hermes-agent" "$AGENT_REF"
429+
ensure_clone "$WEBUI_DIR" "$WEBUI_REPO" "hermes-webui" "$WEBUI_REF"
417430
ensure_agent_venv
418431
ensure_mcp_sdk
419432

0 commit comments

Comments
 (0)