Skip to content
繁體中文
Gemini Messages

Tool Calling ​

Connect model requests to your application functions and return results for the next turn.

POST /v1beta/interactions

Custom functions run in your application. The model supplies the function name and arguments; your code performs the lookup and returns the result.

Route prerequisite

These are Interactions protocol examples. The current local gateway registers Gemini generateContent, not /v1beta/interactions; run these examples only if your deployment separately provides that route. See Gemini CLI for native clients and Nano Banana for image generation. On 404, do not change only the URL: the request and response schemas differ.

Request and Authentication ​

http
POST https://api.tokatlas.ai/v1beta/interactions
x-goog-api-key: YOUR_API_KEY
Content-Type: application/json
json
{
  "model": "gemini-2.5-flash",
  "tools": [
    {
      "type": "function",
      "name": "lookup_stock",
      "description": "Look up available inventory for a product SKU.",
      "parameters": {
        "type": "object",
        "properties": {
          "sku": {
            "type": "string",
            "description": "Product SKU, for example DEMO-001"
          }
        },
        "required": [
          "sku"
        ],
        "additionalProperties": false
      }
    }
  ],
  "input": "Check stock for DEMO-001."
}

Tool Call Format ​

Illustrative call item; IDs and arguments come from the actual response.

json
{
  "type": "function_call",
  "id": "call_example",
  "name": "lookup_stock",
  "arguments": {
    "sku": "DEMO-001"
  }
}
  • Read function_call entries in steps; arguments is an object. Return function_result with call_id equal to the call’s id.

  • This example requires stored interactions. Pass the latest previous_interaction_id and resend tools each round. With store: false, preserve the full interaction history, including thought/signature data.

  • Use the Interactions schema shown here, not generateContent fields such as functionDeclarations or functionResponse. For streaming, reconstruct complete steps before dispatching calls.

First Request in Each Language ​

These requests obtain a tool-call request; they do not execute the tool. Use the complete workflow below to return results with the actual call IDs and continue the conversation.

See language setup. Set API_KEY and replace model, file URL, and ID placeholders first. Each version displays the raw response to the same request.

bash
curl --fail-with-body --silent --show-error --max-time 180 \
  --request POST \
  --url "https://api.tokatlas.ai/v1beta/interactions" \
  --header "x-goog-api-key: $API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
  "model": "gemini-3.7-flash",
  "tools": [
    {
      "type": "function",
      "name": "lookup_stock",
      "description": "Look up available inventory for a product SKU.",
      "parameters": {
        "type": "object",
        "properties": {
          "sku": {
            "type": "string",
            "description": "Product SKU, for example DEMO-001"
          }
        },
        "required": [
          "sku"
        ],
        "additionalProperties": false
      }
    }
  ],
  "stream": false,
  "input": "Check stock for DEMO-001.",
  "store": true
}'
python
import os
import requests

headers = {
    'x-goog-api-key': os.environ["API_KEY"],
    'Content-Type': 'application/json',
}
payload = {'model': 'gemini-3.7-flash',
 'tools': [{'type': 'function',
            'name': 'lookup_stock',
            'description': 'Look up available inventory for a product SKU.',
            'parameters': {'type': 'object',
                           'properties': {'sku': {'type': 'string',
                                                  'description': 'Product SKU, for '
                                                                 'example DEMO-001'}},
                           'required': ['sku'],
                           'additionalProperties': False}}],
 'stream': False,
 'input': 'Check stock for DEMO-001.',
 'store': True}
response = requests.request(
    'POST', 'https://api.tokatlas.ai/v1beta/interactions', headers=headers,
    json=payload,
    timeout=180,
)
response.raise_for_status()
print(response.text)
js
if (!process.env.API_KEY) throw new Error("Set API_KEY first.");
const response = await fetch("https://api.tokatlas.ai/v1beta/interactions", {
  method: "POST",
  headers: {
    "x-goog-api-key": process.env.API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
  "model": "gemini-3.7-flash",
  "tools": [
    {
      "type": "function",
      "name": "lookup_stock",
      "description": "Look up available inventory for a product SKU.",
      "parameters": {
        "type": "object",
        "properties": {
          "sku": {
            "type": "string",
            "description": "Product SKU, for example DEMO-001"
          }
        },
        "required": [
          "sku"
        ],
        "additionalProperties": false
      }
    }
  ],
  "stream": false,
  "input": "Check stock for DEMO-001.",
  "store": true
}),
  signal: AbortSignal.timeout(180_000),
});
if (!response.ok) {
  throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
console.log(await response.text());
java
import java.net.URI;
import java.net.http.*;
import java.time.Duration;

public class Example {
    public static void main(String[] args) throws Exception {
        String apiKey = System.getenv("API_KEY");
        if (apiKey == null || apiKey.isBlank()) {
            throw new IllegalArgumentException("Set API_KEY first.");
        }
        String payload = String.join("\n",
            "{",
            "  \"model\": \"gemini-3.7-flash\",",
            "  \"tools\": [",
            "    {",
            "      \"type\": \"function\",",
            "      \"name\": \"lookup_stock\",",
            "      \"description\": \"Look up available inventory for a product SKU.\",",
            "      \"parameters\": {",
            "        \"type\": \"object\",",
            "        \"properties\": {",
            "          \"sku\": {",
            "            \"type\": \"string\",",
            "            \"description\": \"Product SKU, for example DEMO-001\"",
            "          }",
            "        },",
            "        \"required\": [",
            "          \"sku\"",
            "        ],",
            "        \"additionalProperties\": false",
            "      }",
            "    }",
            "  ],",
            "  \"stream\": false,",
            "  \"input\": \"Check stock for DEMO-001.\",",
            "  \"store\": true",
            "}"
        );
        HttpClient client = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(30)).build();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.tokatlas.ai/v1beta/interactions"))
            .timeout(Duration.ofSeconds(180))
            .header("x-goog-api-key", apiKey)
            .header("Content-Type", "application/json")
            .method("POST", HttpRequest.BodyPublishers.ofString(payload))
            .build();
        HttpResponse<String> response = client.send(
            request, HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() < 200 || response.statusCode() >= 300) {
            throw new IllegalStateException("HTTP " + response.statusCode() + ": "
                + response.body());
        }
        System.out.println(response.body());
    }
}

Complete Python Example ​

Install requests (pip install requests) and set the API_KEY environment variable. The inventory result is demo data. Replace execute with your business service and select a model enabled for your account.

python
import json
import os
import requests

URL = "https://api.tokatlas.ai/v1beta/interactions"
HEADERS = {'x-goog-api-key': os.environ["API_KEY"], 'Content-Type': 'application/json'}
TOOLS = [{'type': 'function',
  'name': 'lookup_stock',
  'description': 'Look up available inventory for a product SKU.',
  'parameters': {'type': 'object',
                 'properties': {'sku': {'type': 'string',
                                        'description': 'Product SKU, for example '
                                                       'DEMO-001'}},
                 'required': ['sku'],
                 'additionalProperties': False}}]


def post(payload):
    response = requests.post(URL, headers=HEADERS, json=payload, timeout=60)
    response.raise_for_status()
    body = response.json()
    # Accept the documented gateway envelope or a direct protocol response.
    data = body.get("data", body)
    if not isinstance(data, dict):
        raise RuntimeError("Unexpected API response")
    if data.get("error"):
        raise RuntimeError(data["error"])
    return data


def execute(name, args):
    if name != "lookup_stock":
        return {"error": "Unknown tool"}
    if not isinstance(args, dict) or set(args) != {"sku"}:
        return {"error": "Expected exactly one sku argument"}
    if not isinstance(args["sku"], str) or not args["sku"].strip():
        return {"error": "sku must be a non-empty string"}
    # Demo fixture only; replace with your inventory service.
    stock = {"DEMO-001": 18}
    if args["sku"] not in stock:
        return {"error": "SKU not found"}
    return {"sku": args["sku"], "available": stock[args["sku"]]}

payload = {"model": "gemini-2.5-flash", "store": True, "tools": TOOLS,
           "input": "Check stock for DEMO-001."}
for _ in range(6):
    reply = post(payload)
    if reply.get("status") in ("failed", "cancelled", "incomplete"):
        raise RuntimeError("Interaction did not complete")
    steps = reply["steps"]
    calls = [s for s in steps if s["type"] == "function_call"]
    if not calls:
        print(json.dumps(steps, ensure_ascii=False, indent=2))
        break
    results = []
    for call in calls:
        result = execute(call["name"], call["arguments"])
        results.append({"type": "function_result", "name": call["name"],
                        "call_id": call["id"], "result": json.dumps(result),
                        "is_error": "error" in result})
    payload = {"model": "gemini-2.5-flash", "store": True, "tools": TOOLS,
               "previous_interaction_id": reply["id"], "input": results}
else:
    raise RuntimeError("Tool round limit reached")

Troubleshooting ​

SymptomCheck
Missing tool resultReturn one result for every call; retain the exact IDs.
Repeated callsAvoid forcing a tool on every round; cap the loop.
Invalid argumentsValidate names and parameters before dispatching.
Tool failureReturn a structured error instead of invented data.
Unsupported optionCheck the selected model and gateway route capabilities.