The SDK supports the Gemini Live API for real-time bidirectional voice and video interactions over WebSocket:
1 2 3 4 5 6 7 8 91011121314151617181920212223
usingGoogle.Gemini;usingvarclient=newGeminiClient(apiKey);// Connect to the Live APIawaitusingvarsession=awaitclient.ConnectLiveAsync(newLiveSetupConfig{Model="models/gemini-3.1-flash-live-preview",GenerationConfig=newGenerationConfig{ResponseModalities=[GenerationConfigResponseModalitie.Audio],},});// Send text and receive audio responsesawaitsession.SendTextAsync("Hello, how are you?");awaitforeach(varmessageinsession.ReadEventsAsync()){// Audio data in message.ServerContent.ModelTurn.Parts[].InlineDataif(message.ServerContent?.TurnComplete==true)break;}
// First turnawaitsession.SendTextAsync("My name is Alice");awaitforeach(varmsginsession.ReadEventsAsync()){if(msg.ServerContent?.TurnComplete==true)break;}// Second turn — the model remembers contextawaitsession.SendTextAsync("What's my name?");
System instruction (customize model behavior):
1 2 3 4 5 6 7 8 9101112
awaitusingvarsession=awaitclient.ConnectLiveAsync(newLiveSetupConfig{Model="models/gemini-3.1-flash-live-preview",GenerationConfig=newGenerationConfig{ResponseModalities=[GenerationConfigResponseModalitie.Audio],},SystemInstruction=newContent{Parts=[newPart{Text="You are a friendly pirate. Always respond in pirate speak."}],},});
varconfig=newLiveSetupConfig{Model="models/gemini-3.1-flash-live-preview",GenerationConfig=newGenerationConfig{ResponseModalities=[GenerationConfigResponseModalitie.Audio],},Tools=[newTool{FunctionDeclarations=[myFunction]}],};awaitusingvarsession=awaitclient.ConnectLiveAsync(config);awaitsession.SendTextAsync("What's the weather in London?");awaitforeach(varmessageinsession.ReadEventsAsync()){if(message.ToolCallis{}toolCall){// Handle function call and send responseawaitsession.SendToolResponseAsync([newFunctionResponse{Name=toolCall.FunctionCalls![0].Name,Id=toolCall.FunctionCalls[0].Id,Response=new{temperature="15C"},}]);}// Tool calls cancelled due to user interruptionif(message.ToolCallCancellationis{}cancellation){Console.WriteLine($"Tool calls cancelled: {string.Join(",", cancellation.Ids!)}");}if(message.ServerContent?.TurnComplete==true)break;}
Use FunctionDeclaration.Parameters for simple tool schemas. If you need raw JSON Schema features such as additionalProperties: false, exact propertyOrdering, or you already have a JSON Schema document to reuse, prefer FunctionDeclaration.ParametersJsonSchema instead. The detailed Live API example is in the Live API guide.
Session resumption (reconnect without losing context):
1 2 3 4 5 6 7 8 9101112131415161718192021
varconfig=newLiveSetupConfig{Model="models/gemini-3.1-flash-live-preview",GenerationConfig=newGenerationConfig{ResponseModalities=[GenerationConfigResponseModalitie.Audio],},SessionResumption=newLiveSessionResumptionConfig(),};awaitusingvarsession1=awaitclient.ConnectLiveAsync(config);// ... interact ...varhandle=session1.LastSessionResumptionHandle;// Later, reconnect with the handlevarconfig2=newLiveSetupConfig{// ... same config ...SessionResumption=newLiveSessionResumptionConfig{Handle=handle},};awaitusingvarsession2=awaitclient.ConnectLiveAsync(config2);
Output transcription (get text alongside audio responses):
1 2 3 4 5 6 7 8 910111213141516171819202122
varconfig=newLiveSetupConfig{Model="models/gemini-3.1-flash-live-preview",GenerationConfig=newGenerationConfig{ResponseModalities=[GenerationConfigResponseModalitie.Audio],},OutputAudioTranscription=newLiveOutputAudioTranscription(),};awaitusingvarsession=awaitclient.ConnectLiveAsync(config);awaitsession.SendTextAsync("Tell me a joke");awaitforeach(varmessageinsession.ReadEventsAsync()){// Text transcription of the audio responseif(message.ServerContent?.OutputTranscription?.Textis{}text)Console.Write(text);if(message.ServerContent?.TurnComplete==true)break;}
Send audio/video:
1 2 3 4 5 6 7 8 9101112131415
// Send PCM audio (16-bit, 16kHz, little-endian, mono)awaitsession.SendAudioAsync(pcmBytes);// Send audio with custom MIME typeawaitsession.SendAudioAsync(audioBytes,"audio/pcm;rate=24000");// Send video frameawaitsession.SendVideoAsync(jpegBytes,"image/jpeg");// Stream video frames in a loopforeach(varframeinvideoFrames){awaitsession.SendVideoAsync(frame,"image/jpeg");awaitTask.Delay(100);// ~10 fps}
Auto-reconnect on GoAway (resilient sessions):
1 2 3 4 5 6 7 8 91011121314151617181920212223
// ResilientLiveSession automatically reconnects when the server sends GoAwayawaitusingvarsession=awaitclient.ConnectResilientLiveAsync(newLiveSetupConfig{Model="models/gemini-3.1-flash-live-preview",GenerationConfig=newGenerationConfig{ResponseModalities=[GenerationConfigResponseModalitie.Audio],},});session.GoAwayReceived+=(sender,goAway)=>Console.WriteLine($"Server closing in {goAway.TimeLeft}, reconnecting...");session.Reconnected+=(sender,_)=>Console.WriteLine("Reconnected successfully!");awaitsession.SendTextAsync("Hello!");// Events keep flowing transparently across reconnectionsawaitforeach(varmessageinsession.ReadEventsAsync()){if(message.ServerContent?.TurnComplete==true)break;}
Input audio transcription (get text for audio you send):
1 2 3 4 5 6 7 8 910111213141516171819202122
varconfig=newLiveSetupConfig{Model="models/gemini-3.1-flash-live-preview",GenerationConfig=newGenerationConfig{ResponseModalities=[GenerationConfigResponseModalitie.Audio],},InputAudioTranscription=newLiveInputAudioTranscription(),};awaitusingvarsession=awaitclient.ConnectLiveAsync(config);awaitsession.SendAudioAsync(pcmBytes);awaitforeach(varmessageinsession.ReadEventsAsync()){// Text transcription of the audio you sentif(message.ServerContent?.InputTranscription?.Textis{}text)Console.Write($"[You said: {text}]");if(message.ServerContent?.TurnComplete==true)break;}
varconfig=newLiveSetupConfig{Model="models/gemini-3.1-flash-live-preview",GenerationConfig=newGenerationConfig{ResponseModalities=[GenerationConfigResponseModalitie.Audio],},ContextWindowCompression=newLiveContextWindowCompression{SlidingWindow=newLiveSlidingWindow{TargetTokens=1024,// tokens to retain after compression},},};
**Interruption handling** (user speaks during model response):
1 2 3 4 5 6 7 8 9101112131415161718192021
awaitforeach(varmessageinsession.ReadEventsAsync()){if(message.ServerContent?.Interrupted==true){// Model response was cut short — user started speakingConsole.WriteLine("Model interrupted by user input");}if(message.ServerContent?.ModelTurn?.Partsis{}parts){foreach(varpartinparts){// Process audio/text parts (may be partial if interrupted)if(part.InlineData?.Datais{}audioData)PlayAudio(audioData);}}if(message.ServerContent?.TurnComplete==true)break;}
awaitforeach(varmessageinsession.ReadEventsAsync()){if(message.GoAwayis{}goAway){// Server is closing soon — reconnect using session resumptionConsole.WriteLine($"Server closing in {goAway.TimeLeft}, reconnecting...");break;// dispose session and reconnect with resumption handle}if(message.ServerContent?.TurnComplete==true)break;}
The Gemini API Free Tier is model-specific. In practice, that means this SDK can be used for many free workflows, but whether a call is free depends on the model you choose, not on the SDK method name.
Free Tier commonly covers text and chat generation on selected Gemini models.
It also covers many multimodal understanding scenarios, such as sending images, video, or audio to supported models and getting text back.
Embeddings are available on the Free Tier through models such as gemini-embedding-001 and gemini-embedding-2-preview.
Some live and audio features are also available on the Free Tier for selected preview models.
Native image, video, and music generation are separate model families, so they should not be used as the definition of "what is free".
For the current Free Tier model categories, publicly documented quotas, and official links, see the Gemini API Free Tier guide in the docs and Google's docs for pricing, billing, rate limits, and available regions.
usingvarclient=newGeminiClient(apiKey);varmodelId=GetGenerateContentModelId();try{IChatClientchatClient=client;varupdates=chatClient.GetStreamingResponseAsync(messages:[ new ChatMessage(ChatRole.User, "Generate 5 random words.") ],options:newChatOptions{ModelId=modelId,});vardeltas=newList<string>();awaitforeach(varupdateinupdates){if(!string.IsNullOrWhiteSpace(update.Text)){deltas.Add(update.Text);}}// In streaming mode, rate limiting may not throw ApiException but instead// return empty/truncated data. Treat empty results as inconclusive.if(deltas.Count==0){return;}}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}
Chat Client Five Random Words
1 2 3 4 5 6 7 8 9101112131415161718192021
usingvarclient=newGeminiClient(apiKey);varmodelId=GetGenerateContentModelId();try{IChatClientchatClient=client;varresponse=awaitchatClient.GetResponseAsync(messages:[ new ChatMessage(ChatRole.User, "Generate 5 random words.") ],options:newChatOptions{ModelId=modelId,});}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}
Chat Client Get Service Returns Chat Client Metadata
usingvarclient=newGeminiClient(apiKey);varmodelId=GetGenerateContentModelId();try{vargetWeatherTool=AIFunctionFactory.Create((stringlocation)=>$"The weather in {location} is 72°F and sunny.",name:"get_weather",description:"Gets the current weather for a given location.");IChatClientchatClient=client;varmessages=newList<ChatMessage>{new(ChatRole.User,"What is the weather in Paris?"),};// First turn: model requests tool callvarresponse=awaitchatClient.GetResponseAsync(messages,newChatOptions{ModelId=modelId,Tools=[getWeatherTool],});varfunctionCall=response.Messages.SelectMany(m=>m.Contents).OfType<FunctionCallContent>().FirstOrDefault();// Verify thought signature is preserved on function call content// (Gemini API requires it to be echoed back in subsequent turns)if(functionCall!.AdditionalProperties?.TryGetValue("gemini.thoughtSignature",outvarsig)==true){}// Add assistant message with function call and tool resultmessages.AddRange(response.Messages);vartoolResult=awaitgetWeatherTool.InvokeAsync(functionCall.Argumentsis{}args?newAIFunctionArguments(args):null);messages.Add(newChatMessage(ChatRole.Tool,[ new FunctionResultContent(functionCall.CallId, toolResult), ]));// Second turn: model should produce a final text response// (this verifies the thought signature round-trip works — the API// rejects requests with missing thought signatures)varfinalResponse=awaitchatClient.GetResponseAsync(messages,newChatOptions{ModelId=modelId,Tools=[getWeatherTool],});}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}
usingvarclient=newGeminiClient(apiKey);varmodelId=GetGenerateContentModelId();try{vargetWeatherTool=AIFunctionFactory.Create((stringlocation)=>$"The weather in {location} is 72°F and sunny.",name:"get_weather",description:"Gets the current weather for a given location.");IChatClientchatClient=client;varresponse=awaitchatClient.GetResponseAsync([ new ChatMessage(ChatRole.User, "What is the weather in Paris?") ],newChatOptions{ModelId=modelId,Tools=[getWeatherTool],});// The model should request a tool callvarfunctionCall=response.Messages.SelectMany(m=>m.Contents).OfType<FunctionCallContent>().FirstOrDefault();}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}
usingvarclient=newGeminiClient(apiKey);varmodelId=GetGenerateContentModelId();try{vargetWeatherTool=AIFunctionFactory.Create((stringlocation)=>$"The weather in {location} is 72°F and sunny.",name:"get_weather",description:"Gets the current weather for a given location.");IChatClientchatClient=client;varupdates=chatClient.GetStreamingResponseAsync([ new ChatMessage(ChatRole.User, "What is the weather in Paris?") ],newChatOptions{ModelId=modelId,Tools=[getWeatherTool],});// Collect all streaming updatesvarfunctionCalls=newList<FunctionCallContent>();awaitforeach(varupdateinupdates){functionCalls.AddRange(update.Contents.OfType<FunctionCallContent>());}// In streaming mode, rate limiting may not throw ApiException but instead// return empty/truncated data. Treat empty results as inconclusive.if(functionCalls.Count==0){return;}}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}
usingvarclient=newGeminiClient(apiKey);varmodelId=GetGenerateContentModelId();try{varresponse=awaitclient.ModelsCountTokensAsync(modelsId:modelId,contents:[ new Content { Role = "user", Parts = [new Part { Text = "What is the meaning of life?" }],},newContent{Role="model",Parts=[newPart{Text="The meaning of life is a philosophical question."}],},newContent{Role="user",Parts=[newPart{Text="Can you elaborate?"}],},]);}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}
Count Tokens Simple Text
1 2 3 4 5 6 7 8 91011121314151617181920
usingvarclient=newGeminiClient(apiKey);varmodelId=GetGenerateContentModelId();try{varresponse=awaitclient.ModelsCountTokensAsync(modelsId:modelId,contents:[ new Content { Parts = [new Part { Text = "Hello, world! This is a test of token counting." }],},]);}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}
Edit Image Simple Edit
1 2 3 4 5 6 7 8 91011121314151617181920
usingvarclient=newGeminiClient(apiKey);try{// First generate an image to editvaroriginal=awaitclient.GenerateImageAsync(prompt:"A plain white background",imageSize:"1K");varedited=awaitclient.EditImageAsync(prompt:"Add a red circle in the center",imageData:original.ImageData!,mimeType:original.MimeType??"image/png",imageSize:"1K");}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}
usingvarclient=newGeminiClient(apiKey);varmodelId=GetEmbeddingModelId();try{IEmbeddingGenerator<string,Embedding<float>>generator=client;// Use RETRIEVAL_QUERY task type for search queriesvarqueryResult=awaitgenerator.GenerateAsync(values:["How do I reset my password?"],options:newEmbeddingGenerationOptions{ModelId=modelId,AdditionalProperties=newAdditionalPropertiesDictionary{["TaskType"]="RETRIEVAL_QUERY",},});// Use RETRIEVAL_DOCUMENT task type with a Title for documentsvardocResult=awaitgenerator.GenerateAsync(values:["To reset your password, go to Settings > Security > Change Password."],options:newEmbeddingGenerationOptions{ModelId=modelId,AdditionalProperties=newAdditionalPropertiesDictionary{["TaskType"]="RETRIEVAL_DOCUMENT",["Title"]="Password Reset Guide",},});}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}
File Management
12345
usingvarclient=newGeminiClient(apiKey);varresponse=awaitclient.FilesListAsync();// Should return a valid response even if no files exist
usingvarclient=newGeminiClient(apiKey);varmodelId=GetGenerateContentModelId();try{Console.WriteLine($"Using model: {modelId}");GenerateContentResponseresponse=awaitclient.ModelsGenerateContentAsync(modelsId:modelId,contents:[newContent{Parts=[newPart{Text="Generate 5 random words",},],Role="user",},],generationConfig:newGenerationConfig(),safetySettings:newList<SafetySetting>());Console.WriteLine(response.Candidates?[0].Content?.Parts?[0].Text);}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}
Generate Image Simple Prompt
1 2 3 4 5 6 7 8 910111213
usingvarclient=newGeminiClient(apiKey);try{varresult=awaitclient.GenerateImageAsync(prompt:"A simple red circle on a white background",imageSize:"1K");}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}
Generate Image With Aspect Ratio
1 2 3 4 5 6 7 8 91011121314
usingvarclient=newGeminiClient(apiKey);try{varresult=awaitclient.GenerateImageAsync(prompt:"A landscape with mountains",imageSize:"1K",aspectRatio:"16:9");}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}
Generate Image With References Single Reference
1 2 3 4 5 6 7 8 910111213141516171819
usingvarclient=newGeminiClient(apiKey);try{// First generate a reference imagevarreference=awaitclient.GenerateImageAsync(prompt:"A simple red square",imageSize:"1K");varresult=awaitclient.GenerateImageWithReferencesAsync(prompt:"Create a similar shape but in blue",referenceImages:[(reference.ImageData!,reference.MimeType??"image/png")],imageSize:"1K");}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}
Generate Video Simple Prompt
1 2 3 4 5 6 7 8 910111213141516
usingvarclient=newGeminiClient(apiKey);try{varresult=awaitclient.GenerateVideoAsync(prompt:"A serene beach at sunset with gentle waves");}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}catch(ApiExceptionex)when(ex.StatusCodeisSystem.Net.HttpStatusCode.BadRequest){// VIDEO modality may not be supported in generateContent endpoint yet}
Generate Video From Image Simple Animation
1 2 3 4 5 6 7 8 9101112131415161718192021
usingvarclient=newGeminiClient(apiKey);try{varimage=awaitclient.GenerateImageAsync(prompt:"A still landscape with mountains and a lake",imageSize:"1K");varresult=awaitclient.GenerateVideoFromImageAsync(prompt:"Animate the clouds moving slowly across the sky",imageData:image.ImageData!,mimeType:image.MimeType??"image/png");}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}catch(ApiExceptionex)when(ex.StatusCodeisSystem.Net.HttpStatusCode.BadRequest){}
Interpolate Frames Two Images
1 2 3 4 5 6 7 8 910111213141516171819202122232425
usingvarclient=newGeminiClient(apiKey);try{varstartFrame=awaitclient.GenerateImageAsync(prompt:"A red circle on a white background",imageSize:"1K");varendFrame=awaitclient.GenerateImageAsync(prompt:"A blue square on a white background",imageSize:"1K");varresult=awaitclient.InterpolateFramesAsync(startFrame:startFrame.ImageData!,endFrame:endFrame.ImageData!,prompt:"Smoothly transition between the two shapes");}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}catch(ApiExceptionex)when(ex.StatusCodeisSystem.Net.HttpStatusCode.BadRequest){}
usingvarclient=newGeminiClient(apiKey);try{varresult=awaitclient.SpeakAsync(text:"Say calmly: Testing with a different voice. This should sound professional.",voiceName:"Kore");}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}catch(ApiExceptionex)when(ex.StatusCodeisSystem.Net.HttpStatusCode.BadRequest&&ex.Message.Contains("only be used for TTS")){}
Speak Simple Text
1 2 3 4 5 6 7 8 91011121314151617
usingvarclient=newGeminiClient(apiKey);try{varresult=awaitclient.SpeakAsync(text:"Say cheerfully: Hello, this is a test of text to speech. Have a wonderful day!",voiceName:"Puck");}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}catch(ApiExceptionex)when(ex.StatusCodeisSystem.Net.HttpStatusCode.BadRequest&&ex.Message.Contains("only be used for TTS")){}
Transcribe Generated Audio
1 2 3 4 5 6 7 8 9101112131415161718192021
usingvarclient=newGeminiClient(apiKey);try{// First generate audio to transcribevaraudio=awaitclient.SpeakAsync(text:"Read aloud: The quick brown fox jumps over the lazy dog.");vartranscription=awaitclient.TranscribeAsync(audioData:audio.AudioData!,mimeType:audio.MimeType??"audio/wav");}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}catch(ApiExceptionex)when(ex.StatusCodeisSystem.Net.HttpStatusCode.BadRequest&&ex.Message.Contains("only be used for TTS")){}
Generate Music Simple Prompt
1 2 3 4 5 6 7 8 910111213141516
usingvarclient=newGeminiClient(apiKey);try{// Generate a short music clip from a text prompt using the Lyria 3 Clip model.varresult=awaitclient.GenerateMusicAsync(prompt:"A cheerful acoustic guitar melody with a light percussion beat, major key, 120 BPM");}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}catch(ApiExceptionex)when(ex.StatusCodeisSystem.Net.HttpStatusCode.BadRequest){}
usingvarclient=newGeminiClient(apiKey);try{usingvarcts=newCancellationTokenSource(TimeSpan.FromSeconds(30));// Connects to the Gemini Live API, sends text, receives audio response.awaitusingvarsession=awaitclient.ConnectLiveAsync(CreateLiveConfig(),cancellationToken:cts.Token);// Send a simple text message.awaitsession.SendTextAsync("Say hello",cts.Token);// Read events until the model turn is complete.boolreceivedResponse=false;awaitforeach(varmessageinsession.ReadEventsAsync(cts.Token)){if(message.ServerContent?.ModelTurn?.Partsis{Count:>0}){receivedResponse=true;}if(message.ServerContent?.TurnComplete==true){break;}}}catch(WebSocketExceptionex){}catch(OperationCanceledException){}
usingvarclient=newGeminiClient(apiKey);try{// Generate music with vocals using structure tags and lyrics.varresult=awaitclient.GenerateMusicAsync(prompt:"""Popballad,femalevocal,pianoaccompaniment,90BPM,Cmajor[Verse]Walkingthroughthemorninglight,Everythingfeelswarmandbright.[Chorus]ThisiswhereIwanttobe,Underskiessowideandfree.""");}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}catch(ApiExceptionex)when(ex.StatusCodeisSystem.Net.HttpStatusCode.BadRequest){}
Generate Music Pro Model
1 2 3 4 5 6 7 8 91011121314151617
usingvarclient=newGeminiClient(apiKey);try{// Generate a longer music piece using the Lyria 3 Pro model.varresult=awaitclient.GenerateMusicAsync(prompt:"Epic orchestral soundtrack with strings, brass, and timpani, building from soft to powerful, D minor, 100 BPM",modelId:"lyria-3-pro-preview");}catch(ApiExceptionex)when(IsTransientAvailabilityIssue(ex)){AssertTransientAvailability(ex);}catch(ApiExceptionex)when(ex.StatusCodeisSystem.Net.HttpStatusCode.BadRequest){}
usingvarclient=newGeminiClient(apiKey);try{usingvarcts=newCancellationTokenSource(TimeSpan.FromSeconds(30));// Sends PCM audio and verifies audio parts are received in the response.awaitusingvarsession=awaitclient.ConnectLiveAsync(CreateLiveConfig(),cancellationToken:cts.Token);// Generate a short 16-bit PCM 16kHz sine wave (0.5s of 440Hz tone).varsampleRate=16000;varsamples=(int)(sampleRate*0.5);varpcmBytes=newbyte[samples*2];for(inti=0;i<samples;i++){varsample=(short)(Math.Sin(2*Math.PI*440*i/sampleRate)*8000);pcmBytes[i*2]=(byte)(sample&0xFF);pcmBytes[i*2+1]=(byte)((sample>>8)&0xFF);}awaitsession.SendAudioAsync(pcmBytes,cts.Token);// Also send text to ensure a response is triggered.awaitsession.SendTextAsync("Repeat what you heard",cts.Token);boolreceivedAudioParts=false;awaitforeach(varmessageinsession.ReadEventsAsync(cts.Token)){if(message.ServerContent?.ModelTurn?.Partsis{}parts){foreach(varpartinparts){if(part.InlineData?.Datais{Length:>0}){receivedAudioParts=true;}}}if(message.ServerContent?.TurnComplete==true){break;}}}catch(WebSocketExceptionex){}catch(OperationCanceledException){}
usingvarclient=newGeminiClient(apiKey);try{usingvarcts=newCancellationTokenSource(TimeSpan.FromSeconds(30));// Enables output audio transcription to receive text alongside audio.varconfig=CreateLiveConfig();config.OutputAudioTranscription=newLiveOutputAudioTranscription();awaitusingvarsession=awaitclient.ConnectLiveAsync(config,cancellationToken:cts.Token);// Send a text message and collect transcription events.awaitsession.SendTextAsync("Say the word hello",cts.Token);boolreceivedTranscription=false;boolreceivedAudio=false;awaitforeach(varmessageinsession.ReadEventsAsync(cts.Token)){if(message.ServerContent?.ModelTurn?.Partsis{Count:>0}){receivedAudio=true;}if(message.ServerContent?.OutputTranscription?.Textis{Length:>0}){receivedTranscription=true;}if(message.ServerContent?.TurnComplete==true){break;}}}catch(WebSocketExceptionex){}catch(OperationCanceledException){}
usingvarclient=newGeminiClient(apiKey);try{usingvarcts=newCancellationTokenSource(TimeSpan.FromSeconds(30));// Connects with a speech config to select a specific voice.varconfig=CreateLiveConfig();config.GenerationConfig!.SpeechConfig=newSpeechConfig{VoiceConfig=newVoiceConfig{PrebuiltVoiceConfig=newPrebuiltVoiceConfig{VoiceName="Kore",},},};awaitusingvarsession=awaitclient.ConnectLiveAsync(config,cancellationToken:cts.Token);// Send a message — voice selection is applied at setup time.awaitsession.SendTextAsync("Say hello",cts.Token);boolreceivedResponse=false;awaitforeach(varmessageinsession.ReadEventsAsync(cts.Token)){if(message.ServerContent?.ModelTurn?.Partsis{Count:>0}){receivedResponse=true;}if(message.ServerContent?.TurnComplete==true){break;}}}catch(WebSocketExceptionex){}catch(OperationCanceledException){}
usingvarclient=newGeminiClient(apiKey);try{usingvarcts=newCancellationTokenSource(TimeSpan.FromSeconds(30));// Connects with a system instruction to customize model behavior.varconfig=CreateLiveConfig();config.SystemInstruction=newContent{Parts=[newPart{Text="You are a helpful assistant. Always be concise."}],};awaitusingvarsession=awaitclient.ConnectLiveAsync(config,cancellationToken:cts.Token);// Send a message — system instruction is accepted at setup time.awaitsession.SendTextAsync("Say hello",cts.Token);boolreceivedResponse=false;awaitforeach(varmessageinsession.ReadEventsAsync(cts.Token)){if(message.ServerContent?.ModelTurn?.Partsis{Count:>0}){receivedResponse=true;}if(message.ServerContent?.TurnComplete==true){break;}}}catch(WebSocketExceptionex){}catch(OperationCanceledException){}
usingvarclient=newGeminiClient(apiKey);try{usingvarcts=newCancellationTokenSource(TimeSpan.FromSeconds(30));// Demonstrates a multi-turn conversation using sequential text exchanges.awaitusingvarsession=awaitclient.ConnectLiveAsync(CreateLiveConfig(),cancellationToken:cts.Token);// First turn: tell the model a fact.awaitsession.SendTextAsync("My name is Alice",cts.Token);awaitforeach(varmessageinsession.ReadEventsAsync(cts.Token)){if(message.ServerContent?.TurnComplete==true){break;}}// Second turn: ask the model to recall the fact.awaitsession.SendTextAsync("What is my name?",cts.Token);boolreceivedResponse=false;awaitforeach(varmessageinsession.ReadEventsAsync(cts.Token)){if(message.ServerContent?.ModelTurn?.Partsis{Count:>0}){receivedResponse=true;}if(message.ServerContent?.TurnComplete==true){break;}}}catch(WebSocketExceptionex){}catch(OperationCanceledException){}
usingvarclient=newGeminiClient(apiKey);try{usingvarcts=newCancellationTokenSource(TimeSpan.FromSeconds(30));// Connects to the Live API with a tool and handles a function call.// Use ParametersJsonSchema when you need to send raw JSON Schema features// such as additionalProperties, exact property ordering, or nested metadata.varweatherSchema=JsonDocument.Parse("""{"type":"object","additionalProperties":false,"propertyOrdering":["location","units","preferences"],"properties":{"location":{"type":"string","description":"The city name"},"units":{"type":"string","enum":["celsius","fahrenheit"],"description":"Preferred temperature unit"},"preferences":{"type":"object","description":"Optional weather display preferences","additionalProperties":false,"propertyOrdering":["includeHumidity"],"properties":{"includeHumidity":{"type":"boolean","description":"Whether to include humidity in the response"}}}},"required":["location"]}""").RootElement.Clone();varconfig=CreateLiveConfig();config.Tools=[ new Tool { FunctionDeclarations = [ new FunctionDeclaration { Name = "get_weather", Description = "Get the current weather for a location", ParametersJsonSchema = weatherSchema, }, ],},];awaitusingvarsession=awaitclient.ConnectLiveAsync(config,cancellationToken:cts.Token);// Ask about weather to trigger the tool call.awaitsession.SendTextAsync("What is the weather in London? Use the get_weather tool.",cts.Token);// Read until we get a tool call or turn complete.LiveToolCall?toolCall=null;awaitforeach(varmessageinsession.ReadEventsAsync(cts.Token)){if(message.ToolCallisnotnull){toolCall=message.ToolCall;break;}if(message.ServerContent?.TurnComplete==true){break;}}// Send a tool response.awaitsession.SendToolResponseAsync([ new FunctionResponse { Name = "get_weather", Id = toolCall.FunctionCalls[0].Id,Response=new{temperature="15C",condition="cloudy"},},],cts.Token);// Read until turn is complete.boolreceivedResponse=false;awaitforeach(varmessageinsession.ReadEventsAsync(cts.Token)){if(message.ServerContent?.ModelTurn?.Partsis{Count:>0}){receivedResponse=true;}if(message.ServerContent?.TurnComplete==true){break;}}}catch(WebSocketExceptionex){}catch(OperationCanceledException){}
usingvarclient=newGeminiClient(apiKey);try{usingvarcts=newCancellationTokenSource(TimeSpan.FromSeconds(60));// Connects with session resumption enabled, exchanges a message,// then reconnects using the resumption handle via ReconnectLiveAsync.varconfig=CreateLiveConfig();config.SessionResumption=newLiveSessionResumptionConfig();// First session: send a message and collect the resumption handle.// The handle arrives asynchronously — keep reading after turnComplete.string?resumptionHandle;awaitusing(varsession1=awaitclient.ConnectLiveAsync(config,cancellationToken:cts.Token)){awaitsession1.SendTextAsync("Remember: the secret word is banana.",cts.Token);boolturnDone=false;awaitforeach(varmessageinsession1.ReadEventsAsync(cts.Token)){if(message.ServerContent?.TurnComplete==true){turnDone=true;}// Once turn is done AND we have a handle, stopif(turnDone&&session1.LastSessionResumptionHandleis{Length:>0}){break;}}resumptionHandle=session1.LastSessionResumptionHandle;}if(string.IsNullOrEmpty(resumptionHandle)){}// Second session: reconnect using ReconnectLiveAsync.varconfig2=CreateLiveConfig();config2.SessionResumption=newLiveSessionResumptionConfig{Handle=resumptionHandle,};awaitusingvarsession2=awaitclient.ConnectLiveAsync(config2,cancellationToken:cts.Token);awaitsession2.SendTextAsync("What was the secret word?",cts.Token);boolreceivedResponse=false;awaitforeach(varmessageinsession2.ReadEventsAsync(cts.Token)){if(message.ServerContent?.ModelTurn?.Partsis{Count:>0}){receivedResponse=true;}if(message.ServerContent?.TurnComplete==true){break;}}}catch(WebSocketExceptionex){}catch(OperationCanceledException){}
usingvarclient=newGeminiClient(apiKey);try{usingvarcts=newCancellationTokenSource(TimeSpan.FromSeconds(30));// Connects using ResilientLiveSession and verifies basic text exchange works.varconfig=CreateLiveConfig();awaitusingvarsession=awaitclient.ConnectResilientLiveAsync(config,cancellationToken:cts.Token);// Send a text message through the resilient session.awaitsession.SendTextAsync("Say hello",cts.Token);boolreceivedResponse=false;awaitforeach(varmessageinsession.ReadEventsAsync(cts.Token)){if(message.ServerContent?.ModelTurn?.Partsis{Count:>0}){receivedResponse=true;}if(message.ServerContent?.TurnComplete==true){break;}}}catch(WebSocketExceptionex){}catch(OperationCanceledException){}
Embedding Models
Model
Dimensions
Description
gemini-embedding-001
768 (default)
Stable text embedding model
gemini-embedding-2-preview
3072 (default)
Latest multimodal model — text, images, video, audio, PDFs. Matryoshka dimensions support
The SDK defaults to gemini-embedding-001. For best retrieval quality, use gemini-embedding-2-preview (note: embedding spaces are incompatible between the two models). See Google's embedding guide for details.
API Version
This SDK targets the v1beta API, which is the full-featured version used by Google's own SDKs (Python, JS, Go). The v1 (stable) API only exposes ~30 of the 70+ available endpoints and lacks critical features like tool calling, file upload, context caching, and grounding.