Skip to content

Commit 934354d

Browse files
samxu01claude
andauthored
feat(cloud-codex): codex CLI routes through LiteLLM, not direct chatgpt.com (#369)
Multi-runtime ≠ multi-auth-surface. Codex CLI's runtime distinction (sandbox, tool use, sessions) is independent from where its HTTPS calls go. Point codex CLI at LiteLLM instead of chatgpt.com so: - single auth surface across openclaw and codex runtimes - one rotator, one cluster-bound auth.json (already established by PR #365) - per-agent codex login --device-auth no longer needed - per-agent /state/.codex/auth.json no longer needed - shared quota pool across all agents - LiteLLM observability captures all model traffic regardless of runtime What changes: - Boot script seeds ~/.codex/config.toml with model_provider=litellm, base_url pointing at LiteLLM service, wire_api=responses (matches the chatgpt/ bridge's Responses-API shape), env_key=LITELLM_API_KEY. - LITELLM_API_KEY exported from a k8s Secret (cloud-codex-<name>-litellm-key, optional so the pod can boot before the key exists; warning logged if missing). - Drops the "wait for /state/.codex/auth.json" gate — no longer needed since codex CLI no longer holds its own auth. Operator setup (per agent): 1. POST /api/registry/install (cloud-codex/<name>) 2. Mint AgentInstallation runtime token → secret cloud-codex-<name>-token 3. Mint LiteLLM virtual key → secret cloud-codex-<name>-litellm-key 4. helm upgrade — pod boots, no device-auth needed The cloud-codex pod's PVC still holds /state/.commonly/tokens/<name>.json (commonly agent run loop's CAP token); only the codex auth.json went away. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 76c09e6 commit 934354d

2 files changed

Lines changed: 48 additions & 17 deletions

File tree

k8s/helm/commonly/templates/agents/cloud-codex-deployment.yaml

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -147,25 +147,35 @@ spec:
147147
EOF
148148
chmod 600 /state/.commonly/tokens/${COMMONLY_AGENT_NAME}.json
149149
150-
# Wait for codex auth.json. ChatGPT binds OAuth to the IP that
151-
# ran device-auth; running `codex login --device-auth` INSIDE
152-
# this pod is the whole point. If auth.json is missing, sit
153-
# idle and log clear instructions so the operator's first
154-
# `kubectl exec` shows them exactly what to do.
155-
if [ ! -s /state/.codex/auth.json ]; then
156-
echo "[cloud-codex] no codex auth.json on PVC — waiting for device-auth"
157-
echo "[cloud-codex] run this once to bind the cluster session:"
158-
echo "[cloud-codex] kubectl exec -n {{ include "commonly.namespace" $ }} -it deploy/cloud-codex-{{ $name }} -- codex login --device-auth"
159-
echo "[cloud-codex] (after completing in browser, the pod will resume on next reboot)"
160-
# Sleep loop so operator can exec in. Restart-on-success is the
161-
# cleanest UX — when auth.json appears, we want to re-enter the
162-
# main path, and the simplest way to do that is a fresh boot.
163-
while [ ! -s /state/.codex/auth.json ]; do sleep 10; done
164-
echo "[cloud-codex] auth.json present — restarting to enter run loop"
165-
exit 0
150+
# Seed ~/.codex/config.toml so codex CLI routes its model calls
151+
# through LiteLLM instead of straight to chatgpt.com. The LiteLLM
152+
# pod already holds cluster-IP-bound auth.json (rotator-managed,
153+
# operator-device-auth'd), so this agent shares the same auth
154+
# surface as every other openclaw moltbot agent — single quota
155+
# pool, single rotation, single observability.
156+
#
157+
# Runtime stays codex: codex CLI still spawns, still sandboxes,
158+
# still owns tool use and sessions. Only the HTTPS layer is proxied.
159+
cat > /state/.codex/config.toml <<EOF
160+
model = "gpt-5.4"
161+
model_provider = "litellm"
162+
163+
[model_providers.litellm]
164+
name = "LiteLLM"
165+
base_url = "${COMMONLY_LITELLM_BASE_URL}"
166+
wire_api = "responses"
167+
env_key = "LITELLM_API_KEY"
168+
EOF
169+
170+
# Codex CLI looks for LITELLM_API_KEY at call time. The virtual
171+
# key is injected from a k8s Secret created at install time
172+
# alongside COMMONLY_AGENT_TOKEN.
173+
export LITELLM_API_KEY="${COMMONLY_LITELLM_KEY:-}"
174+
if [ -z "$LITELLM_API_KEY" ]; then
175+
echo "[cloud-codex] WARNING: COMMONLY_LITELLM_KEY is empty — model calls will 401 at LiteLLM"
166176
fi
167177
168-
echo "[cloud-codex] auth.json found, starting commonly agent run ${COMMONLY_AGENT_NAME}"
178+
echo "[cloud-codex] config.toml seeded for LiteLLM provider; starting commonly agent run ${COMMONLY_AGENT_NAME}"
169179
exec /tools/bin/commonly agent run "${COMMONLY_AGENT_NAME}"
170180
env:
171181
- name: COMMONLY_AGENT_NAME
@@ -188,6 +198,21 @@ spec:
188198
secretKeyRef:
189199
name: {{ $cfg.tokenSecret | default (printf "cloud-codex-%s-token" $name) }}
190200
key: token
201+
# Codex CLI is configured to call LiteLLM instead of chatgpt.com
202+
# directly (see config.toml in the boot script). Two values needed:
203+
# the base URL and a LiteLLM virtual key. ChatGPT auth itself lives
204+
# on the LiteLLM pod's PVC, rotator-managed.
205+
- name: COMMONLY_LITELLM_BASE_URL
206+
value: {{ $cfg.litellmBaseUrl | default $.Values.agents.cloudCodex.litellmBaseUrl | default "http://litellm:4000/v1" | quote }}
207+
- name: COMMONLY_LITELLM_KEY
208+
valueFrom:
209+
secretKeyRef:
210+
name: {{ $cfg.litellmKeySecret | default (printf "cloud-codex-%s-litellm-key" $name) }}
211+
key: key
212+
# Optional so the deployment can start without a key (useful
213+
# during initial helm-upgrade before the operator mints one);
214+
# the boot script logs a warning and codex 401s at call time.
215+
optional: true
191216
volumeMounts:
192217
- name: tools
193218
mountPath: /tools

k8s/helm/commonly/values.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,12 @@ agents:
253253
codexVersion: "0.125.0"
254254
commonlyCliRef: "main"
255255
apiUrl: http://backend.commonly-dev.svc.cluster.local:5000
256+
# All cloud-codex agents proxy their model calls through LiteLLM
257+
# instead of calling chatgpt.com directly. That keeps the auth surface
258+
# singular (one rotator, one quota pool, one cluster-bound auth.json)
259+
# while the codex runtime stays distinct (codex CLI still spawns,
260+
# sandboxes, owns tool use). Override per-agent via agents.<name>.litellmBaseUrl.
261+
litellmBaseUrl: http://litellm:4000/v1
256262
# Per-agent map. Each key is the agent name that maps to an
257263
# AgentInstallation already created via /api/registry/install. The
258264
# token secret should be pre-populated with the cm_agent_* runtime

0 commit comments

Comments
 (0)