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
61 lines
3.3 KiB
Docker
61 lines
3.3 KiB
Docker
# Plan A6, third of three: Claude Code pointed at Kimi.
|
|
#
|
|
# Same shape as `agent-glm` — same CLI, same pinned version, a different
|
|
# endpoint — for the same reason: an independent verifier is only independent if
|
|
# it runs somewhere else, and a third provider costs an env contract rather than
|
|
# a third agent harness.
|
|
#
|
|
# WHY CLAUDE CODE AND NOT `kimi`. Moonshot ship their own CLI
|
|
# (`@moonshot-ai/kimi-code`), and it would be the more native choice — but the
|
|
# whole mission harness is Claude-Code-shaped: `--agents` JSON roles, the
|
|
# `verifier` tool allowlist, the `Stop` hook that backs the completion gate, and
|
|
# the per-subagent transcripts we count as delegation evidence. `kimi` has none
|
|
# of those flags; its equivalents are TOML files and markdown agent dirs. Running
|
|
# it would mean a second executor with its own untested failure modes, so this
|
|
# image uses the Anthropic-compatible mode instead and the harness is unchanged.
|
|
#
|
|
# THE URL IS MEASURED, and the first answer was the wrong one. `api.moonshot.ai/
|
|
# anthropic/v1/messages` exists and speaks the protocol, but it belongs to the
|
|
# platform.moonshot.ai account namespace and rejects an `sk-kimi-` key. The Kimi
|
|
# CODE service is a different host: `POST https://api.kimi.com/coding/v1/messages`
|
|
# returns a real Anthropic Messages body — `msg_` id, `content` blocks, a
|
|
# `thinking` block with a signature.
|
|
#
|
|
# So the base URL is `https://api.kimi.com/coding` and NOT `.../coding/v1`:
|
|
# Claude Code appends `/v1/messages` itself, and the doubled `/v1/v1/messages`
|
|
# is a 404 that would look like a broken image rather than a bad URL.
|
|
#
|
|
# Two more things measured rather than assumed, because each would otherwise be
|
|
# a silent failure at the first turn:
|
|
# - `Authorization: Bearer` is accepted (so ANTHROPIC_AUTH_TOKEN is the right
|
|
# injection channel; `x-api-key` works too, but that is the API-key path a
|
|
# microVM deliberately does not use).
|
|
# - a `claude-*` model id is ACCEPTED and answered, so Kimi maps it onto its
|
|
# own model exactly as z.ai does. No ANTHROPIC_MODEL override is needed.
|
|
FROM clawmates/agent-toolchain:dev
|
|
|
|
# 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 is injected per turn by
|
|
# `mission_runtime::microvm_provider_env` from the server's `KIMI_API_KEY`. A VM
|
|
# built from this image therefore cannot be handed an Anthropic subscription
|
|
# token or a z.ai key — the wrong credential has nowhere to go.
|
|
ENV HOME=/root \
|
|
CLAWMATES_AGENT_CLI=claude \
|
|
ANTHROPIC_BASE_URL=https://api.kimi.com/coding
|
|
RUN mkdir -p /root/.claude
|
|
|
|
# No ANTHROPIC_MODEL: measured above, the service maps the `claude-*` id Claude
|
|
# Code sends onto its own model (`kimi-for-coding`, K2.7 Coding, 262k context).
|