How to Implement Tool Use with the Gemini Interactions API

Use the unified Gen AI SDK (google-genai >= 2.0.0 for Python or @google/genai >= 2.0.0 for TypeScript) to pass local functions via the tools parameter, inspect the response for tool_calls, execute the requested functions locally, and continue the conversation by referencing the previous interaction's ID via previous_interaction_id or previousInteractionId.

The Gemini Interactions API, part of the Gemini Enterprise Agent Platform, supports tool use (also known as function calling) to enable models to request execution of user-defined functions during stateful conversations. As documented in the google/skills repository, this capability requires strict adherence to the unified Gen AI SDK and turn-scoped parameter patterns defined in skills/cloud/gemini-interactions-api/SKILL.md.

Prerequisites and SDK Requirements

The Gemini Interactions API only supports the unified Gen AI SDK. Legacy packages are explicitly prohibited.

  • Python: Install google-genai >= 2.0.0
  • TypeScript/JavaScript: Install @google/genai >= 2.0.0

Initialize the client with enterprise configuration:

from google import genai
import google.auth

_, project_id = google.auth.default()
client = genai.Client(enterprise=True, project=project_id, location="global")
import { GoogleGenAI } from "@google/genai";

const ai = new GoogleGenAI();

Understanding Turn-Scoped Parameters

According to the source documentation in skills/cloud/gemini-interactions-api/SKILL.md, turn-scoped parameters must be supplied with every interaction request. These parameters are not persisted across turns.

Critical turn-scoped parameters include:

  • tools – The list of callable functions or function declarations
  • system_instruction – System-level directives for the model
  • generation_config – Sampling parameters and output constraints

Failing to pass these parameters on subsequent turns results in the model losing access to previously defined tools or configurations.

The Tool Use Implementation Pattern

Implementing tool use requires a four-step workflow: defining tools, passing them to the model, executing requested functions locally, and continuing the conversation with results.

1. Define Local Tools

Create standard Python functions or TypeScript functions that perform the desired operations. The unified SDK automatically serializes Python function signatures into the required schema. For TypeScript, you must explicitly define functionDeclarations with parameter schemas.

def get_stock_price(ticker: str) -> float:
    """Return a mock price for a given ticker."""
    return {"GOOG": 175.50}.get(ticker.upper(), 100.0)
function getStockPrice({ ticker }: { ticker: string }): number {
  return ticker.toUpperCase() === "GOOG" ? 175.5 : 100.0;
}

2. Pass Tools to the First Interaction

Include the tools in the initial interactions.create call using the tools parameter. In Python, pass the raw callable; in TypeScript, pass the structured declaration.

first = client.interactions.create(
    model="gemini-3-flash-preview",
    input="What is the stock price of GOOG?",
    tools=[get_stock_price]          # Pass the callable directly

)
const interaction = await ai.interactions.create({
  model: "gemini-3-flash-preview",
  input: "What is the stock price of GOOG?",
  tools: [
    {
      functionDeclarations: [
        {
          name: "getStockPrice",
          description: "Gets the stock price for a given ticker symbol.",
          parameters: {
            type: Type.OBJECT,
            properties: {
              ticker: { type: Type.STRING, description: "The ticker symbol" }
            },
            required: ["ticker"]
          }
        }
      ]
    }
  ]
});

3. Detect and Execute Tool Calls

Inspect the last step of the response for the tool_calls (Python) or toolCalls (TypeScript) array. If present, extract the function name and arguments, then execute the corresponding local function.

last_step = first.steps[-1]
if last_step.tool_calls:
    for call in last_step.tool_calls:
        if call.name == "get_stock_price":
            ticker = call.args.get("ticker")
            price = get_stock_price(ticker)
const lastStep = interaction.steps[interaction.steps.length - 1];
if (lastStep.toolCalls) {
  for (const call of lastStep.toolCalls) {
    if (call.name === "getStockPrice") {
      const ticker = call.args.ticker as string;
      const price = getStockPrice({ ticker });
    }
  }
}

4. Continue the Conversation with Results

Create a new interaction that references the original interaction's id via previous_interaction_id (Python) or previousInteractionId (TypeScript). Include the tool execution result in the new input to provide context for the model's final response.

final = client.interactions.create(
    model="gemini-3-flash-preview",
    input=f"The stock price for {ticker} is ${price}.",
    previous_interaction_id=first.id   # Maintain state

)
const finalTurn = await ai.interactions.create({
  model: "gemini-3-flash-preview",
  input: `The stock price for ${ticker} is $${price}.`,
  previousInteractionId: interaction.id   // Preserve state
});

Complete Code Examples

Python Implementation

from google import genai
import google.auth

# Initialize client

_, project_id = google.auth.default()
client = genai.Client(enterprise=True, project=project_id, location="global")

# Define tool

def get_stock_price(ticker: str) -> float:
    """Return a mock price for a given ticker."""
    return {"GOOG": 175.50}.get(ticker.upper(), 100.0)

# First interaction

first = client.interactions.create(
    model="gemini-3-flash-preview",
    input="What is the stock price of GOOG?",
    tools=[get_stock_price]
)

# Execute tool calls

last_step = first.steps[-1]
if last_step.tool_calls:
    for call in last_step.tool_calls:
        if call.name == "get_stock_price":
            ticker = call.args.get("ticker")
            price = get_stock_price(ticker)
            
            # Continue with result

            final = client.interactions.create(
                model="gemini-3-flash-preview",
                input=f"The stock price for {ticker} is ${price}.",
                previous_interaction_id=first.id
            )
            print(final.steps[-1].content[0].text)

TypeScript Implementation

import { GoogleGenAI, Type } from "@google/genai";

const ai = new GoogleGenAI();

function getStockPrice({ ticker }: { ticker: string }): number {
  return ticker.toUpperCase() === "GOOG" ? 175.5 : 100.0;
}

const interaction = await ai.interactions.create({
  model: "gemini-3-flash-preview",
  input: "What is the stock price of GOOG?",
  tools: [
    {
      functionDeclarations: [
        {
          name: "getStockPrice",
          description: "Gets the stock price for a given ticker symbol.",
          parameters: {
            type: Type.OBJECT,
            properties: {
              ticker: { type: Type.STRING, description: "The ticker symbol" }
            },
            required: ["ticker"]
          }
        }
      ]
    }
  ]
});

const lastStep = interaction.steps[interaction.steps.length - 1];
if (lastStep.toolCalls) {
  for (const call of lastStep.toolCalls) {
    if (call.name === "getStockPrice") {
      const ticker = call.args.ticker as string;
      const price = getStockPrice({ ticker });

      const finalTurn = await ai.interactions.create({
        model: "gemini-3-flash-preview",
        input: `The stock price for ${ticker} is $${price}.`,
        previousInteractionId: interaction.id
      });
      console.log(finalTurn.steps[finalTurn.steps.length - 1].content[0].text);
    }
  }
}

Streaming Tool Use Responses

To receive incremental chunks during the interaction, pass stream=True (Python) or stream: true (TypeScript) to the interactions.create method. This works for both the initial tool-calling turn and subsequent continuation turns.

response = client.interactions.create(
    model="gemini-3-flash-preview",
    input="What is the stock price of GOOG?",
    tools=[get_stock_price],
    stream=True
)

Summary

  • Use the unified SDK: Only google-genai >= 2.0.0 (Python) or @google/genai >= 2.0.0 (TypeScript) support the Interactions API.
  • Pass tools every turn: The tools parameter is turn-scoped and must be included in every request requiring function access.
  • Python vs. TypeScript: Python accepts raw callables; TypeScript requires explicit functionDeclarations with JSON Schema parameter definitions.
  • Maintain state: Use previous_interaction_id (Python) or previousInteractionId (TypeScript) to link multi-turn conversations after executing tool calls.
  • Check tool_calls: Inspect the last step of the response for the tool_calls array to determine when local execution is required.

Frequently Asked Questions

What SDK versions are required to implement tool use with the Gemini Interactions API?

You must use the unified Gen AI SDK version 2.0.0 or higher. For Python, install google-genai >= 2.0.0. For TypeScript or JavaScript, install @google/genai >= 2.0.0. Legacy packages such as the older Vertex AI SDK or Google AI SDK are not compatible with the Interactions API.

Do I need to pass the tools parameter on every interaction turn?

Yes. Parameters like tools, system_instruction, and generation_config are turn-scoped. According to the documentation in skills/cloud/gemini-interactions-api/SKILL.md, you must pass these parameters with each interaction request. If you omit tools on a subsequent turn, the model loses access to those functions.

How do I maintain conversation state between the tool call and the result?

Create a new interaction that references the previous turn's ID using previous_interaction_id (Python) or previousInteractionId (TypeScript). This parameter links the turns into a single stateful conversation, allowing the model to see the original query, the tool execution result, and generate a final response with full context.

Can I use streaming responses when implementing tool use?

Yes. Pass stream=True (Python) or stream: true (TypeScript) to interactions.create(). The streaming chunks will include the tool_calls data when the model decides to invoke a function, allowing you to process tool requests in real-time before continuing the conversation with the results.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →