Function calling lets developers create a description of a function in their code, then pass that description to a language model in a request. The response from the model includes the name of a function that matches the description and the arguments to call it with. Function calling lets you use functions as tools in generative AI applications, and you can define more than one function within a single request.
This notebook provides code examples to help you get started. The documentation’s quickstart is also a good place to start understanding function calling.
You can create your API key using Google AI Studio with a single click.
Remember to treat your API key like a password. Don’t accidentally save it in a notebook or source file you later commit to GitHub. In this notebook we will be storing the API key in a .env file. You can also set it as an environment variable or use a secret manager.
Another option is to set the API key as an environment variable. You can do this in your terminal with the following command:
$ export GEMINI_API_KEY="<YOUR_API_KEY>"
Load the API key
To load the API key from the .env file, we will use the dotenv package. This package loads environment variables from a .env file into process.env.
$ npm install dotenv
Then, we can load the API key in our code:
const dotenv =require("dotenv") astypeofimport("dotenv");dotenv.config({ path:"../.env",});const GEMINI_API_KEY =process.env.GEMINI_API_KEY??"";if (!GEMINI_API_KEY) {thrownewError("GEMINI_API_KEY is not set in the environment variables");}console.log("GEMINI_API_KEY is set in the environment variables");
GEMINI_API_KEY is set in the environment variables
Note
In our particular case the .env is is one directory up from the notebook, hence we need to use ../ to go up one directory. If the .env file is in the same directory as the notebook, you can omit it altogether.
To use function calling, pass a list of FunctionDeclaration or CallableTool to the tools parameter when creating a GenerativeModel. The model uses this to decide if it needs the function to best answer a prompt and if so, it returns the relevant parameters to call the function.
Example: Lighting System Functions
Here are 3 functions controlling a hypothetical lighting system.
import { CallableTool, FunctionCall, FunctionDeclaration, Part, Tool, Type } from"@google/genai";const enable_lights: FunctionDeclaration = { name:"enable_lights", description:"Turn on the lighting system.", response: { type: Type.STRING, description:"A confirmation message indicating that the lights have been enabled.", },};const set_light_color: FunctionDeclaration = { name:"set_light_color", description:"Set the light color. Lights must be enabled for this to work.", parameters: { type: Type.OBJECT, properties: { color: { type: Type.STRING, description:"The color to set the lights to. Must be a valid rgb color in the format 'rgb(r, g, b)' or 'hex(#RRGGBB)'.", }, }, required: ["color"], }, response: { type: Type.STRING, description:"A confirmation message indicating that the lights have been set to the specified color.", },};const stop_lights: FunctionDeclaration = { name:"stop_lights", description:"Stop flashing lights.", response: { type: Type.STRING, description:"A confirmation message indicating that the lights have been stopped.", },};const enable_lights_tool: CallableTool = { callTool:async (functionCalls: FunctionCall[]):Promise<Part[]>=> {console.log("Enabling lights...",JSON.stringify(functionCalls,null,2));const functionCall = functionCalls[0];return [ google.createPartFromFunctionResponse(functionCall.id??"", functionCall.name??"", { name: functionCall.name, result:"Lights have been enabled.", }), ]; }, tool:async ():Promise<Tool>=> ({ functionDeclarations: [enable_lights] }),};const set_light_color_tool: CallableTool = {asynccallTool(functionCalls: FunctionCall[]):Promise<Part[]> {console.log("Setting light colors...",JSON.stringify(functionCalls,null,2));const functionCall = functionCalls[0];const color = functionCall.argsas { color:string };return [ google.createPartFromFunctionResponse(functionCall.id??"", functionCall.name??"", { name: functionCall.name, result:`Lights have been set to color: ${color.color}`, }), ]; },asynctool():Promise<Tool> {return { functionDeclarations: [set_light_color] }; },};const stop_lights_tool: CallableTool = {asynccallTool(functionCalls: FunctionCall[]):Promise<Part[]> {console.log("Stopping lights...",JSON.stringify(functionCalls,null,2));const functionCall = functionCalls[0];return [ google.createPartFromFunctionResponse(functionCall.id??"", functionCall.name??"", { name: functionCall.name, result:"Lights have been stopped.", }), ]; },asynctool():Promise<Tool> {return { functionDeclarations: [stop_lights] }; },};
Basic Function Calling with Chat
Function calls naturally fit into multi-turn conversations. The JS SDK’s ChatSession (client.chats.create(…)) is ideal for this, as it automatically handles conversation history.
Note
For now in the JS SDK automatic function calling is only supported by generateContentStream and sendMessageStream also its enabled by default, to disable this behavior you can set functionCallingConfig.mode to None:
const chat = ai.chats.create({ model: MODEL_ID, config: { systemInstruction:` You are a helpful lighting system bot. You can turn lights on and off, and you can set the color. Do not perform any other tasks. `, tools: [enable_lights_tool, set_light_color_tool, stop_lights_tool], toolConfig: { functionCallingConfig: { mode: google.FunctionCallingConfigMode.AUTO, }, }, },});// temporarily make console.warn a no-op to avoid warnings in the output (non-text part in GenerateContentResponse caused by accessing .text)// https://github.com/googleapis/js-genai/blob/d82aba244bdb804b063ef8a983b2916c00b901d2/src/types.ts#L2005// copy the original console.warn function to restore it laterconst warn_fn =console.warn;// eslint-disable-next-line @typescript-eslint/no-empty-function, no-empty-functionconsole.warn=function () {};const chat_response_1 =await chat.sendMessageStream({ message:"It's awful dark in here...",});forawait (const part of chat_response_1) {console.log(part.text??"");}
Enabling lights... [
{
"name": "enable_lights",
"args": {}
}
]
Ok
, I've turned on the lights.
Examining Function Calls and Execution History
To understand what happened in the background, you can examine the chat history.
The Chat.history property stores a chronological record of the conversation between the user and the Gemini model. You can get the history using Chat.getHistory(). Each turn in the conversation is represented by a genai.types.Content object, which contains the following information:
Role: Identifies whether the content originated from the “user” or the “model”.
Parts: A list of genai.types.Part objects that represent individual components of the message. With a text-only model, these parts can be:
Text: Plain text messages.
Function Call (genai.types.FunctionCall): A request from the model to execute a specific function with provided arguments.
Function Response (genai.types.FunctionResponse): The result returned by the user after executing the requested function.
Function Call
{
"name": "enable_lights",
"args": {}
}
user:
Function Response
{
"id": "",
"name": "enable_lights",
"response": {
"name": "enable_lights",
"result": "Lights have been enabled."
}
}
model:
Ok
model:
, I’ve turned on the lights.
This history shows the flow:
User: Sends the message.
Model: Responds not with text, but with a FunctionCall requesting enable_lights.
User (SDK): The ChatSession automatically executes enable_lights() because FunctionCallingConfigMode.AUTO is set. It sends the result back as a FunctionResponse.
Model: Uses the function’s result (“Lights enabled.”) to formulate the final text response.
Example: Math Operations
import { CallableTool, FunctionCall, FunctionDeclaration, Part, Tool, Type } from"@google/genai";const add: FunctionDeclaration = { name:"add", description:"Add two numbers together.", parameters: { type: Type.OBJECT, properties: { a: { type: Type.NUMBER, description:"The first number to add.", }, b: { type: Type.NUMBER, description:"The second number to add.", }, }, required: ["a","b"], }, response: { type: Type.NUMBER, description:"The sum of the two numbers.", },};const add_tool: CallableTool = { callTool:async (functionCalls: FunctionCall[]):Promise<Part[]>=> {console.log("Adding numbers...",JSON.stringify(functionCalls,null,2));const functionCall = functionCalls[0];const args = functionCall.argsas { a:number; b:number };const result = args.a+ args.b;return [ google.createPartFromFunctionResponse(functionCall.id??"", functionCall.name??"", { name: functionCall.name, result, }), ]; }, tool:async ():Promise<Tool>=> ({ functionDeclarations: [add] }),};const subtract: FunctionDeclaration = { name:"subtract", description:"Subtract two numbers.", parameters: { type: Type.OBJECT, properties: { a: { type: Type.NUMBER, description:"The number to subtract from.", }, b: { type: Type.NUMBER, description:"The number to subtract.", }, }, required: ["a","b"], }, response: { type: Type.NUMBER, description:"The result of the subtraction.", },};const subtract_tool: CallableTool = { callTool:async (functionCalls: FunctionCall[]):Promise<Part[]>=> {console.log("Subtracting numbers...",JSON.stringify(functionCalls,null,2));const functionCall = functionCalls[0];const args = functionCall.argsas { a:number; b:number };const result = args.a- args.b;return [ google.createPartFromFunctionResponse(functionCall.id??"", functionCall.name??"", { name: functionCall.name, result, }), ]; }, tool:async ():Promise<Tool>=> ({ functionDeclarations: [subtract] }),};const multiply: FunctionDeclaration = { name:"multiply", description:"Multiply two numbers together.", parameters: { type: Type.OBJECT, properties: { a: { type: Type.NUMBER, description:"The first number to multiply.", }, b: { type: Type.NUMBER, description:"The second number to multiply.", }, }, required: ["a","b"], }, response: { type: Type.NUMBER, description:"The product of the two numbers.", },};const multiply_tool: CallableTool = { callTool:async (functionCalls: FunctionCall[]):Promise<Part[]>=> {console.log("Multiplying numbers...",JSON.stringify(functionCalls,null,2));const functionCall = functionCalls[0];const args = functionCall.argsas { a:number; b:number };const result = args.a* args.b;return [ google.createPartFromFunctionResponse(functionCall.id??"", functionCall.name??"", { name: functionCall.name, result, }), ]; }, tool:async ():Promise<Tool>=> ({ functionDeclarations: [multiply] }),};const divide: FunctionDeclaration = { name:"divide", description:"Divide two numbers.", parameters: { type: Type.OBJECT, properties: { a: { type: Type.NUMBER, description:"The number to divide.", }, b: { type: Type.NUMBER, description:"The number to divide by.", }, }, required: ["a","b"], }, response: { type: Type.NUMBER, description:"The result of the division.", },};const divide_tool: CallableTool = { callTool:async (functionCalls: FunctionCall[]):Promise<Part[]>=> {console.log("Dividing numbers...",JSON.stringify(functionCalls,null,2));const functionCall = functionCalls[0];const args = functionCall.argsas { a:number; b:number };if (args.b===0) {thrownewError("Cannot divide by zero"); }const result = args.a/ args.b;return [ google.createPartFromFunctionResponse(functionCall.id??"", functionCall.name??"", { name: functionCall.name, result, }), ]; }, tool:async ():Promise<Tool>=> ({ functionDeclarations: [divide] }),};
const math_chat = ai.chats.create({ model: MODEL_ID, config: { tools: [add_tool, subtract_tool, multiply_tool, divide_tool], toolConfig: { functionCallingConfig: { mode: google.FunctionCallingConfigMode.AUTO, }, }, },});const math_chat_response_1 =await math_chat.sendMessageStream({ message:"I have 57 cats, each owns 44 mittens, how many mittens is that in total?",});forawait (const part of math_chat_response_1) {console.log(part.text??"");}
Multiplying numbers... [
{
"name": "multiply",
"args": {
"a": 57,
"b": 44
}
}
]
That
is 2508 mittens in total.
printHistory(math_chat.getHistory());
user:
I have 57 cats, each owns 44 mittens, how many mittens is that in total?
Automatic execution handled the multiply call seamlessly.
Manual function calling
For more control, or if automatic function calling is not available, you can process FunctionCall requests from the model yourself. This would be the case if:
You use a Chat with the default automaticFunctionCalling: { disable: true }.
You use generateContent or sendMessage.
Example: Movies
The following example uses functions that return (mock) movie playtime information, possibly from a hypothetical API:
import { CallableTool, FunctionCall, FunctionDeclaration, Part, Tool, Type } from"@google/genai";const find_movie: FunctionDeclaration = { name:"find_movie", description:"Find movie titles currently playing in theaters based on any description, genre, title words, etc.", parameters: { type: Type.OBJECT, properties: { description: { type: Type.STRING, description:"Any kind of description including category or genre, title words, attributes, etc.", }, location: { type: Type.STRING, description:"The city and state, e.g. San Francisco, CA or a zip code e.g. 95616", }, }, required: ["description","location"], }, response: { type: Type.ARRAY, items: { type: Type.STRING, }, description:"A list of movie titles that match the search criteria.", },};const find_movie_tool: CallableTool = { callTool:async (functionCalls: FunctionCall[]):Promise<Part[]>=> {console.log("Finding movies...",JSON.stringify(functionCalls,null,2));const functionCall = functionCalls[0];const args = functionCall.argsas { description:string; location:string };// Mock responseconst movies = ["Barbie","Oppenheimer"];return [ google.createPartFromFunctionResponse(functionCall.id??"", functionCall.name??"", { name: functionCall.name, result: movies, }), ]; }, tool:async ():Promise<Tool>=> ({ functionDeclarations: [find_movie] }),};const find_theaters: FunctionDeclaration = { name:"find_theaters", description:"Find theaters based on location and optionally movie title which are currently playing in theaters.", parameters: { type: Type.OBJECT, properties: { location: { type: Type.STRING, description:"The city and state, e.g. San Francisco, CA or a zip code e.g. 95616", }, movie: { type: Type.STRING, description:"Any movie title", }, }, required: ["location"], }, response: { type: Type.ARRAY, items: { type: Type.STRING, }, description:"A list of theater names that match the search criteria.", },};const find_theaters_tool: CallableTool = { callTool:async (functionCalls: FunctionCall[]):Promise<Part[]>=> {console.log("Finding theaters...",JSON.stringify(functionCalls,null,2));const functionCall = functionCalls[0];const args = functionCall.argsas { location:string; movie?:string };// Mock responseconst theaters = ["Googleplex 16","Android Theatre"];return [ google.createPartFromFunctionResponse(functionCall.id??"", functionCall.name??"", { name: functionCall.name, result: theaters, }), ]; }, tool:async ():Promise<Tool>=> ({ functionDeclarations: [find_theaters] }),};const get_showtimes: FunctionDeclaration = { name:"get_showtimes", description:"Find the start times for movies playing in a specific theater.", parameters: { type: Type.OBJECT, properties: { location: { type: Type.STRING, description:"The city and state, e.g. San Francisco, CA or a zip code e.g. 95616", }, movie: { type: Type.STRING, description:"Any movie title", }, theater: { type: Type.STRING, description:"Name of the theater", }, date: { type: Type.STRING, description:"Date for requested showtime", }, }, required: ["location","theater","date"], }, response: { type: Type.ARRAY, items: { type: Type.STRING, }, description:"A list of showtimes for the specified movie in the specified theater.", },};const get_showtimes_tool: CallableTool = { callTool:async (functionCalls: FunctionCall[]):Promise<Part[]>=> {console.log("Getting showtimes...",JSON.stringify(functionCalls,null,2));const functionCall = functionCalls[0];const args = functionCall.argsas { location:string; movie:string; theater:string; date:string };// Mock responseconst showtimes = ["10:00 AM","11:00 AM","1:00 PM"];return [ google.createPartFromFunctionResponse(functionCall.id??"", functionCall.name??"", { name: functionCall.name, result: showtimes, }), ]; }, tool:async ():Promise<Tool>=> ({ functionDeclarations: [get_showtimes] }),};const theater_functions: CallableTool[] = [find_movie_tool, find_theaters_tool, get_showtimes_tool];
const movie_response_1 =await ai.models.generateContent({ model: MODEL_ID, contents:"Which theaters in Mountain View, CA show the Barbie movie?", config: { tools: theater_functions, },});const movie_fc = movie_response_1.candidates[0].content.parts[0];console.log(JSON.stringify(movie_fc,null,2));
Finally, pass the response plus the message history to the next generateContent() call to get a final text response from the model.
const movie_response_2 =await ai.models.generateContent({ model: MODEL_ID, contents: [ { role:"user", parts: [google.createPartFromText("Which theaters in Mountain View, CA show the Barbie movie?")], }, { role:"model", parts: [movie_fc], }, { role:"tool", parts: result, }, ], config: { tools: theater_functions, },});console.log(movie_response_2.text??"");
The Barbie movie is playing at Googleplex 16 and Android Theatre in Mountain View, CA.
This demonstrates the manual workflow: call, check, execute, respond, call again.
Parallel function calls
The Gemini API can call multiple functions in a single turn. This caters for scenarios where there are multiple function calls that can take place independently to complete a task.
First set the tools up. Unlike the movie example above, these functions do not require input from each other to be called so they should be good candidates for parallel calling.
import { CallableTool, FunctionCall, FunctionDeclaration, Part, Tool, Type } from"@google/genai";const power_disco_ball: FunctionDeclaration = { name:"power_disco_ball", description:"Powers the spinning disco ball.", parameters: { type: Type.OBJECT, properties: { power: { type: Type.BOOLEAN, description:"Whether the disco ball should be spinning or not.", }, }, required: ["power"], }, response: { type: Type.BOOLEAN, description:"Returns true if the disco ball is spinning.", },};const power_disco_ball_tool: CallableTool = { callTool:async (functionCalls: FunctionCall[]):Promise<Part[]>=> {console.log("Powering disco ball...",JSON.stringify(functionCalls,null,2));const functionCall = functionCalls[0];const args = functionCall.argsas { power:boolean };console.log(`Disco ball is ${args.power?"spinning!":"stopped."}`);return [ google.createPartFromFunctionResponse(functionCall.id??"", functionCall.name??"", { name: functionCall.name, result:true, }), ]; }, tool:async ():Promise<Tool>=> ({ functionDeclarations: [power_disco_ball] }),};const start_music: FunctionDeclaration = { name:"start_music", description:"Play some music matching the specified parameters.", parameters: { type: Type.OBJECT, properties: { energetic: { type: Type.BOOLEAN, description:"Whether the music is energetic or not.", }, loud: { type: Type.BOOLEAN, description:"Whether the music is loud or not.", }, bpm: { type: Type.NUMBER, description:"The beats per minute of the music.", }, }, required: ["energetic","loud","bpm"], }, response: { type: Type.STRING, description:"The name of the song being played.", },};const start_music_tool: CallableTool = { callTool:async (functionCalls: FunctionCall[]):Promise<Part[]>=> {console.log("Starting music...",JSON.stringify(functionCalls,null,2));const functionCall = functionCalls[0];const args = functionCall.argsas { energetic:boolean; loud:boolean; bpm:number };console.log(`Starting music! ${args.energetic}${args.loud}, ${args.bpm}`);return [ google.createPartFromFunctionResponse(functionCall.id??"", functionCall.name??"", { name: functionCall.name, result:"Never gonna give you up.", }), ]; }, tool:async ():Promise<Tool>=> ({ functionDeclarations: [start_music] }),};const dim_lights: FunctionDeclaration = { name:"dim_lights", description:"Dim the lights.", parameters: { type: Type.OBJECT, properties: { brightness: { type: Type.NUMBER, description:"The brightness of the lights, 0.0 is off, 1.0 is full.", }, }, required: ["brightness"], }, response: { type: Type.BOOLEAN, description:"Returns true if the lights are dimmed.", },};const dim_lights_tool: CallableTool = { callTool:async (functionCalls: FunctionCall[]):Promise<Part[]>=> {console.log("Dimming lights...",JSON.stringify(functionCalls,null,2));const functionCall = functionCalls[0];const args = functionCall.argsas { brightness:number };console.log(`Lights are now set to ${args.brightness.toFixed(2)}`);return [ google.createPartFromFunctionResponse(functionCall.id??"", functionCall.name??"", { name: functionCall.name, result:true, }), ]; }, tool:async ():Promise<Tool>=> ({ functionDeclarations: [dim_lights] }),};const party_functions: CallableTool[] = [power_disco_ball_tool, start_music_tool, dim_lights_tool];
Now call the model with an instruction that could use all of the specified tools.
const party_chat = ai.chats.create({ model: MODEL_ID, config: { tools: party_functions, toolConfig: { functionCallingConfig: { mode: google.FunctionCallingConfigMode.ANY, }, }, },});const party_response_1 =await party_chat.sendMessageStream({ message:"Turn this place into a party!",});forawait (const part of party_response_1) {console.log(part.text??"");}printHistory(party_chat.getHistory());
Powering disco ball... [
{
"name": "power_disco_ball",
"args": {
"power": true
}
}
]
Disco ball is spinning!
Starting music... [
{
"name": "start_music",
"args": {
"energetic": true,
"bpm": 120,
"loud": true
}
}
]
Powering disco ball... [
{
"name": "power_disco_ball",
"args": {
"power": true
}
}
]
Disco ball is spinning!
Starting music... [
{
"name": "start_music",
"args": {
"energetic": true,
"loud": true,
"bpm": 120
}
}
]
Starting music! true true, 120
Dimming lights... [
{
"name": "dim_lights",
"args": {
"brightness": 0.5
}
}
]
Lights are now set to 0.50
Powering disco ball... [
{
"name": "power_disco_ball",
"args": {
"power": true
}
}
]
Disco ball is spinning!
Starting music... [
{
"name": "start_music",
"args": {
"energetic": true,
"loud": true,
"bpm": 120
}
}
]
Starting music! true true, 120
Dimming lights... [
{
"name": "dim_lights",
"args": {
"brightness": 0.5
}
}
]
Lights are now set to 0.50
Powering disco ball... [
{
"name": "power_disco_ball",
"args": {
"power": true
}
}
]
Disco ball is spinning!
Starting music... [
{
"name": "start_music",
"args": {
"loud": true,
"energetic": true,
"bpm": 120
}
}
]
Starting music! true true, 120
Dimming lights... [
{
"name": "dim_lights",
"args": {
"brightness": 0.5
}
}
]
Lights are now set to 0.50
Powering disco ball... [
{
"name": "power_disco_ball",
"args": {
"power": true
}
}
]
Disco ball is spinning!
Starting music... [
{
"name": "start_music",
"args": {
"loud": true,
"energetic": true,
"bpm": 120
}
}
]
Starting music! true true, 120
Dimming lights... [
{
"name": "dim_lights",
"args": {
"brightness": 0.5
}
}
]
Lights are now set to 0.50
Powering disco ball... [
{
"name": "power_disco_ball",
"args": {
"power": true
}
}
]
Disco ball is spinning!
Starting music... [
{
"name": "start_music",
"args": {
"loud": true,
"energetic": true,
"bpm": 120
}
}
]
Starting music! true true, 120
Dimming lights... [
{
"name": "dim_lights",
"args": {
"brightness": 0.5
}
}
]
Lights are now set to 0.50
Powering disco ball... [
{
"name": "power_disco_ball",
"args": {
"power": true
}
}
]
Disco ball is spinning!
Starting music... [
{
"name": "start_music",
"args": {
"loud": true,
"bpm": 120,
"energetic": true
}
}
]
Starting music! true true, 120
Dimming lights... [
{
"name": "dim_lights",
"args": {
"brightness": 0.5
}
}
]
Lights are now set to 0.50
Powering disco ball... [
{
"name": "power_disco_ball",
"args": {
"power": true
}
}
]
Disco ball is spinning!
Starting music... [
{
"name": "start_music",
"args": {
"energetic": true,
"bpm": 120,
"loud": true
}
}
]
Starting music! true true, 120
Dimming lights... [
{
"name": "dim_lights",
"args": {
"brightness": 0.5
}
}
]
Lights are now set to 0.50
Powering disco ball... [
{
"name": "power_disco_ball",
"args": {
"power": true
}
}
]
Disco ball is spinning!
Starting music... [
{
"name": "start_music",
"args": {
"bpm": 120,
"energetic": true,
"loud": true
}
}
]
Starting music! true true, 120
Dimming lights... [
{
"name": "dim_lights",
"args": {
"brightness": 0.5
}
}
]
Lights are now set to 0.50
Powering disco ball... [
{
"name": "power_disco_ball",
"args": {
"power": true
}
}
]
Disco ball is spinning!
Starting music... [
{
"name": "start_music",
"args": {
"loud": true,
"bpm": 120,
"energetic": true
}
}
]
Starting music! true true, 120
Dimming lights... [
{
"name": "dim_lights",
"args": {
"brightness": 0.5
}
}
]
Lights are now set to 0.50
Notice the single model turn contains three FunctionCall parts, which the SDK then executed before getting the final text response.
Compositional Function Calling
The model can chain function calls across multiple turns, using the result from one call to inform the next. This allows for complex, multi-step reasoning and task completion.
Example: Finding Specific Movie Showtimes
Let’s reuse the theater_functions and ask a more complex query that requires finding movies first, then potentially theaters, then showtimes.
const theater_chat = ai.chats.create({ model: MODEL_ID, config: { tools: theater_functions, },});const theater_response_1 =await theater_chat.sendMessageStream({ message:"Find comedy movies playing in Mountain View, CA on 01/01/2025. First, find the movie titles. Then, find the theaters showing those movies. Finally, find the showtimes for each movie at each theater.",});forawait (const part of theater_response_1) {console.log(part.text??"");}printHistory(theater_chat.getHistory());
Finding movies... [
{
"name": "find_movie",
"args": {
"location": "Mountain View, CA",
"description": "comedy movies"
}
}
]
OK
. I found two comedy movies playing in Mountain View, CA: Barbie and Oppenheimer
. Now I need to find the theaters showing these movies.
Finding theaters... [
{
"name": "find_theaters",
"args": {
"movie": "Barbie",
"location": "Mountain View, CA"
}
}
]
Finding theaters... [
{
"name": "find_theaters",
"args": {
"location": "Mountain View, CA",
"movie": "Oppenheimer"
}
}
]
OK
. Both movies are playing at Googleplex 16 and Android Theatre. Now I need to
find the showtimes for each movie at each theater on 01/0
1/2025.
Getting showtimes... [
{
"name": "get_showtimes",
"args": {
"movie": "Barbie",
"theater": "Googleplex 16",
"location": "Mountain View, CA",
"date": "01/01/2025"
}
}
]
Getting showtimes... [
{
"name": "get_showtimes",
"args": {
"movie": "Barbie",
"date": "01/01/2025",
"theater": "Android Theatre",
"location": "Mountain View, CA"
}
}
]
Getting showtimes... [
{
"name": "get_showtimes",
"args": {
"location": "Mountain View, CA",
"movie": "Oppenheimer",
"theater": "Googleplex 16",
"date": "01/01/2025"
}
}
]
Getting showtimes... [
{
"name": "get_showtimes",
"args": {
"location": "Mountain View, CA",
"theater": "Android Theatre",
"date": "01/01/2025",
"movie": "Oppenheimer"
}
}
]
OK
. Here are the showtimes for the movies:
Barbie:
- Googleplex
16: 10:00 AM, 11:0
0 AM, 1:00 PM
- Android Theatre: 10:00 AM, 11:00 AM, 1
:00 PM
Oppenheimer:
- Googleplex 16: 10:00 AM, 11:00 AM
, 1:00 PM
- Android Theatre: 10:00 AM, 11:00 AM, 1:00 PM
user:
Find comedy movies playing in Mountain View, CA on 01/01/2025. First, find the movie titles. Then, find the theaters showing those movies. Finally, find the showtimes for each movie at each theater.
Here you can see that the model made seven calls to answer your question and used the outputs of them in the subsequent calls and in the final answer.
Function Calling Configuration using Modes
While AUTO mode (or the SDK’s default automatic execution) is often sufficient, you can precisely control when and which functions the model is allowed to call using the toolConfig parameter during model/chat initialization.
The toolConfig accepts a ToolConfig object, which contains a FunctionCallingConfig.
The FunctionCallingConfig has two main fields:
mode: Controls the overall function calling behavior (AUTO, ANY, NONE).
allowedFunctionNames: An optional list of function names the model is restricted to calling in this turn.
AUTO (Default Mode)
Behavior: The model decides whether to respond with text or to call one or more functions from the provided tools. This is the most flexible mode.
SDK Default: When using chat with automatic execution enabled, the underlying behavior effectively uses AUTO mode unless overridden by toolConfig.
const auto_chat = ai.chats.create({ model: MODEL_ID, config: { systemInstruction:` You are a helpful lighting system bot. You can turn lights on and off, and you can set the color. Do not perform any other tasks. `, tools: [enable_lights_tool, set_light_color_tool, stop_lights_tool], toolConfig: { functionCallingConfig: { mode: google.FunctionCallingConfigMode.AUTO, }, }, },});const auto_response_1 =await auto_chat.sendMessageStream({ message:"Turn on the lights!",});forawait (const part of auto_response_1) {console.log(part.text??"");}printHistory(auto_chat.getHistory());
Enabling lights... [
{
"name": "enable_lights",
"args": {}
}
]
OK
, I've turned on the lights.
user:
Turn on the lights!
model:
Function Call
{
"name": "enable_lights",
"args": {}
}
user:
Function Response
{
"id": "",
"name": "enable_lights",
"response": {
"name": "enable_lights",
"result": "Lights have been enabled."
}
}
model:
OK
model:
, I’ve turned on the lights.
NONE Mode
Behavior: The model is explicitly prohibited from calling any functions, even if tools are provided. It will only respond with text. Useful for turns where you want a purely conversational response.
const none_chat = ai.chats.create({ model: MODEL_ID, config: { systemInstruction:` You are a helpful lighting system bot. You can turn lights on and off, and you can set the color. Do not perform any other tasks. `, tools: [enable_lights_tool, set_light_color_tool, stop_lights_tool], toolConfig: { functionCallingConfig: { mode: google.FunctionCallingConfigMode.NONE, }, }, },});const none_response_1 =await none_chat.sendMessageStream({ message:"Hello light-bot, what can you do?",});forawait (const part of none_response_1) {console.log(part.text??"");}printHistory(none_chat.getHistory());
I
can turn lights on and off, and I can set the color.
user:
Hello light-bot, what can you do?
model:
I
model:
can turn lights on and off, and I can set the color.
ANY Mode
Behavior: Forces the model to call at least one function.
If allowedFunctionNames is set, the model must choose one or more functions from that list.
If allowedFunctionNames is not set, the model must choose one or more functions from the full tools list.
If automatic function calling is enabled, the SDK will call functions automatically until maximumRemoteCalls is reached (default: 10).
To allow x automatic function calls, set maximumRemoteCalls to x + 1.
Use Case: Useful when the application state dictates that the next step must involve a specific action or set of actions.
const any_chat = ai.chats.create({ model: MODEL_ID, config: { systemInstruction:` You are a helpful lighting system bot. You can turn lights on and off, and you can set the color. Do not perform any other tasks. `, tools: [enable_lights_tool, set_light_color_tool, stop_lights_tool], toolConfig: { functionCallingConfig: { mode: google.FunctionCallingConfigMode.ANY, }, }, automaticFunctionCalling: { maximumRemoteCalls:1, }, },});const any_response_1 =await any_chat.sendMessageStream({ message:"Make this place PURPLE!",});forawait (const part of any_response_1) {console.log(part.text??"");}printHistory(any_chat.getHistory());
Function Response
{
"id": "",
"name": "set_light_color",
"response": {
"name": "set_light_color",
"result": "Lights have been set to color: hex(#800080)"
}
}
If you reply manually using Chats.sendMessage ormodels.generateContent remember thart the API is stateless you have to send the whole conversation history (a list of Content objects), not just the last one containing the FunctionResponse.
Related examples
Check out these examples using function calling to give you more ideas on how to use that very useful feature:
Discover how to control the model output in JSON or using an Enum or learn how the Gemini API can generate and run code by itself using Code execution.