Files
clawmates/images/agent-glm/Dockerfile
T
Omar SobhandClaude Opus 5 794f2124bc
deploy / test (push) Successful in 5m18s
deploy / build (push) Successful in 5m54s
feat(microvm): Claude Code 2.1.276 rootfs pins, and a VM run that says what it ran
Every rootfs on the fleet had sat on Claude Code 2.1.223–2.1.226 since August
while the container tier moved to 2.1.276, and nothing recorded either. GLM
and Kimi exist only as microVM backends, so "have we upgraded GLM and Kimi"
is this change and the rebuild it drives.

Pins. All four agent-* images pin 2.1.276 — as separate ARGs, since Docker has
no include and each file has to stay reproducible alone — and
scripts/fc-build-rootfs.sh refuses to build if they disagree, naming the odd
one out. They had already drifted (claude 226, the rest 223) under comments
saying "same version on purpose". Between 2.1.226 and 2.1.276, 2.1.265 and
2.1.275 each broke every turn on ANTHROPIC_BASE_URL endpoints, which is how
glm and kimi reach `claude` inside a VM; the container-tier verification never
exercised that path, so the VM runs on those backends are the real test.

Provenance. `VmOutcome` carries the rootfs the node reported booting and the
guest's own `claude --version`; `launch_microvm_phase` persists both as
`checkpoint.vm` beside `records` (the two readers parse only `records`) and
names them in its log line. "Which image and CLI did this mission run on" is
a query now.

Independence. `evaluator` derived the implementer family from a constant
`"anthropic"`, true while every backend was Claude on Anthropic. With glm and
kimi rootfs it made a glm mission judged by glm:glm-5.3 read as
`independent = true` — the one claim that path exists to make honestly.
`implementer_family(missions.backend)` mirrors `microvm_credential_for`; the
subscription judge is now independent exactly when the agent did NOT run on
Anthropic.

Harness. `verify-mission-delivery.sh glm|kimi` run the microvm scenario on
each backend and add the proof the mission itself cannot give: the placed
node's journal must show the VM dialling that provider's host, never being
denied it, and dialling nothing else but the forge — a model's self-report is
measured worthless here. `assert_cli_version` reads checkpoint.vm. The stale
scratch-repo default (dead since the 09-14 wipe) is the re-synced id.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WZb5A2kfVfjpdwSochkuHz
2026-09-18 20:16:06 -05:00

53 lines
2.7 KiB
Docker

# Plan A6, second of three: Claude Code pointed at GLM.
#
# The same CLI as `agent-claude`, the same toolchain underneath, and a different
# endpoint. That is the whole difference, and it is deliberate: z.ai serves an
# Anthropic-compatible API, so a second provider costs an env contract rather
# than a second agent harness with its own failure modes.
#
# Why this image exists at all: a composed mission's `verifier` node reviewing
# work its own model wrote is a correlated failure — the same one the
# cross-provider judge exists to break, one layer down. A roster can only put a
# node on another provider if another provider's rootfs is on the fleet.
#
# Build (on the node that will run it):
#
# ssh osobh@tank "cd ~/clawmates && \
# docker build -f images/agent-glm/Dockerfile -t clawmates/agent-glm:dev images/agent-glm/"
# scripts/fc-build-rootfs.sh osobh@tank clawmates/agent-glm:dev glm 8G
FROM clawmates/agent-toolchain:dev
# Pinned to the SAME version as agent-claude on purpose. A solo run and a
# composed run's verifier node should differ by provider and by nothing else; two
# CLI versions in one graph would make "the verifier disagreed" ambiguous between
# the model and the harness.
# 2.1.276, 2026-09-18. Between 2.1.226 and here, 2.1.265 and 2.1.275 each broke
# every turn on ANTHROPIC_BASE_URL endpoints (HTTP 400) — the path the glm and
# kimi images use — and 2.1.276 is the first version after both that is fixed.
# All four agent-* images pin the SAME version; scripts/fc-build-rootfs.sh
# refuses to build if they drift. Bump them together, on purpose, and run a
# mission on each backend before promoting (see deploy/clawmates-runtime/Dockerfile
# for the same rule on the container tier).
ARG CLAUDE_CODE_VERSION=2.1.276
RUN npm install -g "@anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}" \
&& npm cache clean --force \
&& rm -rf /root/.npm \
&& claude --version
# The endpoint is baked in; the CREDENTIAL never is. `mission_runtime::
# microvm_provider_env` injects `ANTHROPIC_AUTH_TOKEN` from the server's
# `ZAI_API_KEY` at turn time, so the key lives and dies with the VM.
#
# Baking the base URL rather than injecting it is the safer half of the split: an
# image whose URL is fixed cannot be handed a token for one provider and an
# endpoint for another. That mix-up — an Anthropic subscription token sent to
# z.ai — is precisely what `microvm_credential_for` refuses to allow.
ENV HOME=/root \
CLAWMATES_AGENT_CLI=claude \
ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic
RUN mkdir -p /root/.claude
# No CLAUDE_CODE_OAUTH_TOKEN and no ANTHROPIC_API_KEY: this backend authenticates
# with a z.ai key alone. The subscription token must never reach this image —
# it would be sent, verbatim, to another company's endpoint.