Google

Gemini over the Interactions API and generateContent, plus embeddings, files, caching, batch, Imagen, Veo, and Gemini Live.

let model = GoogleModel("gemini-3.6-flash")

Key from GOOGLE_GENERATIVE_AI_API_KEY; base URL https://generativelanguage.googleapis.com/v1beta.

Two chat surfaces

Google now has two ways to talk to Gemini, and both are here:

SurfaceModel typeUse it for
generateContent / streamGenerateContentGoogleModelThe wire everything already speaks. Google calls it legacy but keeps it fully supported
Interactions APIGoogleInteractionsModelWhere Google ships new features: server-side conversation state, background execution, and agents
let interactions = GoogleInteractionsModel("gemini-3.6-flash")
let result = try await generateText(model: interactions, prompt: "Explain how AI works")

Both conform to LanguageModel, so tools, structured output, reasoning, and the whole generateText / streamText / Agent surface work either way.

Server-side state, background runs, and agents

var chat = GoogleInteractionsModel("gemini-3.6-flash", store: true)
let first = try await generateText(model: chat, prompt: "I have 2 dogs.")

chat.previousInteractionID = first.providerMetadata?["google"]?["interactionId"]?.stringValue
let second = try await generateText(model: chat, prompt: "How many paws?")

previousInteractionID replays the stored history server-side instead of resending it, which also raises cache hit rates. store defaults to false here even though Google's API defaults it to true — opting into 55-day (paid) or 1-day (free) retention should be a decision you make, not one you inherit. background: true runs long tasks server-side, and cancel(_:), retrieve(_:), and delete(_:) manage a stored interaction.

Agents use the same endpoint with agent: instead of model::

let research = GoogleInteractionsModel.agent("deep-research-preview-04-2026")
let report = try await generateText(model: research, prompt: "Compare Swift 6 concurrency proposals")

agent_config replaces generation_config for agent runs (Antigravity and CodeMender take their own settings), so pass it through GoogleInteractionsModel.agent(agentConfig:). Reasoning maps to thinking_level (minimal / low / medium / high); thought steps arrive as .reasoningDelta and the interaction id lands on result.providerMetadata["google"]["interactionId"].

Features

  • Tools, vision, and file parts on the native generateContent wire.
  • Structured output uses constrained decoding (responseSchema + responseMimeType), not prompt tricks.
  • The reasoning parameter maps to thinkingConfig (below); thinking streams as .reasoningDelta.
  • usage.cachedInputTokens reports context-cache hits.
  • Full groundingMetadata, safetyRatings, and urlContextMetadata arrive on result.providerMetadata["google"] (grounding chunks also surface as .source).
  • Native fields (safetySettings, cachedContent, ...) pass through providerOptions at the top level.
  • Grounding tools have typed builders under GoogleModel.ToolsgoogleSearch, urlContext, codeExecution, fileSearch, enterpriseWebSearch, googleMaps (Gemini 2.0 and newer). Pass them in tools: and they run server-side. Grounding chunks surface as StreamPart.source:
let result = try await generateText(
  model: GoogleModel("gemini-3.6-flash"),
  prompt: "Ground this in current sources.",
  tools: [GoogleModel.Tools.googleSearch(), GoogleModel.Tools.urlContext()]
)

Models

  • gemini-3* takes thinkingLevel.none and .minimal both map to minimal (thinking can't be fully disabled), .xhigh caps at high. Exception: gemini-3-pro-image stays on budgets.
  • Everything else takes thinkingBudget: 0 for .none, otherwise a fraction of the 65,536-token ceiling capped at 32,768 (2.5 Pro, gemini-3-pro-image) or 24,576 (the rest).

Current lineup

Language models as of July 2026, newest first:

ModelNotes
gemini-3.6-flashNewest flash (July 2026)
gemini-3.5-flash, gemini-3.5-flash-litePrevious flash line
gemini-3.1-pro-previewPro preview
gemini-3.1-flash-liteFast and cheap
gemini-3-flash, gemini-3-pro-previewGemini 3 line
gemini-3-pro-imageImage-out model — budget-based thinking
gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-liteThe 2.5 line
gemma-4-31b-itOpen-weights Gemma via the same API

Vertex AI

let vertex = GoogleVertexModel(
  "gemini-3.5-flash",
  project: "my-project",      // or GOOGLE_VERTEX_PROJECT
  location: "us-central1"     // or GOOGLE_VERTEX_LOCATION
)

Express-mode API keys and bearer accessToken: auth both work; the request body is identical to the Gemini wire.

Gemini Live

GoogleRealtimeModel connects to the Live API for realtime voice: tokens mint against v1alpha/auth_tokens and the session config rides in the token request. See Realtime voice for connection, session, audio, and tool-call events.

Embeddings

let embeddings = GoogleEmbeddingModel(
  "gemini-embedding-001",
  taskType: .retrievalDocument,
  outputDimensionality: 768
)
let vectors = try await embedMany(model: embeddings, values: chunks)

One text uses embedContent, several use batchEmbedContents automatically. taskType covers the documented set (retrieval query and document, semantic similarity, classification, clustering, question answering, fact verification, code retrieval).

Beyond text

SurfaceEntry point
Image generationGoogleImageModel("imagen-4.0-generate-001") — Imagen :predict
Video generationGoogleVideoModel("veo-3.1-generate-preview") — Veo :predictLongRunning with polling and URI download
Speech generationGoogleSpeechModel("gemini-3.1-flash-tts-preview") — audio modality on generateContent
MusicGoogleMusicModel("lyria-3-clip-preview").generateMusic(prompt:)

Platform APIs

let files = GoogleFilesClient()
let uploaded = try await files.upload(audio, mimeType: "audio/mpeg", displayName: "call.mp3")
let ready = try await files.waitUntilActive(uploaded.name)

let answer = try await generateText(
  model: GoogleModel("gemini-3.6-flash"),
  messages: [Message(role: .user, content: [
    .text("Summarize this call."),
    .file(FileContent(url: URL(string: ready.uri)!, mediaType: "audio/mpeg"))
  ])]
)

GoogleFilesClient implements Google's two-step resumable upload (X-Goog-Upload-Protocol: resumable, then a finalize PUT to the returned URL), plus get, list, delete, and waitUntilActive for the PROCESSING → ACTIVE transition that large media needs.

  • GoogleCachedContentClient: explicit context caching — create (with ttlSeconds), list, get, updateTTL, delete. Pass the returned cachedContents/… name through providerOptions as cachedContent.
  • GoogleBatchClient: create (batchGenerateContent), createEmbeddings (asyncBatchEmbedContent), get, list, cancel, delete — the 50%-cheaper async path.
  • GoogleModel.countTokens(_:systemInstruction:): pre-flight sizing against models/{id}:countTokens.