Function calling
Provide a map of FunctionDeclarations and the client will drive the function-calling loop for you: it forwards the declarations to the model as tools, invokes the matching function when the model requests a call, feeds the result back, and repeats until the model produces a final answer. Function parameter and return types are derived from ZIO Schema, just like structured responses:
scala
import zio.*
import zio.schema.*
import com.anymindgroup.gcp.aiplatform.*
import com.anymindgroup.gcp.aiplatform.v1.schemas.*
import com.anymindgroup.gcp.auth.defaultAccessTokenBackend
import com.github.plokhotnyuk.jsoniter_scala as json
object express_vertex_ai_function_calling extends ZIOAppDefault:
def run = for
authedBackend <- defaultAccessTokenBackend()
express = ExpressModelClient(
backend = authedBackend,
projectsId = "my-gcp-project",
locationsId = "global",
publishersId = "google",
modelsId = "gemini-3.5-flash",
)
msg = GenerateContentRequest(
contents = Chunk(
GoogleCloudAiplatformV1Content(
parts = Chunk(GoogleCloudAiplatformV1Part(text = Some("What is the weather like in Tokyo?"))),
role = Some("user"),
)
),
responseSchema = Schema[WeatherResult],
)
res <- express.send(
baseRequest = msg,
functions = Map(
"get_weather" -> FunctionDeclaration(
function =
(city: City) => ZIO.succeed(WeatherResult(temperature = 22, unit = "celsius", conditions = "Sunny")),
description = Some("Get the current weather for a given city"),
)
),
)
_ = println(s"Result: $res")
yield ()
case class City(name: String) derives Schema
given json.core.JsonValueCodec[City] = json.macros.JsonCodecMaker.make
case class WeatherResult(temperature: Int, unit: String, conditions: String) derives Schema
given json.core.JsonValueCodec[WeatherResult] = json.macros.JsonCodecMaker.make