OpenAI · GPT-6 Astra

GPT-6 Astra Function Calling 実践 2026:AI に API・DB・カスタムツールを呼ばせる

2026.09.11 · 約 15 分

Function Calling の難所はツールループの誤実装、権限の未分離、Chat Completions に縛られてホストツールへ移行できないことだ。 以下で HTTP API ツールスキーマ、完全なツールループ、読み取り専用 DB パターン、関数ツールとホストツールの比較、決定行列と 7 ステップを示す。

GPT-6 Astra Function Calling ツールループをデバッグする開発者

GPT-6 Astra の Function Calling は AI エージェントの中核だ。モデルが呼び出すツールと引数を決定し、ランタイムが副作用を実行し、結果をモデルに返して推論を続ける。ループが正しければ Astra は自律的に API を叩き、データベースを読み、カスタムロジックを実行できる。誤っていればループが詰まり、ツール権限が暴走する。「Function Calling とは何か」は プロトコル比較 に、「API キーの取り方」は API チュートリアル に譲る。本稿では「動く」から「安全に本番稼動できる」までの 3 つのツールパターンを解説する。

Responses
ツール呼び出しの唯一の経路
function_call
output のイベント型
allowlist
DB ツールのセキュリティ基線
Responses API は必須
Function Calling、ホストツール(Web 検索・コードインタープリタ・Computer Use)、非同期ツールループはすべて Responses API が必要。Chat Completions にホストツールを加えると 400 が返る。本稿のコードはすべてテキスト経路が確立済みの前提で Responses を使う。

ステップ 1:ツールスキーマを定義する

ツールスキーマは「このツールの名前・目的・パラメータ」をモデルに伝える JSON オブジェクトだ。天気 HTTP API を叩く関数ツールの例を示す。

ツールスキーマ定義(HTTP API ツール)
import json
from openai import OpenAI

client = OpenAI()

tools = [
    {
        "type": "function",
        "name": "get_weather",
        "description": "Get current weather for a city via HTTP API.",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string",
                    "description": "City name, e.g. Tokyo, London, Shanghai",
                },
                "unit": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "description": "Temperature unit. Default celsius.",
                },
            },
            "required": ["city"],
            "additionalProperties": False,
        },
    }
]

description は「何をするか」を動詞句で書く。モデルはここを読んでツールを呼ぶか判断する。必須パラメータは required に列挙し、additionalProperties: false で予期しないキーを排除する。複数ツールは同じリストに入れる。モデルが 1 ターンで複数ツールを並列呼び出しすることもあるため、ループは必ず全 tool_call を処理すること。

ステップ 2:完全なツールループ

リクエスト送信 → output の function_call を検出 → 実行 → 結果を input に追加 → 再送function_call が消えるまで while で繰り返す。if で 1 回だけ処理すると最終テキスト回答が届かない。

完全なツールループ(Responses API)
import json
import requests
from openai import OpenAI

client = OpenAI()

def call_weather_api(city: str, unit: str = "celsius") -> dict:
    """Replace with your real HTTP endpoint."""
    url = "https://api.example.com/weather"
    r = requests.get(url, params={"city": city, "unit": unit}, timeout=5)
    r.raise_for_status()
    return r.json()  # e.g. {"city": "Tokyo", "temp": 22, "condition": "sunny"}

# Initial request — model may call tools
response = client.responses.create(
    model="gpt-6-astra",
    input="What is the weather in Tokyo right now?",
    tools=tools,
    reasoning={"effort": "low"},
)

# Tool loop: keep going until model stops calling tools
while True:
    tool_calls = [o for o in response.output if o.type == "function_call"]
    if not tool_calls:
        break  # model is done — final answer is in response.output_text

    tool_results = []
    for call in tool_calls:
        args = json.loads(call.arguments)
        if call.name == "get_weather":
            result = call_weather_api(**args)
        else:
            result = {"error": f"Unknown tool: {call.name}"}
        tool_results.append({
            "type": "function_call_output",
            "call_id": call.call_id,
            "output": json.dumps(result, ensure_ascii=False),
        })

    # Append history + results and continue
    response = client.responses.create(
        model="gpt-6-astra",
        input=response.output + tool_results,
        tools=tools,
        reasoning={"effort": "low"},
    )

print(response.output_text)

実装上の注意点。① response.output は複数の型が混在するリスト。type == "function_call" だけを抽出する。② 続行時は response.output + tool_results を input に渡す。履歴を省くとモデルがコンテキストを失う。③ call_id は tool_call と tool_result で一致させる。④ 戻り値は json.dumps で文字列化する。

セキュリティ:ツールを allowlist で制限し、実行を隔離する
ツールが何をできるかはランタイムが決める。name フィールドを known allowlist で検証し、引数を型チェックし、HTTP ツールにはタイムアウトとドメイン allowlist を設ける。DB ツールは事前定義 SQL のみ実行し、モデル出力を SQL に連結しない。ディスク書き込みやシェル実行を伴うツールはリモート Mac で隔離する。

ステップ 3:読み取り専用データベースツール

安全な DB ツールの 3 要件:読み取り専用権限(INSERT / UPDATE / DELETE を与えない)、パラメータ化クエリ(インジェクション防止)、SQL allowlist(任意クエリを防ぐ)。

読み取り専用 DB ツール(allowlist + パラメータ化)
import sqlite3
from typing import Any

# Only these parameterized queries can be executed — no raw user SQL
ALLOWED_QUERIES: dict[str, str] = {
    "get_order":   "SELECT id, status, total, created_at FROM orders WHERE id = ?",
    "list_orders": "SELECT id, status, total FROM orders WHERE user_id = ? LIMIT 20",
}

def query_db(query_name: str, params: list[Any]) -> list[dict]:
    """Execute an allowlisted, parameterized read-only query.
    Never accepts raw SQL strings from the model.
    """
    sql = ALLOWED_QUERIES.get(query_name)
    if sql is None:
        raise ValueError(f"Query '{query_name}' not in allowlist")
    con = sqlite3.connect("orders.db", check_same_thread=False)
    con.row_factory = sqlite3.Row
    try:
        rows = con.execute(sql, params).fetchall()
        return [dict(r) for r in rows]
    finally:
        con.close()

# Schema exposed to the model
db_tool = {
    "type": "function",
    "name": "query_db",
    "description": "Query the orders DB. Only read-only allowlisted queries.",
    "parameters": {
        "type": "object",
        "properties": {
            "query_name": {
                "type": "string",
                "enum": list(ALLOWED_QUERIES.keys()),
                "description": "Name of the allowlisted query",
            },
            "params": {
                "type": "array",
                "items": {"type": ["string", "number"]},
                "description": "Positional parameters for the query",
            },
        },
        "required": ["query_name", "params"],
    },
}

本番では接続プール、クエリタイムアウト、行数上限の SQL 組み込み、機密フィールドのマスクが必要。モデルに返すのはサマリーであり、テーブル全体の raw dump ではない。

関数ツール vs ホストツール

関数ツール(type: function)ホストツール(OpenAI 運営)
実行場所自前のランタイム(ローカル / リモート Mac)OpenAI インフラ
適用シーンプライベート API・社内 DB・カスタムロジックWeb 検索・ファイル検索・コード実行・shell・Computer Use
開発コストスキーマ・実行関数・ループを自前で実装ツール名を指定するだけ、OpenAI が実行
課金トークンのみトークン + ツール従量費
隔離要件書き込み系は実行環境を隔離OpenAI がサンドボックスを管理

2 種類は同一リクエストで混在可能。ホストツールの結果は自動でコンテキストに入るため手動提出不要。関数ツールの結果は function_call_output で手動提出する。

決定行列

したいこと使うもの理由
社内 REST API を呼ぶ関数ツールプライベートネットワークは OpenAI インフラから到達不可
社内 DB を読む(読み取り専用)関数ツール + SQL allowlistプライベートデータ。アクセス権を自前で管理
公開 Web 情報をリアルタイムで検索ホスト web_search_previewクロールとランキングは OpenAI 任せ
モデルに Python を実行させるホスト code_interpreterOpenAI サンドボックス実行。ローカルリソース不要
モデルにデスクトップ / ブラウザを操作させるホスト computer_use + 隔離 Mac可視デスクトップが必要。誤操作防止のため隔離
ディスク書き込みを伴う shell コマンドを実行関数ツール + リモート Mac 隔離書き込み権限は破棄可能な環境に限定

A — 個人開発・プロトタイプ: ローカル + 関数ツール(HTTP API、ディスク非書き込み)。スキーマとループを確立し call_id をログ。単一ツールループを安定させてから複数ツールへ。

B — 小チーム・プロダクト: 関数ツールは内部サービスに token 認証でマウント。DB ツールは読み取り専用 + 接続プール + クエリタイムアウト。ホストツールはタスク種別に応じて有効化。ツール実行ロジックはユニットテストでカバー。

C — エンタープライズ: 関数ツールは API ゲートウェイ経由で監査ログ付き。DB は読み取り専用レプリカ + 行レベルセキュリティ。Computer Use は破棄可能な隔離 Mac ノードで実行。ノード月額は 料金ページ、アカウントは ヘルプセンター

よくある失敗

  1. ループを 1 回だけ実行(if を使う):最終テキスト回答が届かない。
  2. 履歴なしで結果を提出:input に tool_results だけ渡し、モデルがコンテキストを失う。
  3. モデル出力を SQL / シェルに直接連結:allowlist + パラメータ化クエリで防ぐ。
  4. HTTP ツールのタイムアウトなし:下流サービスがハングするとエージェント全体が止まる。
  5. ツールが大量データを返す:結果がコンテキストに入り 272K 升档料金を誘発。

アクションプラン:7 ステップ

  1. まずテキスト経路が通っていることを確認(API チュートリアル参照)。
  2. 最初の関数ツールスキーマを書く。description を動詞句に、required を設定し、additionalProperties: false。
  3. ツール実行関数を実装。HTTP ツールにタイムアウト、DB ツールに allowlist + パラメータ化クエリ。
  4. tools パラメータ付きで Responses リクエストを送り、response.output に function_call が現れることを確認。
  5. while True ループを実装。call_id を一致させて function_call_output を提出し、履歴を input に含める。
  6. ホストツール(web_search、code_interpreter)が必要なら追加。その結果は手動提出不要。
  7. ディスク書き込み・コマンド実行・ブラウザ操作のツールは隔離リモート Mac へ移し、セッション終了後に破棄。

FAQ

Function Calling は Responses API 必須か?

はい。ツール呼び出し・ホストツール・非同期ループは Responses API が必要です。

1 リクエストで定義できるツール数は?

厳密な小さい上限はないが、ツールが増えるほどプロンプトトークンコストが増える。タスクに必要なものだけを渡す。

SQL インジェクションを防ぐには?

? プレースホルダーのパラメータ化クエリと SQL allowlist を組み合わせる。モデル出力を SQL に直接連結しない。

関数ツールとホストツールの使い分けは?

プライベート API・社内 DB・カスタムロジックは関数ツール。Web 検索・コード実行・Computer Use はホストツール。

ツール呼び出し後の最終回答はストリーミング可能か?

可能です。非ストリーミングのツールループを安定させてから stream=True を加えること。

まとめ

GPT-6 Astra Function Calling の要点:明確な description を持つスキーマ、履歴付きで結果を提出する while ループ、allowlist + パラメータ化クエリの DB ツール、そして書き込み系ツールの隔離実行。リモート Mac ノードは レンタルページ料金ページ、アカウントは ヘルプセンター

関連記事

実際の API を呼ぶツールは隔離 Cloud Mac で動かす

HTTP API の呼び出しはローカルでもよい。ただしディスク書き込み・リポジトリ編集・ブラウザ操作を伴うツールは日常デスクトップと同居させない。リモート Mac はセッション単位でワークスペースを隔離する。

今すぐ注文 · 料金を見る

GPT-6 Astra Function Calling

実際の API を呼ぶツールは隔離 Cloud Mac で動かす

Cloud Mac · isolated agent runtime

今すぐ注文
Mac 今すぐ注文