Allow Claude model requests to route through Google Vertex AI (#23985)

* feat: add anthropic-vertex provider for Claude via GCP Vertex AI

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: sallyom <somalley@redhat.com>

* docs: add anthropic-vertex provider guide

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: sallyom <somalley@redhat.com>

* Agents: validate Anthropic Vertex project env

* Changelog: format update for Vertex entry

* Providers: rename Anthropic Vertex to Google Vertex Claude

* Providers: remove Vertex Claude provider path

* Models: normalize Vercel Claude shorthand refs

* Onboarding: default Vercel model to Claude shorthand

* Changelog: add @vincentkoc credit for #23985

* Onboarding: keep canonical Vercel default model ref

* Tests: expand Vercel model normalization coverage

---------

Signed-off-by: sallyom <somalley@redhat.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
Sally O'Malley
2026-02-23 11:04:31 -05:00
committed by GitHub
parent 544809b6f6
commit eb4ff6df81
4 changed files with 42 additions and 0 deletions

View File

@@ -8,6 +8,8 @@ Docs: https://docs.openclaw.ai
### Changes
- Providers/Vercel AI Gateway: accept Claude shorthand model refs (`vercel-ai-gateway/claude-*`) by normalizing to canonical Anthropic-routed model ids. (#23985) Thanks @sallyom, @markbooch, and @vincentkoc.
### Breaking
### Fixes

View File

@@ -48,3 +48,11 @@ openclaw onboard --non-interactive \
If the Gateway runs as a daemon (launchd/systemd), make sure `AI_GATEWAY_API_KEY`
is available to that process (for example, in `~/.openclaw/.env` or via
`env.shellEnv`).
## Model ID shorthand
OpenClaw accepts Vercel Claude shorthand model refs and normalizes them at
runtime:
- `vercel-ai-gateway/claude-opus-4.6` -> `vercel-ai-gateway/anthropic/claude-opus-4.6`
- `vercel-ai-gateway/opus-4.6` -> `vercel-ai-gateway/anthropic/claude-opus-4-6`

View File

@@ -97,6 +97,31 @@ describe("model-selection", () => {
});
});
it("normalizes Vercel Claude shorthand to anthropic-prefixed model ids", () => {
expect(parseModelRef("vercel-ai-gateway/claude-opus-4.6", "openai")).toEqual({
provider: "vercel-ai-gateway",
model: "anthropic/claude-opus-4.6",
});
expect(parseModelRef("vercel-ai-gateway/opus-4.6", "openai")).toEqual({
provider: "vercel-ai-gateway",
model: "anthropic/claude-opus-4-6",
});
});
it("keeps already-prefixed Vercel Anthropic models unchanged", () => {
expect(parseModelRef("vercel-ai-gateway/anthropic/claude-opus-4.6", "openai")).toEqual({
provider: "vercel-ai-gateway",
model: "anthropic/claude-opus-4.6",
});
});
it("passes through non-Claude Vercel model ids unchanged", () => {
expect(parseModelRef("vercel-ai-gateway/openai/gpt-5.2", "openai")).toEqual({
provider: "vercel-ai-gateway",
model: "openai/gpt-5.2",
});
});
it("should handle invalid slash usage", () => {
expect(parseModelRef("/", "anthropic")).toBeNull();
expect(parseModelRef("anthropic/", "anthropic")).toBeNull();

View File

@@ -109,6 +109,13 @@ function normalizeProviderModelId(provider: string, model: string): string {
if (provider === "anthropic") {
return normalizeAnthropicModelId(model);
}
if (provider === "vercel-ai-gateway" && !model.includes("/")) {
// Allow Vercel-specific Claude refs without an upstream prefix.
const normalizedAnthropicModel = normalizeAnthropicModelId(model);
if (normalizedAnthropicModel.startsWith("claude-")) {
return `anthropic/${normalizedAnthropicModel}`;
}
}
if (provider === "google") {
return normalizeGoogleModelId(model);
}