# `Nous.Providers.VertexAI`
[🔗](https://github.com/nyo16/nous/blob/v0.17.1/lib/nous/providers/vertex_ai.ex#L1)

Google Vertex AI provider implementation.

Supports Gemini models via the Vertex AI API, which provides enterprise features
like VPC-SC, CMEK, IAM, and regional/global endpoints.

## Supported Models

| Model                    | Model ID                       | Endpoint       | API Version |
|--------------------------|--------------------------------|----------------|-------------|
| Gemini 3.1 Pro (preview) | `gemini-3.1-pro-preview`       | global only    | v1beta1     |
| Gemini 3 Flash (preview) | `gemini-3-flash-preview`       | global only    | v1beta1     |
| Gemini 3.1 Flash-Lite    | `gemini-3.1-flash-lite-preview`| global only    | v1beta1     |
| Gemini 2.5 Pro           | `gemini-2.5-pro`               | regional/global| v1          |
| Gemini 2.5 Flash         | `gemini-2.5-flash`             | regional/global| v1          |
| Gemini 2.0 Flash         | `gemini-2.0-flash`             | regional/global| v1          |

Preview and experimental models automatically use the `v1beta1` API version.
Stable models use `v1`. This is determined by `api_version_for_model/1`.

## Authentication

Vertex AI uses OAuth2 Bearer tokens (not API keys like Google AI).
Token resolution order:

1. `:api_key` option passed directly (treated as a Bearer access token)
2. Goth integration — if a Goth process name is configured, fetches tokens automatically
3. `VERTEX_AI_ACCESS_TOKEN` environment variable
4. Application config: `config :nous, :vertex_ai, api_key: "..."`

### Using Goth with a Service Account (Recommended)

Goth handles OAuth2 token fetching, caching, and auto-refresh from a GCP service account.
Load the service account JSON from an environment variable (no file path dependency):

    # Set env vars:
    # export GOOGLE_CREDENTIALS='{"type":"service_account","project_id":"...",...}'
    # export GOOGLE_CLOUD_PROJECT="your-project-id"
    # export GOOGLE_CLOUD_LOCATION="global"  # required for Gemini 3.x preview

    # mix.exs
    {:goth, "~> 1.4"}

    # application.ex — start Goth in your supervision tree
    credentials = System.get_env("GOOGLE_CREDENTIALS") |> JSON.decode!()

    children = [
      {Goth, name: MyApp.Goth, source: {:service_account, credentials}}
    ]

Then configure Nous to use it:

    # config.exs (recommended for production)
    config :nous, :vertex_ai, goth: MyApp.Goth

    # Then just use it:
    agent = Nous.new("vertex_ai:gemini-3.1-pro-preview")
    {:ok, result} = Nous.run(agent, "Hello!")

Or pass Goth per-model (useful for multiple projects):

    agent = Nous.new("vertex_ai:gemini-3-flash-preview",
      default_settings: %{goth: MyApp.Goth}
    )

### Using an Access Token

For quick testing without Goth (tokens expire after ~1 hour):

    # export VERTEX_AI_ACCESS_TOKEN="$(gcloud auth print-access-token)"
    agent = Nous.new("vertex_ai:gemini-3.1-pro-preview")

Or pass it explicitly:

    agent = Nous.new("vertex_ai:gemini-3.1-pro-preview",
      api_key: System.get_env("VERTEX_AI_ACCESS_TOKEN")
    )

## URL Construction

The base URL is built at request time from environment variables and the model name.
The provider selects the correct hostname and API version automatically.

### Regional Endpoints (for stable models)

    https://{region}-aiplatform.googleapis.com/v1/projects/{project}/locations/{region}

### Global Endpoint (required for Gemini 3.x preview models)

    https://aiplatform.googleapis.com/v1beta1/projects/{project}/locations/global

### Environment Variables

- `GOOGLE_CLOUD_PROJECT` (or `GCLOUD_PROJECT`) — GCP project ID (required)
- `GOOGLE_CLOUD_REGION` (or `GOOGLE_CLOUD_LOCATION`) — GCP region or `global` (defaults to `us-central1`)

Both `GOOGLE_CLOUD_REGION` and `GOOGLE_CLOUD_LOCATION` are supported, consistent with
other Google Cloud libraries and tooling. `GOOGLE_CLOUD_REGION` takes precedence if both
are set.

### Explicit Base URL

You can override the auto-constructed URL entirely:

    alias Nous.Providers.VertexAI

    # Use the endpoint helper to build the URL with correct API version:
    url = VertexAI.endpoint("my-project", "global", "gemini-3.1-pro-preview")
    # => "https://aiplatform.googleapis.com/v1beta1/projects/my-project/locations/global"

    agent = Nous.new("vertex_ai:gemini-3.1-pro-preview", base_url: url)

## Input Validation

The provider validates `GOOGLE_CLOUD_PROJECT` and the region at request time and returns
helpful error messages for invalid values (e.g., typos, wrong format) instead of opaque
DNS or HTTP errors.

## Configuration

    # config.exs
    config :nous, :vertex_ai,
      goth: MyApp.Goth

    # Or with an explicit base_url (overrides env var URL construction):
    config :nous, :vertex_ai,
      goth: MyApp.Goth,
      base_url: "https://aiplatform.googleapis.com/v1beta1/projects/my-project/locations/global"

## Thinking (Gemini 2.5/3.x)

For models that support extended thinking, pass `:thinking_config` in
`default_settings`. Both the Elixir shape (snake_case atoms) and the native
Vertex shape (camelCase strings) are accepted:

    Nous.new("vertex_ai:gemini-2.5-pro",
      default_settings: %{
        thinking_config: %{thinking_budget: 1024, include_thoughts: true}
      }
    )

When `include_thoughts: true`, thought summaries arrive as
`Message.reasoning_content`. For tool-using thinking models, Vertex emits a
`thoughtSignature` on each tool call; Nous preserves it in
`tool_call["metadata"]["thought_signature"]` and echoes it back on the next
turn automatically — required for multi-turn thinking + tool loops to keep
working.

See https://cloud.google.com/vertex-ai/generative-ai/docs/thinking for the
Vertex thinking docs.

## Examples

    # Gemini 3.1 Pro on global endpoint (preview, v1beta1)
    agent = Nous.new("vertex_ai:gemini-3.1-pro-preview")

    # Gemini 3 Flash on global endpoint (preview, v1beta1)
    agent = Nous.new("vertex_ai:gemini-3-flash-preview")

    # Gemini 2.0 Flash on regional endpoint (stable, v1)
    agent = Nous.new("vertex_ai:gemini-2.0-flash")

    # With explicit region override
    agent = Nous.new("vertex_ai:gemini-3.1-pro-preview",
      base_url: VertexAI.endpoint("my-project", "global", "gemini-3.1-pro-preview")
    )

# `api_key`

```elixir
@spec api_key(keyword()) :: String.t() | nil
```

Get the API key from options, environment, or application config.

Lookup order:
1. `:api_key` option passed directly
2. Environment variable (VERTEX_AI_ACCESS_TOKEN)
3. Application config: `config :nous, vertex_ai, api_key: "..."`

# `api_version_for_model`

```elixir
@spec api_version_for_model(String.t() | nil) :: String.t()
```

Returns the appropriate API version for a model name.

Preview and experimental models use `v1beta1`, stable models use `v1`.

# `base_url`

```elixir
@spec base_url(keyword()) :: String.t()
```

Get the base URL from options, application config, or default.

Lookup order:
1. `:base_url` option passed directly
2. Application config: `config :nous, vertex_ai, base_url: "..."`
3. Default: 

# `count_tokens`

```elixir
@spec count_tokens(list()) :: integer()
```

Count tokens in messages (rough estimate).

Override this in your provider for more accurate counting.

# `endpoint`

```elixir
@spec endpoint(String.t(), String.t(), String.t() | nil) :: String.t()
```

Build a Vertex AI endpoint URL from project ID, region, and optional model name.

Uses `v1beta1` API version for preview/experimental models and `v1` for stable models.
If no model name is provided, defaults to `v1`.

When region is `"global"`, uses `aiplatform.googleapis.com` (no region prefix).
Regional endpoints use `{region}-aiplatform.googleapis.com`.

Gemini 3.x preview models (`gemini-3.1-pro-preview`, `gemini-3-flash-preview`, etc.)
are only available on the global endpoint.

## Examples

    # Regional endpoint, stable model (v1)
    iex> Nous.Providers.VertexAI.endpoint("my-project", "us-central1")
    "https://us-central1-aiplatform.googleapis.com/v1/projects/my-project/locations/us-central1"

    iex> Nous.Providers.VertexAI.endpoint("my-project", "us-central1", "gemini-2.0-flash")
    "https://us-central1-aiplatform.googleapis.com/v1/projects/my-project/locations/us-central1"

    # Global endpoint, preview model (v1beta1) — required for Gemini 3.x
    iex> Nous.Providers.VertexAI.endpoint("my-project", "global", "gemini-3.1-pro-preview")
    "https://aiplatform.googleapis.com/v1beta1/projects/my-project/locations/global"

    iex> Nous.Providers.VertexAI.endpoint("my-project", "global", "gemini-3-flash-preview")
    "https://aiplatform.googleapis.com/v1beta1/projects/my-project/locations/global"

# `request`

High-level request with message conversion, telemetry, and error wrapping.

Default implementation that:
1. Converts messages to provider format
2. Builds request params
3. Calls chat/2
4. Parses response
5. Emits telemetry events
6. Wraps errors

# `request_stream`

High-level streaming request with message conversion and telemetry.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
