Repository navigation
NativeAOT and Trimming Guidelines
NativeAOT and trimming make applications smaller and faster to start, but they restrict runtime reflection and dynamic code generation. This page explains which parts of the SDK work without changes and where you need to supply your own JsonSerializerContext.
-
SDK request and response types. All built-in types are serialized with System.Text.Json source generation, so no reflection-based serialization is needed for the SDK's own types:
-
TypesSerializerContext(namespaceGenerativeAI.Types): the core context used byDefaultSerializerOptions.Optionsfor content generation, chat, embeddings, files, caching, models, batch, Live API setup, auth tokens and more. -
Separate contexts for newer API areas. Each client puts its context first in its own resolver chain:
Context Used by FileSearchSerializerContextFileSearchStoresClient(File Search stores and documents)InteractionsSerializerContextInteractionsClient(Interactions API) and, for shared types, the agent API clientsWebhooksSerializerContextWebhooksClientTuningSerializerContextTuningClientAgentApisSerializerContextAgentsClient,VoicesClient,EnvironmentsClient,TriggersClient,CredentialsClient,DecisionsClientThese are separate contexts rather than partials of
TypesSerializerContextbecause the System.Text.Json source generator shipped for net6.0 to net10.0 and netstandard2.0 fails when[JsonSerializable]attributes are split across partial declarations.
-
-
Source-generated function tools. Tools defined with
[FunctionTool]or[GenerateJsonSchema](see Function Calling) generate their schemas and call code at compile time.
The repository's tests/AotTest project (<PublishAot>true</PublishAot>) exercises these paths.
Your own types are not known to the SDK's contexts. You must register them when you use:
-
JSON mode (
GenerateObjectAsync<T>,UseJsonMode<T>,ToObject<T>), see JSON Mode -
Reflection-based
QuickTool/QuickTools, for parameter and return types
using System.Text.Json.Serialization;
using GenerativeAI;
public class MyData
{
public string Name { get; set; } = string.Empty;
public int Age { get; set; }
}
[JsonSerializable(typeof(MyData))]
public partial class MyDataJsonContext : JsonSerializerContext { }Then register it in one of three ways (see Passing a JsonSerializerContext):
// Option 1: global
DefaultSerializerOptions.CustomJsonTypeResolvers.Add(MyDataJsonContext.Default);
// Option 2: per GenerativeModel instance
generativeModel.GenerateObjectJsonSerializerOptions = MyDataJsonContext.Default.Options;
// Option 3: per request / response
var request = new GenerateContentRequest();
request.UseJsonMode<MyData>(MyDataJsonContext.Default.Options);Register every parameter type and return type used by the tool:
using System.Text.Json.Serialization;
using GenerativeAI;
using GenerativeAI.Tools;
public class ToolInput { public string InputText { get; set; } = string.Empty; }
public class ToolOutput { public int Result { get; set; } }
[JsonSerializable(typeof(ToolInput))]
[JsonSerializable(typeof(ToolOutput))]
public partial class MyToolJsonContext : JsonSerializerContext { }
public static class MyTools
{
public static ToolOutput MyToolMethod(ToolInput input) => new() { Result = input.InputText.Length };
}
// Option 1: global
DefaultSerializerOptions.CustomJsonTypeResolvers.Add(MyToolJsonContext.Default);
// Option 2: pass the options to the constructor
var quickTool = new QuickTool(MyTools.MyToolMethod, options: MyToolJsonContext.Default.Options);QuickTools(Delegate[] delegates, JsonSerializerOptions? options = null) accepts the same options for several delegates.
-
Global. Add the context to
DefaultSerializerOptions.CustomJsonTypeResolversat startup. It is then used by JSON mode and QuickTools everywhere in the application.using GenerativeAI; public static void ConfigureJsonContext() { DefaultSerializerOptions.CustomJsonTypeResolvers.Add(MyDataJsonContext.Default); }
-
GenerativeModelscope. SetGenerateObjectJsonSerializerOptionson a model instance. You can skip this if the context is already registered globally.using GenerativeAI; public async Task<MyData?> UseModelScopedContext(string apiKey, string prompt) { var googleAi = new GoogleAi(apiKey); var model = googleAi.CreateGenerativeModel(GoogleAIModels.Gemini38Flash); model.GenerateObjectJsonSerializerOptions = MyDataJsonContext.Default.Options; return await model.GenerateObjectAsync<MyData>(prompt); }
-
Request / response level. Pass the options to
GenerateContentRequest.UseJsonMode<T>(options)andGenerateContentResponse.ToObject<T>(options).using GenerativeAI; using GenerativeAI.Types; public async Task UseRequestSpecificContext(GenerativeModel model, string prompt) { var request = new GenerateContentRequest(); request.AddText(prompt); request.UseJsonMode<MyData>(MyDataJsonContext.Default.Options); var response = await model.GenerateContentAsync(request); var myData = response.ToObject<MyData>(MyDataJsonContext.Default.Options); Console.WriteLine($"Name: {myData?.Name}, Age: {myData?.Age}"); }
GenerativeAIChatClient and the other MEAI adapters (see Microsoft.Extensions.AI IChatClient) use the same serialization. For tools, prefer [FunctionTool(MeaiFunctionTool = true)] or [GenerateJsonSchema(MeaiFunctionTool = true)] and their generated AsMeaiTools(). If you use new QuickTool(...).AsMeaiTool(), register your types as shown above.
-
Register every type. All types used in JSON mode and QuickTools must be in a
JsonSerializerContext; a missing type causes a runtime error in AOT or trimmed builds. - Performance. Pre-generated serialization code also improves startup time and throughput.
-
Trimming. The trimmer removes unused code; a
JsonSerializerContextkeeps the serialization code your types need. - Reflection limits. Prefer source generation and explicit type registration over runtime reflection.
-
Check warnings. Publish with
dotnet publish -c Release(withPublishAotorPublishTrimmed) and fix anyIL2026/IL3050warnings that point at your own reflection-based code.
Getting Started
- Initialization
- Authentication
- Configuration & Error Handling
- Supported Models
- Migration Guide (v4)
- Release Notes (v4)
Core Features
- Generate Content
- Chat Session
- Streaming
- Multimodal Features
- JSON Mode
- Function Calling
- Embeddings
- Context Caching
Gemini APIs
- Interactions API
- Multimodal Live API
- File Search
- Batch API
- Model Tuning
- Webhooks
- Agent APIs
- Image Generation
- Video Generation
- Speech Generation
- Files Client
- Model Client
Vertex AI
Integrations
Guides
Legacy