Skip to content

fix: Go ADK Vertex AI client sends requests to wrong endpoint (missing rawPredict URL rewrite)#2314

Open
jon-waggoner wants to merge 2 commits into
kagent-dev:mainfrom
jon-waggoner:fix/vertex-ai-http-client-ordering
Open

fix: Go ADK Vertex AI client sends requests to wrong endpoint (missing rawPredict URL rewrite)#2314
jon-waggoner wants to merge 2 commits into
kagent-dev:mainfrom
jon-waggoner:fix/vertex-ai-http-client-ordering

Conversation

@jon-waggoner

@jon-waggoner jon-waggoner commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Fixes #2315

Summary

Fix the Go ADK Anthropic Vertex AI client to correctly route requests to the Vertex AI rawPredict endpoint instead of the direct Anthropic API path /v1/messages.

Problem

When using Anthropic models via Vertex AI, the Go ADK runtime (golang-adk image) sends requests to the wrong URL:

POST "https://us-east5-aiplatform.googleapis.com/v1/messages": 401 Unauthorized

The correct Vertex AI endpoint should be:

POST https://{region}-aiplatform.googleapis.com/v1/projects/{project}/locations/{region}/publishers/anthropic/models/{model}:rawPredict

The Python runtime works correctly because the Python Anthropic SDK properly constructs the Vertex AI URL.

Root Cause

In NewAnthropicVertexAIModelWithLogger, the SDK options were applied in the wrong order:

// BEFORE (broken): WithGoogleAuth first, then WithHTTPClient overwrites it
opts := []option.RequestOption{
    vertex.WithGoogleAuth(ctx, region, projectID),  // sets up OAuth2 client + URL rewriting
}
httpClient, _ := BuildHTTPClient(config.TransportConfig)
opts = append(opts, option.WithHTTPClient(httpClient))  // OVERWRITES the OAuth2 client!

The vertex.WithGoogleAuth function (from anthropic-sdk-go) internally does three things via WithCredentials:

  1. Sets WithBaseURL to the Vertex AI endpoint
  2. Registers middleware that rewrites /v1/messages to the rawPredict path
  3. Sets WithHTTPClient with an OAuth2-authenticated HTTP transport

When option.WithHTTPClient(httpClient) was appended after WithGoogleAuth, it replaced the OAuth2-authenticated client with a plain HTTP client (just TLS + headers + timeout). This meant:

  • No OAuth2 token was attached to requests → 401 Unauthorized
  • The Vertex AI URL rewriting middleware was ineffective

Fix

Reorder the options so WithHTTPClient is applied before vertex.WithGoogleAuth, allowing the Vertex option to take precedence:

// AFTER (fixed): WithHTTPClient first, then WithGoogleAuth overrides with OAuth2 client
var opts []option.RequestOption
httpClient, _ := BuildHTTPClient(config.TransportConfig)
opts = append(opts, option.WithHTTPClient(httpClient))           // plain client first
opts = append(opts, vertex.WithGoogleAuth(ctx, region, projectID)) // OAuth2 client overrides

This ensures the Vertex AI SDK's authenticated client, base URL, and URL-rewriting middleware all take effect.

Copilot AI review requested due to automatic review settings July 22, 2026 13:48
@github-actions github-actions Bot added the bug Something isn't working label Jul 22, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes the Go ADK Anthropic Vertex AI client setup so that requests are routed through Vertex AI’s authenticated client and request rewriting (e.g., /v1/messages:rawPredict) instead of accidentally being sent via an unauthenticated plain http.Client.

Changes:

  • Reorders option.WithHTTPClient(...) and vertex.WithGoogleAuth(...) so the Vertex option is applied last and cannot be overwritten.
  • Adds detailed inline commentary explaining the ordering/root-cause to prevent regressions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread go/adk/pkg/models/anthropic.go Outdated
Comment on lines +97 to +101
// Create HTTP client with timeout, custom headers, and TLS.
// This must be applied BEFORE vertex.WithGoogleAuth so that the Vertex
// option (which internally calls WithHTTPClient with an OAuth2-authenticated
// transport, sets the Vertex AI base URL, and registers middleware that
// rewrites /v1/messages to the rawPredict endpoint) takes precedence.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call -- the comment is over-specifying SDK internals that could drift as the anthropic-sdk-go evolves. I'll tighten both comments to focus on the ordering contract (last WithHTTPClient wins) rather than describing internal middleware behavior. Thanks for the suggestion.

@jon-waggoner
jon-waggoner force-pushed the fix/vertex-ai-http-client-ordering branch from 5321736 to 31f4afc Compare July 22, 2026 13:52
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 22, 2026
…th2 auth

The Vertex AI client option ordering was incorrect: vertex.WithGoogleAuth
was applied first, then option.WithHTTPClient was appended after it. Since
WithGoogleAuth internally calls WithHTTPClient with an OAuth2-authenticated
transport (plus setting the Vertex AI base URL and registering URL-rewriting
middleware for rawPredict), the subsequent WithHTTPClient call from
BuildHTTPClient overwrote the authenticated client with a plain one.

This caused two problems:
1. Requests were sent without OAuth2 credentials (HTTP 401)
2. The URL path remained /v1/messages instead of being rewritten to the
   correct Vertex AI rawPredict endpoint

The fix reorders the options so WithHTTPClient (TLS/headers/timeout) is
applied first, then vertex.WithGoogleAuth is applied last, allowing its
internal WithHTTPClient to take precedence with the OAuth2-authenticated
transport.

Signed-off-by: jon waggoner <jon.waggoner@gocaribou.com>
Signed-off-by: jon waggoner <jon.waggoner@gocaribou.com>
@jon-waggoner
jon-waggoner force-pushed the fix/vertex-ai-http-client-ordering branch from 6e4f633 to 547190f Compare July 24, 2026 01:46
@jon-waggoner

Copy link
Copy Markdown
Contributor Author

Note: I considered adding a unit test for the option ordering fix but decided against it. The Anthropic SDK's option.RequestOption is opaque — there's no way to inspect which WithHTTPClient "won" without actually calling GCP auth, and vertex.WithGoogleAuth requires real Application Default Credentials. The existing Go model tests (bedrock, ollama, openai) test conversion logic and response mapping, not constructor option ordering. The inline comments documenting the ordering invariant are the appropriate safeguard here.


// Must be last: last WithHTTPClient wins, so Vertex auth must come after
// any custom HTTP client.
opts = append(opts, vertex.WithGoogleAuth(ctx, region, projectID))

@mesutoezdil mesutoezdil Jul 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heads up, vertex.WithGoogleAuth builds its own http client n calls withhttpclient itself, so it wipes buildhttpclient's custom tls/headers client entirely not just the oauth part, so custom ca cert or headers on a vertex cfg would silently stop applying

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Go ADK: Vertex AI Anthropic requests fail with 401 CREDENTIALS_MISSING due to SDK option ordering

3 participants