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

Google Gemini provider implementation.

Supports Gemini models via the Google AI Generative Language API.

## Usage

    # Basic usage
    {:ok, response} = Nous.Providers.Gemini.chat(%{
      model: "gemini-2.0-flash-exp",
      contents: [%{"role" => "user", "parts" => [%{"text" => "Hello"}]}]
    })

    # With system instruction
    {:ok, response} = Nous.Providers.Gemini.chat(%{
      model: "gemini-2.0-flash-exp",
      systemInstruction: %{"parts" => [%{"text" => "You are helpful."}]},
      contents: [%{"role" => "user", "parts" => [%{"text" => "Hello"}]}],
      generationConfig: %{"temperature" => 0.7, "maxOutputTokens" => 1024}
    })

    # Streaming
    {:ok, stream} = Nous.Providers.Gemini.chat_stream(params)
    Enum.each(stream, fn event -> IO.inspect(event) end)

## Configuration

    # In config.exs
    config :nous, :gemini,
      api_key: "AIza...",
      base_url: "https://generativelanguage.googleapis.com/v1beta"  # optional

## Note on Authentication

The API key is sent via the `x-goog-api-key` request header (not the URL
query string), so it does not leak into proxy/load-balancer access logs,
tracing spans, or redirect logs.

## 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:

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

    # Native Vertex shape
    Nous.new("gemini:gemini-2.5-pro",
      default_settings: %{
        thinking_config: %{"thinkingBudget" => 1024, "includeThoughts" => 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://ai.google.dev/gemini-api/docs/thinking for the Gemini-side docs
and https://cloud.google.com/vertex-ai/generative-ai/docs/thinking for the
Vertex equivalent.

# `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 (GOOGLE_AI_API_KEY)
3. Application config: `config :nous, gemini, api_key: "..."`

# `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, gemini, base_url: "..."`
3. Default: https://generativelanguage.googleapis.com/v1beta

# `count_tokens`

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

Count tokens in messages (rough estimate).

Override this in your provider for more accurate counting.

# `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*
