Compendium.Adapters.Gemini 1.0.0-preview.0

This is a prerelease version of Compendium.Adapters.Gemini.
dotnet add package Compendium.Adapters.Gemini --version 1.0.0-preview.0
                    
NuGet\Install-Package Compendium.Adapters.Gemini -Version 1.0.0-preview.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Compendium.Adapters.Gemini" Version="1.0.0-preview.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Compendium.Adapters.Gemini" Version="1.0.0-preview.0" />
                    
Directory.Packages.props
<PackageReference Include="Compendium.Adapters.Gemini" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Compendium.Adapters.Gemini --version 1.0.0-preview.0
                    
#r "nuget: Compendium.Adapters.Gemini, 1.0.0-preview.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Compendium.Adapters.Gemini@1.0.0-preview.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Compendium.Adapters.Gemini&version=1.0.0-preview.0&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Compendium.Adapters.Gemini&version=1.0.0-preview.0&prerelease
                    
Install as a Cake Tool

Compendium.Adapters.Gemini

Direct adapter for the Google Gemini REST API (https://generativelanguage.googleapis.com) that implements IAIProvider from Compendium.Abstractions.AI.

What Value
Target framework net9.0
Abstractions pin Compendium.Abstractions.AI 1.0.1
HTTP stack Typed HttpClient + Microsoft.Extensions.Http.Resilience (standard pipeline) + System.Text.Json
Auth ?key=<ApiKey> query parameter on every request
Surface Chat completions (sync + SSE streaming), embeddings (single + batched), tool / function calling, structured outputs, system instructions, vision (inline & file-URI)
Tests xUnit 2.9 + FluentAssertions + NSubstitute + RichardSzalay.MockHttp

Sits alongside Compendium.Adapters.OpenAI and Compendium.Adapters.Anthropic. Use this adapter when you want direct, billable access to Google's Gemini models (1.5 Pro, 2.0 Flash, the embedding family, etc.) — for cost, latency, or Gemini-specific capabilities (long context, native multimodal). For Vertex AI Gemini (Google Cloud auth, different endpoints), use the separate compendium-adapter-vertex-gemini package once it lands.

Installation

dotnet add package Compendium.Adapters.Gemini

Configuration

Register at startup:

services.AddCompendiumGemini(opt =>
{
    opt.ApiKey = builder.Configuration["Gemini:ApiKey"]!;
    opt.DefaultModel = "gemini-2.0-flash";
    opt.DefaultEmbeddingModel = "text-embedding-004";
});

…or bind from IConfiguration (section Gemini):

services.AddCompendiumGemini(builder.Configuration);
{
  "Gemini": {
    "ApiKey": "...",
    "BaseUrl": "https://generativelanguage.googleapis.com",
    "ApiVersion": "v1beta",
    "DefaultModel": "gemini-2.0-flash",
    "DefaultEmbeddingModel": "text-embedding-004",
    "TimeoutSeconds": 120,
    "MaxEmbeddingsBatchSize": 100
  }
}

The standard resilience pipeline (AddStandardResilienceHandler) is applied automatically; tune retry/timeout behaviour by configuring GeminiOptions.TimeoutSeconds and RetryAttempts.

Usage

Chat (sync)

var provider = sp.GetRequiredService<IAIProvider>();
var result = await provider.CompleteAsync(new CompletionRequest
{
    Model = "gemini-2.0-flash",
    SystemPrompt = "Be concise.",
    Messages = new List<Message> { Message.User("Pick a colour.") },
    MaxTokens = 64
});
if (result.IsSuccess) Console.WriteLine(result.Value.Content);

SystemPrompt is sent as Gemini's top-level systemInstruction field — not as a content part — exactly per Google's spec.

Chat (streaming)

await foreach (var chunk in provider.StreamCompleteAsync(request))
{
    if (chunk.IsSuccess) Console.Write(chunk.Value.ContentDelta);
}

Implemented via streamGenerateContent?alt=sse; the final chunk carries IsFinal=true, FinishReason, and Usage (token counts).

Embeddings

var result = await provider.EmbedAsync(new EmbeddingRequest
{
    Model = "text-embedding-004",
    Inputs = manyTexts,
    Dimensions = 768 // optional — sent as outputDimensionality
});
  • Single input goes through embedContent.
  • Multiple inputs are batched through batchEmbedContents in chunks of MaxEmbeddingsBatchSize (default 100, Gemini's documented cap).

Tool / function calling

using Compendium.Adapters.Gemini.Tools;
using Compendium.Abstractions.AI.Agents.Models;

var tools = new List<AgentTool>
{
    new(
        Name: "get_weather",
        Description: "Returns the current weather for the named city.",
        InputSchemaJson: """{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}""")
};

var request = new CompletionRequest
{
    Model = "gemini-2.0-flash",
    Messages = new List<Message> { Message.User("What's the weather in Paris?") }
}.WithTools(tools, toolChoice: "auto");

var result = await provider.CompleteAsync(request);
foreach (var call in result.Value.GetToolCalls())
{
    Console.WriteLine($"{call.ToolName}({call.ArgumentsJson})");
}

toolChoice maps to Gemini's functionCallingConfig.mode:

Value Mode
"auto" AUTO
"any" / "required" ANY
"none" NONE
any other string ANY + allowedFunctionNames: [<name>]

To feed a tool result back to the model, send a Message with Role = MessageRole.Tool and Name = "<function_name>"; the adapter translates it into a functionResponse content. The Content may be a JSON object (passed through verbatim) or plain text (wrapped as {"result": "<text>"}).

Structured outputs

using Compendium.Adapters.Gemini.StructuredOutputs;

var schema = """
{
  "type":"object",
  "properties":{ "city": {"type":"string"}, "tempC": {"type":"number"} },
  "required":["city","tempC"]
}
""";

var request = new CompletionRequest
{
    Model = "gemini-2.0-flash",
    Messages = new List<Message> { Message.User("Weather in Paris as JSON.") }
}.WithStructuredOutput(schema);

// or: plain JSON mode (no schema)
request = request.WithJsonMode();

Schema mode sets responseMimeType: "application/json" + responseSchema. JSON mode sets only the mime type. Globally opt every request into JSON mode with GeminiOptions.UseStructuredOutputsByDefault = true.

Vision (images & files)

CompletionRequest has no first-class image field, so attach a list of pre-built GeminiPart entries under the gemini.vision_parts key in AdditionalParameters:

using Compendium.Adapters.Gemini.Http.Models;

var visionParts = new List<GeminiPart>
{
    new() { InlineData = new GeminiInlineData { MimeType = "image/png", Data = Convert.ToBase64String(bytes) } },
    new() { FileData = new GeminiFileData { MimeType = "image/jpeg", FileUri = "https://files.example/img.jpg" } }
};

var request = new CompletionRequest
{
    Model = "gemini-2.0-flash",
    Messages = new List<Message> { Message.User("Describe the images.") },
    AdditionalParameters = new Dictionary<string, object>
    {
        ["gemini.vision_parts"] = (IReadOnlyList<GeminiPart>)visionParts
    }
};

These parts are appended to the last user content. Files larger than ~20 MB should be uploaded via the Files API and referenced by fileUri.

Cancellation

Every async surface accepts a CancellationToken. The adapter:

  • re-throws OperationCanceledException when the caller cancelled, so callers can await cleanly;
  • maps non-caller cancellations (timeouts) into Result.Failure(AIErrors.Timeout(...));
  • aborts streaming loops on cancellation between SSE chunks.

Error mapping

HTTP Error.Code
401 / 403 AI.InvalidApiKey
402 AI.InsufficientCredits
404 AI.ModelNotFound
429 AI.RateLimitExceeded
5xx / other AI.ProviderError
Timeout (non-cancellation) AI.Timeout

Gemini's structured error body ({ "error": { "code", "message", "status" } }) is parsed when present and surfaced through the Error payload.

Observability

GeminiOptions.EnableLogging = true emits the raw request/response bodies at Debug level via the injected ILogger<GeminiHttpClient>. Keep it off in production — payloads can contain user PII and the API key is on the URL.

Sample

samples/01-chat-with-tool wires up a 1-tool agent and dumps the model's tool-call decision. Run with GEMINI_API_KEY=... dotnet run --project samples/01-chat-with-tool.

Integration tests

Live tests live in tests/Integration/Compendium.Adapters.Gemini.IntegrationTests. They:

  • skip automatically when GEMINI_API_KEY is unset;
  • are excluded from the default CI run via --filter "FullyQualifiedName!~IntegrationTests";
  • hit gemini-2.0-flash / text-embedding-004 so they cost cents per full run.
export GEMINI_API_KEY=...
dotnet test -c Release --filter "FullyQualifiedName~IntegrationTests"

SDK choice (ADR)

Decision: hand-rolled HttpClient + System.Text.Json, no Mscc.GenerativeAI (community SDK) dependency.

Reasons:

  • Avoids the version churn and indirect-deps surface of a community SDK that doesn't track the official spec.
  • Lets the framework's pinned Microsoft.Extensions.Http.Resilience pipeline handle retries / circuit breaking.
  • Mirrors the proven Compendium.Adapters.OpenAI / Compendium.Adapters.Anthropic patterns.
  • Gemini's REST surface is small and stable — generateContent, streamGenerateContent, embedContent, batchEmbedContents, models.

If Google ships an official, stable .NET SDK with a sane transitive graph, we may pivot — document any switch with an updated ADR in docs/.

Out of scope (first preview)

  • Vertex AI Gemini — different endpoints + Google Cloud OAuth — separate Compendium.Adapters.VertexGemini package.
  • Live API (low-latency voice / multimodal streaming) — separate adapter.
  • Code execution tool — feature-flagged, v2.
  • Caching API (cachedContents) — v2.

License

MIT — same as Compendium itself.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0-preview.0 31 5/17/2026