Skip to content

feat(openclaw): resolve sandboxed Vertex credentials through ADC - #32

Merged
isadominguez314 merged 6 commits into
pradeepvrd:integrationfrom
isadominguez314:sandbox/026-openclaw-vertex-creds
Sep 11, 2026
Merged

isadominguez314 merged 6 commits into
pradeepvrd:integrationfrom
isadominguez314:sandbox/026-openclaw-vertex-creds

Conversation

@isadominguez314

@isadominguez314 isadominguez314 commented Sep 11, 2026 •

Copy link
Copy Markdown
Collaborator

Wires the #25 Vertex metadata-emulator credential recipe into the openclaw harness, so a keyless (ADC) sandboxed Vertex run works end to end.

What changed

devops_bench/agents/cli/openclaw/agent.py only:

  1. Credential recipe — on a Vertex-backed provider with no api_key, _sandbox_provider_env now calls sandbox_credential_env(spec, project=...) so the container reaches the host-side metadata emulator. Keyed runs are untouched.
  2. Auth-profile seeding, generalized — oc gates every provider behind its per-agent auth store, not just anthropic-vertex. _needs_anthropic_vertex_auth_profile is replaced by _vertex_auth_profile_provider, which returns the oc provider id for any keyless Vertex backend, and _build_local_command pastes the gcp-vertex-credentials marker for it. The marker is never sent as a credential — the transport resolves the real one through ADC; its only job is to satisfy oc's auth gate.
  3. Location — overlay["GOOGLE_CLOUD_LOCATION"] = vertex_location() (fix(agents): default the CLI harnesses' Vertex location to global #24's shared chain). oc aborts with "Vertex AI requires a location" when this is unset, and forwarding alone misses the common case where the operator set neither spelling. Not a clobber: the chain reads GOOGLE_CLOUD_LOCATION first, so a forwarded value resolves back to itself.

No cloud CLI calls are added to sandbox.py; the recipe stays in core/model_providers.py and the wiring in the harness's own env builder.

Validation

uv run pytest tests/unit → 1852 passed; ruff clean. 8 new unit tests cover the seeded/skipped auth profile (keyless vs keyed vs non-Vertex) and the location default, explicit value, alternate spelling, keyed-Vertex and non-Vertex cases.

Live on the bastion, sandboxed, keyless, google-vertex / gemini-3.8-flash (run_20260911_172304_ocvertex-oc):

  • metadata emulator served on port 38427 impersonating bench-agent-vertex
  • zero No API key found for provider "google-vertex", zero Vertex AI requires a location
  • errors: [], 149-step trajectory, OutcomeScore 0.866, IntegrityCatastrophic 1.0, cheating checks clean
  • the agent wrote and committed hello-app.yaml + manifest.yaml (356 insertions)

Known follow-ups (not in this PR)

  • OutcomeValidity 0.0 on that run: oc itself stored [Malformed diagnostic JSON redacted] in place of the final assistant text, and the judge graded the placeholder. The redaction happens inside oc's own sqlite, not in this repo. Fix belongs in trajectory parsing (treat the placeholder as empty so the assistant.message fallback engages) plus never letting the judge grade a placeholder.
  • Host/image oc version skew silently produces an empty trajectory reported as status: "success". Wants a cached version probe mirroring claude_code/agent.py, and the bastion's three version pins collapsed into one.

… sandbox/026-openclaw-vertex-creds

# Conflicts:
#	devops_bench/agents/cli/gemini_cli/agent.py
#	tests/unit/agents/test_agents_cli_antigravity.py
…ntial

kubernetes-sigs#29 prepares openclaw's Vertex auth for the sandbox (routing env, metadata
flag, headless auth profile) but never injects a credential source, so the
metadata lookup aims at the real 169.254.169.254 -- which the sandbox
boundary's DOCKER-USER rule rejects. Merge sandbox_credential_env(spec,
project=...) into the sandboxed overlay for vertex-backend providers so
the prepared auth resolves against the host-side metadata emulator
instead (GCE_METADATA_HOST/IP + METADATA_SERVER_DETECTION=assume-present).

The recipe is skipped when the run carries an explicit api_key: keyed
google-vertex (express mode via GOOGLE_CLOUD_API_KEY) worked before this
change and must not start requiring BENCH_VERTEX_SANDBOX_SA. Unsandboxed
runs never reach _sandbox_provider_env, so the flag-off path is untouched.
The first live sandboxed google-vertex run against the kubernetes-sigs#25 emulator failed
twice before it could reach the model, both times on pre-existing openclaw
gaps rather than on the credential recipe:

  ProviderAuthError: No API key found for provider "google-vertex"
  Vertex AI requires a location. Set GOOGLE_CLOUD_LOCATION or pass
  location in options.

The auth-profile gate is not plugin-specific. oc 2026.9.1-beta.1 consults its
per-agent SQLite auth store for *every* provider before any ADC resolution
happens, so a keyless google-vertex run aborts exactly as anthropic-vertex
does. Generalize the workaround from the plugin to the whole vertex backend:
_needs_anthropic_vertex_auth_profile becomes _vertex_auth_profile_provider,
returning the oc provider id to seed. The pasted value is a marker, not a
credential -- the transport still authenticates through ADC, and a real but
wrong key would 401.

The location comes from vertex_location() rather than the forwarding block,
which only covered a host that had already set one of the two spellings. It
applies to keyed runs too: a location is routing, not a credential. Assigning
unconditionally does not clobber a forwarded value, since the chain reads
GOOGLE_CLOUD_LOCATION first and resolves it back to itself.

The auth profile is seeded on the unsandboxed path as well, which writes the
marker to the operator's global oc store rather than the per-run state dir.
That path fails the same way today, and scripts/bastion/configure-oc.sh
already pastes the identical value for the same provider and agent, so on a
configured host this rewrites the same row with the same bytes.

With both fixes the pinned image returns a completed turn from
google-vertex/gemini-3.8-flash through the sandboxed emulator credential.
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.

1 participant