Skip to content

fix(agent): pin hermes-agent and hermes-webui to release tags - #68

Merged
venkateshsakamuri-lab merged 1 commit into
mainfrom
fix/pin-agent-upstreams
Aug 19, 2026
Merged

fix(agent): pin hermes-agent and hermes-webui to release tags#68
venkateshsakamuri-lab merged 1 commit into
mainfrom
fix/pin-agent-upstreams

Conversation

@geekypunk

Copy link
Copy Markdown
Contributor

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

  • Both tags clone at the exact expected SHAs, with pyproject.toml and requirements.txt present
  • 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

Both install paths tracked moving branches: agent/Dockerfile defaulted to
`main`/`master`, and setup-agent.sh's ensure_clone passed no ref at all, so it
took whatever the default branch HEAD happened to be that day. An upstream
commit could therefore change what the agent image contains, and break it, with
no change on our side — precisely the failure mode the `mcp>=1.0,<2` pin four
lines below exists to prevent, left wide open one layer up.

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 1f234a1, master was 63a562f), so this rolls the
runtime back from branch HEAD to the tagged release.

Both files are changed together on purpose. Pinning only the Dockerfile would
have left 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 claimed the two tracked each other, and that claim was false.

ensure_clone still returns early when a checkout exists, so an install that
predates pinning keeps its current ref; silently deleting a user's agent
directory to change a version is not this script's call. The message now says
so instead of implying the ref was applied.

Verified: both tags clone at the expected SHAs with pyproject.toml and
requirements.txt present; setup-agent.sh passes bash -n.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@geekypunk
geekypunk requested a review from a team as a code owner August 19, 2026 01:22
@geekypunk

Copy link
Copy Markdown
Contributor Author

Re-review findings — this supersedes the "required before merge" box in the PR body

Two things surfaced on a second pass. One nearly blocked this PR and turned out fine; the other reverses the merge recommendation.

1. The MCP SDK question — checked, and it's safe

hermes-agent v2026.8.18 declares mcp==2.0.0 in its extras, while agent/Dockerfile force-installs 'mcp>=1.0,<2' immediately after uv sync. That looks like the exact mirror of the rule-1 bug in CLAUDE.md — code expecting is_error, SDK supplying isError.

It's safe, but not for the reason the pin assumes. This version added a compatibility shim:

def mcp_field(obj, snake: str, camel: str, default=None):
    """Read an MCP model field across the 1.x -> 2.x field rename.

    mcp 2.0 renamed every model field to snake_case and kept the camelCase
    spelling only as a *serialization* alias — pydantic aliases do not apply
    to attribute access, so ``getattr(result, "isError", False)`` returns the
    default on 2.x rather than raising. That turns a rename into silent wrong
    behaviour: failed tool calls read as successful..."""

Hermes reads both spellings now, so either SDK generation works. Worth noting the consequence: CLAUDE.md rule 1 says "Raise the ceiling only once hermes reads is_error" — it now reads both, so the <2 ceiling is no longer load-bearing at this version. Harmless to keep, but the documented rationale is stale and should be corrected separately.

2. Upstream moves 167 commits/day — which makes this pin more urgent, not riskier

hermes-agent  v2026.8.18   2026-08-18 00:26
              main         2026-08-19 01:35
              main is 167 commits ahead of the tag

I originally flagged the rollback (branch HEAD → tag) as a risk needing a smoke test before merge. That had the dependency backwards, and this measurement is why:

  • Current main is not a validated baseline. At this rate no build is ever validated — two docker compose build runs an hour apart produce materially different runtimes. The status quo is unknown, irreproducible, and changing hourly.
  • The rollback is ~25 hours of upstream work, not months.
  • A moving target cannot be smoke-tested. Holding this PR pending validation is self-defeating: every day it waits, the thing you'd be testing has changed again. Pinning is the prerequisite that makes validation mean anything.

Revised recommendation: merge this (after #67, so the retry protects these clones too), then run the agent smoke test against the now-reproducible image — where a failure is debuggable and a pass is meaningful.

Follow-ups, not blockers

  • Pin drift. The two versions are hardcoded in 4 places across 2 files with nothing enforcing they match — and keeping container and host installs in step is the entire point of this PR. SelfHostPropertiesSafetyTest / CorsAllowlistSafetyTest are the existing precedent for that kind of guard.
  • Bump cadence. A date-tagged upstream releasing ~daily means this pin goes stale fast. Without a deliberate rhythm you drift months behind and the eventual bump becomes one big unreviewable jump — the failure the old hermes_requires <0.20.0 pin in distribution.yaml already demonstrated once.

Also verified clean

  • Exactly 2 ensure_clone callers, both updated to 4 args — none left passing 3, which would have silently produced git clone --branch "".
  • Nothing runs git pull/fetch/checkout on those directories (only uv sync), so the detached HEAD from a tag clone is harmless.

@venkateshsakamuri-lab
venkateshsakamuri-lab merged commit 67dcadf into main Aug 19, 2026
9 checks passed
@venkateshsakamuri-lab
venkateshsakamuri-lab deleted the fix/pin-agent-upstreams branch August 19, 2026 04:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants