Tool Calling
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
POST https://api.tokatlas.ai/v1beta/interactions
x-goog-api-key: YOUR_API_KEY
Content-Type: application/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.
{
"type": "function_call",
"id": "call_example",
"name": "lookup_stock",
"arguments": {
"sku": "DEMO-001"
}
}Read
function_callentries insteps;argumentsis an object. Returnfunction_resultwithcall_idequal to the call’sid.This example requires stored interactions. Pass the latest
previous_interaction_idand resendtoolseach round. Withstore: false, preserve the full interaction history, including thought/signature data.Use the Interactions schema shown here, not
generateContentfields such asfunctionDeclarationsorfunctionResponse. 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.
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
}'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)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());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.
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
| Symptom | Check |
|---|---|
| Missing tool result | Return one result for every call; retain the exact IDs. |
| Repeated calls | Avoid forcing a tool on every round; cap the loop. |
| Invalid arguments | Validate names and parameters before dispatching. |
| Tool failure | Return a structured error instead of invented data. |
| Unsupported option | Check the selected model and gateway route capabilities. |
