Skip to content

Live Tool Calling

This example assumes using Google.Gemini; is in scope and apiKey contains your Google.Gemini API key.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
using var client = new GeminiClient(apiKey);

try
{
    using var cts = new CancellationTokenSource(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.
    var weatherSchema = 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();

    var config = CreateLiveConfig();
    config.Tools =
    [
        new Tool
        {
            FunctionDeclarations =
            [
                new FunctionDeclaration
                {
                    Name = "get_weather",
                    Description = "Get the current weather for a location",
                    ParametersJsonSchema = weatherSchema,
                },
            ],
        },
    ];

    await using var session = await client.ConnectLiveAsync(config, cancellationToken: cts.Token);

    // Ask about weather to trigger the tool call.
    await session.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;
    await foreach (var message in session.ReadEventsAsync(cts.Token))
    {
        if (message.ToolCall is not null)
        {
            toolCall = message.ToolCall;
            break;
        }

        if (message.ServerContent?.TurnComplete == true)
        {
            break;
        }
    }

    // Send a tool response.
    await session.SendToolResponseAsync(
    [
        new FunctionResponse
        {
            Name = "get_weather",
            Id = toolCall.FunctionCalls[0].Id,
            Response = new { temperature = "15C", condition = "cloudy" },
        },
    ], cts.Token);

    // Read until turn is complete.
    bool receivedResponse = false;
    await foreach (var message in session.ReadEventsAsync(cts.Token))
    {
        if (message.ServerContent?.ModelTurn?.Parts is { Count: > 0 })
        {
            receivedResponse = true;
        }

        if (message.ServerContent?.TurnComplete == true)
        {
            break;
        }
    }

}
catch (WebSocketException ex)
{
}
catch (OperationCanceledException)
{
}