Max Narditdata & ai systems
← Articles
10 mindev

Claude Models on Google Cloud (Anthropic managed) vs Vertex AI: IAM replaces the API key, and three places it doesn't reach

From Vertex AI the reason to move is features. From the first-party API it is IAM instead of keys. Either way the IAM part covers less than it looks: a gateway puts one service account on every call, the read-only role reads every agent transcript unlogged by default, and a revoked grant stops nothing already running.

Contents

On October 22 Anthropic launched Claude Models on Google Cloud (Anthropic managed). It is the Claude API itself, run by Anthropic, reached through claude.googleapis.com, authorized by Google Cloud IAM and billed through Google Cloud Marketplace. The older way to call Claude from a Google project, previously known as Vertex AI, is now Claude Models on Google Cloud (Google managed) in Anthropic’s docs. Its SDK client is still called AnthropicVertex.

Both can use the same project, the same Google credentials and the same bill. They differ in API surface, IAM roles, features and whether an Anthropic organization exists at all. The pitch of the new one is that IAM replaces the API key. That is true, and in three places it reaches less far than it sounds: a gateway in front of it, the read-only role, and agents that are already running. I ran the new AnthropicGoogleCloud client from the Python SDK against a mock transport, with a fake token and nothing sent anywhere, to see what it puts on the wire. The gateway finding came out of that run; the other two come straight from the IAM reference.

What is Claude Models on Google Cloud (Anthropic managed), and how is it different from Vertex AI?

It is the first-party Claude API behind a Google front door, while Vertex AI is Google’s own serving of Claude through Agent Platform prediction endpoints. On the Anthropic-managed side a request looks like any Claude API request: model in the body, anthropic-version as a header, "stream": true for streaming, the same model IDs as api.anthropic.com. On the Google-managed side model sits in the URL, anthropic_version in the body, streaming has its own :streamRawPredict endpoint, and models older than Claude 4.6 use @ before the snapshot date.

The request shape is the small difference. The big one is features. The Google-managed docs list as unsupported the Files API, code execution, web fetch, the advisor tool, Agent Skills, the MCP connector, Message Batches, the Models API, server-side fallback and Claude Managed Agents. The Anthropic-managed page lists every one of those as working. Its own exceptions are MCP tunnels, memory stores on self-hosted environments, and the pre-built self-hosted sandbox workers in the ant CLI and the Python, TypeScript and Go SDKs; for those you write your own worker against the Environments Work endpoints.

Two more things flip when you leave Vertex. The data processor: on Google managed it is Google, on Anthropic managed it is Anthropic, as on api.anthropic.com, and per the docs “some supporting services, such as Anthropic’s trust and safety systems, process data outside Google Cloud.” And the limits: Google sets quotas on the Vertex side, Anthropic sets rate limits on the new one. Usage is metered by Anthropic in Claude Consumption Units of $0.01 each, shows up on the Google bill, and counts toward a Google Cloud spend commitment the way other Marketplace purchases do.

So for a team on Vertex the move is mostly a feature unlock. For a team already on api.anthropic.com, the processor stays the same; what changes is access, billing and the organization you work in.

What does setting up Claude Models on Google Cloud (Anthropic managed) create?

A new Anthropic organization, tied to that Google Cloud project, separate from any organization your company already has, Claude Enterprise included. An existing organization can’t be converted. Setup is four steps: subscribe to the Marketplace listing, enable two services, click Activate and fill in the organization form from an emailed link, then open the Claude Console from the Google Cloud console.

shell
gcloud services enable claude.googleapis.com \
  anthropic-managed-claude.cloudpartnerservices.goog \
  --project=my-project-id

claude.googleapis.com serves the API and defines the IAM permissions; the second service attributes usage to your subscription. Enabling the first creates a service agent in the project, and the docs warn that removing its role grants stops the service. Worth a comment in whatever Terraform or org policy prunes unexpected bindings.

If you come from api.anthropic.com, everything starts from zero. API keys, workspaces and Console settings don’t carry over, and files, skills, batches and Managed Agents resources stay in the old organization. A zero data retention (ZDR) arrangement on another organization doesn’t carry over either; here it is available on request. A negotiated discount has to be raised with your account representative before you start, because “discounts can’t be applied to past usage.” The two organizations are independent and can serve traffic side by side, so the cutover can go workload by workload.

Nobody signs in to the new Console with an email address. Google Cloud checks IAM and redirects to platform.claude.com, and only roles/claude.admin can open it. Someone has to, once, to copy the workspace ID that every caller needs.

What does the AnthropicGoogleCloud SDK client send?

A Google access token as Authorization: Bearer, the SDK’s default API version, and a URL that carries the project and workspace. With ANTHROPIC_API_KEY and ANTHROPIC_BASE_URL both set, as on any machine that already talks to the first-party API, the client ignored both. This is the request the mock transport recorded for messages.create:

POST https://claude.googleapis.com/v1/projects/my-project-id/locations/global/workspaces/wrkspc_01FAKE/invoke/v1/messages
user-agent: AnthropicGoogleCloud/Python 2.3.0
anthropic-version: 2026-10-21
authorization: Bearer ya29.FAKE-token

No x-api-key, and no anthropic-workspace-id header, which the docs say a request must not carry because the workspace is in the path. Organization-level routes, /v1/organizations/ and /v1/user_profiles in this SDK version, go to a base with no workspace in it:

GET https://claude.googleapis.com/v1/projects/my-project-id/locations/global/claudeOrganization/invoke/v1/organizations/me

Three behaviors to know before the first deploy.

The client builds without credentials and fails on the first request. With no Application Default Credentials on the machine, AnthropicGoogleCloud(project=..., workspace_id=...) constructed fine and printed its base URL. The DefaultCredentialsError came only from messages.create. A health check that only instantiates the client passes on a host that can’t make a single call.

A missing workspace ID is a request-time error too. Without one, the client constructed, and the message call raised this:

AnthropicError: No workspace ID found. Set the `workspace_id` argument or the `ANTHROPIC_GOOGLE_CLOUD_WORKSPACE_ID` environment variable.

The organization route was still built and handed to the mock, since it needs no workspace.

The project falls back to GOOGLE_CLOUD_PROJECT. With ANTHROPIC_GOOGLE_CLOUD_PROJECT unset, the client took GOOGLE_CLOUD_PROJECT and built the URL for that project. If that variable names some other project, that is where the calls go. Set the Anthropic-specific one explicitly.

How do you move code from AnthropicVertex to AnthropicGoogleCloud?

Account and access first, then a one-line client swap, then two changes that alter behavior. The new SDK client is in beta. After the setup above, grant roles/claude.user on the project to every identity that calls the API (Agent Platform roles like roles/aiplatform.user don’t apply here), set ANTHROPIC_GOOGLE_CLOUD_PROJECT and ANTHROPIC_GOOGLE_CLOUD_WORKSPACE_ID, and swap the client. In Python:

shell
pip install -U "anthropic[google_cloud]"
python
# before: Google managed (Vertex AI)
from anthropic import AnthropicVertex
client = AnthropicVertex(project_id="my-project-id", region="global")
 
# after: Anthropic managed, project and workspace from the environment
from anthropic import AnthropicGoogleCloud
client = AnthropicGoogleCloud()

In TypeScript the package is @anthropic-ai/google-cloud-sdk, in Go googlecloud.NewClient() replaces vertex.WithGoogleAuth(), and in Java GoogleCloudBackend replaces VertexBackend.

The two changes with teeth:

  • Model IDs. For models before Claude 4.6, replace the @ with a hyphen: claude-haiku-4-5@20251001 becomes claude-haiku-4-5-20251001.
  • Residency. If you picked a regional or multi-region Vertex endpoint for residency, there is no matching URL here; the location is global. What the docs offer is inference_geo: "us" per request for US-only inference, on Claude 4.6 and later models only, at 1.1x the standard price. An EU or single-region requirement needs its own check before you move, and a Haiku 4.5 workload can’t take the parameter at all.

The API version deserves a sentence, though it isn’t caused by leaving Vertex. SDK 2.3.0 sends 2026-10-21 by default from both clients, so the upgrade you do for the swap is what moves you there. Under that version temperature, top_p and top_k return 400, and the SDK no longer takes them as arguments. Drop them, or keep one request on the old version as in the API version 2026-10-21 walkthrough.

The ant CLI needs more care than the SDK. Update it first: per the docs, a version without support ignores the ANTHROPIC_GOOGLE_CLOUD_* variables and either sends the request to the Claude API with any other credential it finds or fails. Even a current CLI prefers a first-party credential when one is present, so unset API keys, auth tokens, ANTHROPIC_PROFILE and the federation variables, and leave ANTHROPIC_WORKSPACE_ID unset, or it sends the forbidden workspace header. Then, before production traffic, make one small real request in the target project and workspace and check the rate limits, which are Anthropic’s now, not your Google quota.

Can an LLM gateway sit in front of Claude Models on Google Cloud?

Yes, and it inherits the routing along with the token. The client option for it is skip_auth, for “a proxy that attaches the token for you”: the client then generates no Google token. A header you set yourself, say a token for the gateway, still goes out. It can’t be combined with a token provider or a credentials object:

ValueError: `skip_auth` is mutually exclusive with `token_provider` and `credentials`; `skip_auth` disables authentication entirely.

What the docs leave implicit is the URL. Pointing the client at a gateway means setting base_url (or ANTHROPIC_GOOGLE_CLOUD_BASE_URL), and an explicit base URL turns off the client’s own routing. With skip_auth=True, a workspace ID set, and base_url="http://gw.internal/claude", the mock transport recorded:

POST http://gw.internal/claude/v1/messages
GET  http://gw.internal/claude/v1/organizations/me

No project, no workspace, and both route types on one base. The workspace ID passed to the client went nowhere. A gateway with a short base like this one has to rebuild the claude.googleapis.com URL itself: pick the project and workspace for each caller, and send organization routes to the claudeOrganization base instead. You can bake a full project-and-workspace prefix into base_url for a single-workspace gateway, but then organization routes land under the workspace path and need their own setting. Either way, the gateway has stopped being a header rewrite. It is a routing table now.

The token it attaches has a second effect. If the gateway calls upstream with its own service account, that account is the identity IAM checks, and the identity in whatever audit entries you have enabled. Which developer sent a request is something only the gateway knows. So the gateway has to authenticate its callers by some mechanism of its own, decide which workspace each may reach, and record that, before it swaps in the Google token.

Compare that with the header move in API version 2026-10-21, where a gateway had to find the credential in X-Api-Key or Authorization. Upstream, that question goes away here: there is no key, and x-api-key must not be sent. Downstream it is yours again. If the same gateway also fronts api.anthropic.com or serves older clients, it still accepts whatever they send and must strip it before attaching the Google token. What else has to pass through untouched is in the Claude Code gateway walkthrough; the docs say anthropic-version and anthropic-beta work here as on the Claude API.

Who can read what with the Claude Models on Google Cloud IAM roles?

More than “read-only” suggests. There are three predefined roles, granted on the project: roles/claude.viewer for every get and list on workspace resources, roles/claude.user for everything on workspace resources including sending messages, and roles/claude.admin for organization-level routes and the Console.

A workspace is not an access boundary. Roles are granted on the project, so a role applies to every workspace in it. The docs’ answer for teams that need separate access is a Google Cloud project per team, each with its own Anthropic organization and its own Marketplace setup.

The viewer reads content, not just metadata. The IAM reference is explicit: files.get covers downloading a file’s content, messageBatches.get covers downloading batch results, and sessions.get covers a session’s event history and stream, so “roles/claude.viewer can read every session’s full event history.” Memory contents and skill version content are readable the same way. Vault credentials can be listed, though their secret fields are never returned. A viewer can’t send a message, but it can read the stored history of every Managed Agents session in the project.

Then the logging default. Cloud Audit Logs records this service under claude.googleapis.com. Most routes are Data Access logs, which the docs say are off by default: messages, files, batches and most Managed Agents resources among them. Encryption key routes and most vault routes are Admin Activity logs, which are always on. Unless Data Access logging is enabled for the project, directly or inherited from a folder or organization policy, a viewer reading a month of session transcripts leaves no audit entry. Turn it on before you grant viewer to anyone you would ever need to audit.

What happens to Claude Managed Agents when you revoke IAM access on Google Cloud?

Nothing happens to anything already running. Access is checked when a session or a deployment is created, not while it runs. A session started by an identity you revoke keeps running, and a scheduled deployment doesn’t re-check its creator on each run. The docs’ instruction is to review the sessions and deployments an identity created whenever you remove a user or rotate a service account.

The docs give the rule, not the procedure. The order I would use, so the identity can’t start new work while you clean up:

  • Remove its IAM binding first, and its access to any gateway that calls on its behalf.
  • Then, as an admin who still has access, pause, update or archive the scheduled deployments it created.
  • Send each of its running sessions a user.interrupt event by itself, then archive or delete the session once it is idle.
  • List again and confirm nothing it started is still running.

That assumes you know what it created. With a shared gateway identity, “created by” is the gateway’s service account for everyone, so keep your own record of who started which session and deployment.

Budgets are the exception to “checked only at creation.” A session budget is enforced before each model request, while the session runs, and it can be changed or removed later. It can only be attached when the session is created, though, so an unbudgeted session can’t get one afterwards. If your agents fan out on their own, as in Managed Agents dynamic workflows, set the budget at creation.

Should a team on Vertex AI or api.anthropic.com move to Claude Models on Google Cloud?

Move by workload, not all at once. From Vertex AI the case is strong for anything that needs a feature Vertex lacks: batches, files, skills, the MCP connector, Managed Agents. It is weak for a plain Messages workload that works today and depends on a regional endpoint or on Google as the data processor, since both change.

From api.anthropic.com, you get IAM instead of keys and usage that counts toward a Google commitment. You pay with an organization that starts empty, a ZDR arrangement to re-request, stored resources to recreate, and new rate limits. A team that already replaced static keys with workload identity federation gets less from the IAM half.

My read: new workloads on the Anthropic-managed side, the ones with history where they are, and the IAM work before the traffic. Turn on Data Access logs, decide who really needs viewer, and write down the Managed Agents offboarding step before the first person leaves.

01 / Discussion

No comment section here — all discussions happen on X.

Max Nardit@mnardit

02 / More articles