跳至內容
English
Gemini Messages

工具呼叫 ​

將模型提出的工具請求交由應用程式執行,再回傳結果以繼續對話。

POST /v1beta/interactions

自訂函式由您的應用程式執行。模型提供函式名稱和參數,應用程式負責查詢資料並回傳結果。

路由前提

本頁為 Interactions 協定範例。目前本地網關程式只註冊 Gemini generateContent 路由,沒有註冊 /v1beta/interactions;只有部署環境另外提供此路由時才能執行本頁範例。一般 Gemini 客戶端請見 Gemini CLI,圖像生成請見 Nano Banana。若收到 404,不要只替換 URL:兩種協定的請求與回包不同。

請求與驗證 ​

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."
}

工具呼叫格式 ​

以下為呼叫項目示意;ID 與參數應取自實際回應。

json
{
  "type": "function_call",
  "id": "call_example",
  "name": "lookup_stock",
  "arguments": {
    "sku": "DEMO-001"
  }
}
  • 讀取 steps 中的 function_call,其 arguments 為物件。回傳 function_result 時,call_id 須等於該呼叫的 id。

  • 此範例需要儲存互動狀態。每輪傳入最新的 previous_interaction_id,並重新傳送 tools。若使用 store: false,須保留完整互動歷史,包括思考與簽章資料。

  • 請使用此處的 Interactions 格式,勿混用 generateContent 的 functionDeclarations 或 functionResponse。串流時,完整組合步驟後才執行工具。

多語言首輪請求 ​

這組範例會取得模型的工具呼叫要求,尚未執行工具。讀取下方完整流程,以真實呼叫 ID 回傳工具結果並繼續對話。

執行方式見多語言範例說明。先設定 API_KEY,並替換模型、檔案網址及 ID 占位值;四種方式會顯示相同請求的原始回應。

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());
    }
}

完整 Python 範例 ​

安裝 requests(pip install requests),並設定 API_KEY 環境變數。庫存結果為示範資料;請將 execute 替換為業務服務,並選用帳戶已開通的模型。

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")

常見問題 ​

狀況檢查方式
缺少工具結果每個呼叫都須回傳結果,保留原始 ID。
重複呼叫避免每輪強制使用工具,並限制循環次數。
參數無效執行前驗證函式名稱與參數。
工具執行失敗回傳結構化錯誤,勿編造資料。
選項不支援檢查模型與閘道路由的能力。

相關主題 ​