GEMINI LABEN
ROBOTICS — Gemini Robotics ER 2 が公開プレビューになりました。空間推論・エージェント的なコード実行・複数ロボットの協調に対応しますSTREAMING — gemini-robotics-er-2-streaming-preview は Live API による実時間ストリーミング向けで、音声と映像の双方向入力を扱えますSUNSET — 停止日が近づいています。8月17日に Imagen 系(移行先は gemini-3.1-flash-image)、20日に Grok 4.1 ファミリー、31日に gemini-robotics-er-1.6-preview ですSAMPLING — temperature・top_p・top_k が非推奨になりました。これらを設定として公開しているアプリケーションは、扱いの見直しが要りますLOGS — Interactions API の開発者ログに対応し、AI Studio のダッシュボードから閲覧できるようになりましたMODELS — Gemini 3.1 Pro は依然プレビューです。3.6 Flash は7月21日に GA、3.5 Flash-Lite は大量処理のサブエージェント用途に向きますROBOTICS — Gemini Robotics ER 2 が公開プレビューになりました。空間推論・エージェント的なコード実行・複数ロボットの協調に対応しますSTREAMING — gemini-robotics-er-2-streaming-preview は Live API による実時間ストリーミング向けで、音声と映像の双方向入力を扱えますSUNSET — 停止日が近づいています。8月17日に Imagen 系(移行先は gemini-3.1-flash-image)、20日に Grok 4.1 ファミリー、31日に gemini-robotics-er-1.6-preview ですSAMPLING — temperature・top_p・top_k が非推奨になりました。これらを設定として公開しているアプリケーションは、扱いの見直しが要りますLOGS — Interactions API の開発者ログに対応し、AI Studio のダッシュボードから閲覧できるようになりましたMODELS — Gemini 3.1 Pro は依然プレビューです。3.6 Flash は7月21日に GA、3.5 Flash-Lite は大量処理のサブエージェント用途に向きます
記事一覧/API / SDK
API / SDK/2026-08-08上級

打ち切りは失敗の合図ではありませんでした — ブロッキング挙動を伴う関数呼び出しの設計

呼び出しが返るまで待つ種類のツールをエージェントに持ち込むと、並列化と打ち切りの常識が反転します。サンドボックスで実測した数値とともに、再試行を観測へ振り替える設計をまとめました。

Gemini API206Function Calling17エージェント設計4タイムアウト5冪等性6

プレミアム記事

ロボティクス向けのモデルカードを読んでいて、ある一文で手が止まりました。関数呼び出しが「物理的なロボット動作に合わせたブロッキング挙動」に対応する、という記述です。

実機を持たない私には縁のない話に見えました。読み流しかけて、しかし引っかかりが残りました。

自分の自動化にも、返るまで待つしかない処理がいくつもあるからです。

App Store Connect へのビルド送信。壁紙アセットの一括変換。課金レシートの検証。どれも「呼んだ瞬間に終わる」ものではなく、呼び出し側が待っている間に外の世界が変わっていきます。ロボットアームが動くのと構造は同じでした。

そこで、手元のサンドボックスで測ってみることにしました。結論から書きますと、私がそれまで安全だと思っていた二つの習慣 — 並列化と、余裕を持たせたタイムアウト — は、この種のツールに対しては両方とも逆に働いていました。

「返るまで待つ」ツールは、どこにでもある

ブロッキング挙動という言葉はロボティクス文脈で出てきますが、条件を抽象化すると身近になります。

条件意味個人開発での例
効果が外にある戻り値ではなく、外部の状態が変わることが目的ビルド送信、メール送信、決済確定
取り消せない開始後に呼び出し側から止める手段がないアセット変換ジョブ、通知の配信
重ねられない同じ資源に対して同時に走らせてはいけない同一ファイルの書き換え、在庫の引き当て

三つのうち二つ以上が当てはまるツールを、私は「ブロッキング側」と呼んで別扱いすることにしました。通常のツール(検索、要約、参照)とは設計の前提がまるで違うからです。

通常のツールは、失敗したらもう一度呼べば済みます。ブロッキング側は、もう一度呼ぶことそのものが事故になります。

手元で再現する — 動作を止められないツールの最小ハーネス

実機もクラウド課金も使わずに、この構造だけを取り出したハーネスを書きました。動作の代わりにファイルへ追記し、「同時に走ってはいけない区間」の重なりを数えます。

import asyncio, time
 
class Actuator:
    """物理動作の代役。開始から完了までの間、外から観測すると『動作中』。"""
    def __init__(self):
        self.busy = False
        self.overlaps = 0   # 重ねてはいけない区間が重なった回数
        self.effects = 0    # 外の世界に実際に起きた効果の数
 
    async def move(self, action_id: str, dur: float) -> None:
        if self.busy:
            self.overlaps += 1
        self.busy = True
        try:
            await asyncio.sleep(dur)          # ここが実際の物理動作・外部ジョブ
            self.effects += 1
            with open("effects.log", "a") as f:
                f.write(action_id + "\n")
        finally:
            self.busy = False
 
 
async def blocking_call(act: Actuator, action_id: str, dur: float, timeout: float | None = None) -> str:
    """ツール呼び出し。timeout はクライアント側の待ちを切り上げるだけで、動作自体は止まらない。"""
    task = asyncio.create_task(act.move(action_id, dur))
    if timeout is None:
        await task
        return "ok"
    try:
        # shield が要点。wait_for は通常タスクを cancel するが、
        # 現実の物理動作・外部ジョブは cancel できないため、その非対称性を再現する
        await asyncio.wait_for(asyncio.shield(task), timeout)
        return "ok"
    except asyncio.TimeoutError:
        return "timeout"    # 呼び出しは返る。しかし動作は続いている

asyncio.shield を挟んでいるのが肝でした。asyncio.wait_for は素朴に書くと待っているタスクを取り消します。それでは「打ち切ったら動作も止まった」という、現実には成立しない世界を再現してしまいます。

実機のアームは、こちらが待つのをやめても動き続けます。決済も、ビルドの送信も同じです。shield はその非対称性をコードの上で正直に表現するための一行でした。

ここは実装上の落とし穴でもありました。shield を外したハーネスで最初に測ったとき、二重実行はきれいに0件で並びます。安全な設計ができた証拠に見えました。

実際には、テスト側だけが取り消しに応じていただけです。本番運用に置き換えれば、HTTP リクエストを中断してもサーバー側の処理は進みますし、subprocess を待つのをやめてもプロセスは走り続けます。取り消しが効くのはローカルの await だけでした。

自分の書いた抽象が、現実より都合よく振る舞っていないか。ブロッキング側を扱うときは、まずそこを疑うことをお勧めします。数字が最初から良すぎるときは、たいてい模型の方が甘くできています。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
打ち切りが発火したケースのうち97〜100%は、実際には動作が成功していた(実測3水準)
共有資源を持つツールを4本並列にすると壁時計は1203ms→301msになる一方、重なりが3回発生する
再試行を観測に振り替えると二重実行は30件→0件、追加の待ちは中央値67msで済む
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

API / SDK2026-04-23
Gemini API の Parallel Function Calling を本番で使いこなす — 並列ツール実行の設計パターンと落とし穴
Gemini API の Parallel Function Calling をレスポンス速度と信頼性の両面から本番運用する設計パターンを解説。並列実行の仕様、DAG設計、部分失敗対策、監視までを実装コード付きで詳しく紹介します。
API / SDK2026-08-03
Memory profiles の更新ポリシーを測って選ぶ — 確定値を守るガードが精度を16ポイント下げた記録
Memory Bank の Memory profiles が GA になり、構造化された記憶を後段へ渡せるようになりました。更新ポリシーを3種類つくって同条件で比較したところ、直感的に正しく見えた防御が精度を下げていました。計測コード一式と、フィールド別TTLへ切り替えるまでの記録です。
API / SDK2026-08-02
environment hooks に置いた門番の実測 — 判定は46マイクロ秒、起動は23ミリ秒
Managed Agents の environment hooks に破壊的コマンドのガードを置くまでの記録です。正規表現の denylist が20件中9件を素通りさせた実測から、argv 分解による検出率100パーセントまでの3段階と、判定より500倍重い起動コストの内訳をまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →