Skip to content

Claude Code on Vertex AI through a gateway-minted Google access token - #2888

Open
dhaifley wants to merge 1 commit into
kagent-dev:mainfrom
dhaifley:dhaifley/claude-vertex-gateway-token
Open

dhaifley wants to merge 1 commit into
kagent-dev:mainfrom
dhaifley:dhaifley/claude-vertex-gateway-token

Conversation

@dhaifley

Copy link
Copy Markdown
Contributor

Description

Since #2868 every ModelConfig credential goes through Substrate's egress gateway as an injected header, and the Claude compiler rejects an AnthropicVertexAI ModelConfig with environment credential "KAGENT_CLAUDE_GOOGLE_CREDENTIALS_JSON" cannot use gateway header injection. A service account key needs local signing, which the gateway cannot do, so Claude Code on Vertex AI has been unusable since then.

Substrate's Kubernetes credential provider now serves a second provider name, google-access-token.kubernetes.io (kagent-dev/substrate#47), which reads the same key Secret and returns a short-lived cloud-platform access token instead of the key. This change treats Vertex AI like Bedrock's bearer token: a gateway credential the runtime never holds.

  • The shared credential compiler binds Vertex AI. modelCredentialTarget returns a target that carries the provider authority beside the header, and AnthropicVertexAI binds authorization: Bearer on the Vertex AI hostname for its location, with a URI on the Google authority. egress.CanonicalCredentials accepts that authority and still rejects any other. The Vertex hostname mapping moves from the Claude compiler to the shared translator package.
  • Claude Code sends the request unauthenticated. The Claude compiler renders CLAUDE_CODE_SKIP_VERTEX_AUTH=1 beside the project and region and no longer renders the key. The pinned Claude Code carries the switch. Verified against the binary with a capture endpoint in place of Vertex: with the flag, every request arrives with no authorization header for the gateway to complete; without it, no request leaves the process. The oauth2.googleapis.com egress goes away because the runtime no longer talks to Google's token endpoint. The compile-time checks on the key (service account type, project match, Google token URI) stay, so a misconfigured Secret is still reported against the AgentTemplate rather than at fetch time.
  • The adapter no longer materializes a credential file. KAGENT_CLAUDE_GOOGLE_CREDENTIALS_JSON and the code that wrote it to ephemeral storage are removed. CLAUDE_CODE_SKIP_VERTEX_AUTH and GOOGLE_APPLICATION_CREDENTIALS stay compiler-owned so a Harness cannot point Claude Code at a credential it does not have.

The kagent runtimes are unchanged: they still authenticate to Vertex AI themselves, so a Vertex ModelConfig with a Secret remains rejected for them as before (unsupported volume mounts). The runtime configuration JSON is unchanged, so the config contract version does not move; this controller with an older Claude image works as long as its Claude Code has the switch, which the pinned 2.1.260 does.

This needs a Substrate release whose provider serves the Google authority. The Go pin, CI's SUBSTRATE_VERSION and docs/architecture/credential-injection.md move when it ships. Against an older provider the compiled binding is refused at fetch time with this provider serves "kubernetes.io", and the model call fails; nothing is serialized into the runtime either way.

Related Issues

kagent-dev/substrate#47 adds the provider side.

Testing

cd go
go build ./... && go vet ./core/internal/egress/... ./core/internal/translator/... ./harness/claude/...
go test -skip 'TestE2E.*' ./...
golangci-lint run ./core/internal/egress/... ./core/internal/translator/... ./harness/claude/...

All 87 packages pass and lint reports 0 issues (run without the kube-api-linter plugin, which does not load on macOS and covers only api/v1alpha). go mod tidy produces no change. The Claude compiler tests now pin the compiled bindings for every provider and assert that no Vertex revision points Claude Code at a local credential file; the shared credential tests cover the Vertex target with and without an environment variable. Not run: the KinD E2E suite, which mocks the LLM upstream and has no Vertex case.

Change Type

Bug fix.

…token

Signed-off-by: David Haifley <david.haifley@solo.io>
@dhaifley
dhaifley requested a review from a team as a code owner September 21, 2026 20:35
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