GEMINI LABEN
OUTAGE — Geminiが過去最大級の障害(error 1076/1099)から回復へ。エンジニアリングチームの緩和策で影響は縮小中DAILY-BRIEF — 新エージェント「Daily Brief」が登場。夜間にinbox・カレンダー・タスクを分析し、朝のパーソナルダイジェストを生成GEMINI-OMNI — Geminiと生成メディアモデルを統合した動画AI「Gemini Omni」。プロンプトから一貫性のある高品質動画を生成ENTERPRISE — Gemini Enterpriseで3.5 Flashが6/8からデフォルト固定に。機能管理トグルは廃止され全ユーザーで有効DEPRECATION — 画像previewモデル(3.1-flash-image/3-pro-image)は6/25に停止。GA版への移行はお早めにFILE-SEARCH — File Searchがマルチモーダル検索に対応。gemini-embedding-2で画像をネイティブに埋め込み・検索OUTAGE — Geminiが過去最大級の障害(error 1076/1099)から回復へ。エンジニアリングチームの緩和策で影響は縮小中DAILY-BRIEF — 新エージェント「Daily Brief」が登場。夜間にinbox・カレンダー・タスクを分析し、朝のパーソナルダイジェストを生成GEMINI-OMNI — Geminiと生成メディアモデルを統合した動画AI「Gemini Omni」。プロンプトから一貫性のある高品質動画を生成ENTERPRISE — Gemini Enterpriseで3.5 Flashが6/8からデフォルト固定に。機能管理トグルは廃止され全ユーザーで有効DEPRECATION — 画像previewモデル(3.1-flash-image/3-pro-image)は6/25に停止。GA版への移行はお早めにFILE-SEARCH — File Searchがマルチモーダル検索に対応。gemini-embedding-2で画像をネイティブに埋め込み・検索
記事一覧/API / SDK
API / SDK/2026-06-12中級

Gemini Interactions API の outputs が使えなくなったら — 6月6日廃止の旧スキーマから steps へ移行する手順

2026年6月6日、Gemini Interactions API のレガシー outputs スキーマが削除されました。AttributeError・無言の空応答・履歴の400エラーという症状別に、steps と response_format への書き換え手順を整理します。

gemini-api221interactions-api2breaking-changesmigration3steps-schemaresponse-format

6月6日を境に、Gemini Interactions API のレガシースキーマ(応答を outputs 配列で返す形式)が完全に削除されました。5月中は Api-Revision ヘッダーで旧形式へ一時的に戻せましたが、現在はこのヘッダー自体が無視されます。つまり「いったん戻して様子を見る」という選択肢はすでになく、動かなくなったコードは新しい steps スキーマへ書き換えて前へ進むしかありません。

私自身は5月の終わり、iOS の壁紙アプリ4本の更新作業と並行して、App Store のレビューを毎朝要約して通知する自分用ツールをこの新スキーマへ移行しました。コード量にして百行に満たない小さなツールでしたが、それでも「ドキュメント通りに直したはずなのに最後の出力が取れない」という場面が二度ありました。個人開発の自動化ツールは「動いているから触らない」が積み重なりやすく、今回のような廃止期限で初めて壊れて気づいた方も多いのではないでしょうか。

そこで、移行作業を「壊れ方の症状」から逆引きできる形で並べ直しました。unary(一発呼び出し)、ストリーミング、構造化出力、自前の会話履歴管理の順に、書き換え前後のコードを比べていきます。

何が起きたのか — 三段階で進んだスキーマ切り替え

公式の移行ガイド(Interactions API: Breaking changes migration guide)によると、切り替えは次の三段階で進みました。

  • 5月6日(オプトイン開始): 新スキーマ対応 SDK が公開され、REST では Api-Revision: 2026-05-20 ヘッダーを付けたリクエストのみ新形式になりました
  • 5月20日(デフォルト反転): ヘッダーなしのリクエストが新スキーマへ切り替わりました。Api-Revision: 2026-05-06 を付ければ旧形式に戻せる猶予期間です
  • 6月6日(完全廃止): 旧スキーマが削除され、Api-Revision ヘッダーは無視されるようになりました

変更の柱は2つあります。1つ目は応答の outputs 配列が、種別判別子(type discriminator)付きの steps 配列に置き換わったこと。2つ目は response_mime_type が廃止され、出力形式の指定が多態的な response_format に集約されたことです。

1つ、実際にガイドを読み込んで戸惑った点を共有しておきます。本文には「Python 1.76.0 以降 / JavaScript 1.53.0 以降に上げれば自動的に新スキーマになる」とある一方、タイムライン表には「Python 2.0.0 以降 / JS 2.0.0 以降」と書かれていて、要求バージョンの記載が揺れています。私は深追いせず最新安定版まで一気に上げる判断をしました。移行後のコードが新形式しか想定しない以上、SDK 側も新形式しか返さないバージョンに揃えてしまうほうが、中途半端な版で新旧が混ざるより事故が少ないという考え方です。

なお、5月7日以降に追加された新機能は steps 形式の応答にしか現れない、という記載もガイドにあります。旧形式のまま粘るメリットは、廃止日よりずっと前に実質なくなっていました。モデルIDやAPIリビジョンのような「決め」をコードに固定して差分を検出する運用は、Gemini APIの設定ドリフトを止める — モデルID・安全設定をコード化して環境差を検出するでも書いたとおり、こういう廃止イベントのたびに効いてきます。

症状から切り分ける — 「落ちる」より「無言で空になる」が厄介

手元のコードがどう壊れているかで、直す場所が決まります。私が確認した壊れ方は3通りでした。

  • unary 呼び出しが例外で落ちる: Python なら AttributeError: 'Interaction' object has no attribute 'outputs'、生 REST なら応答 JSON に outputs キーがなく KeyError になります。一番分かりやすい壊れ方です
  • ストリーミングが例外なしで空になる: イベント名が content.delta から step.delta に変わったため、旧イベント名でフィルタしているハンドラは「該当イベントなし」として静かに素通りします。しかも判別フィールド自体が event_type から type に変わっており、二重の理由で一致しません。バッチ処理だと「成功扱いなのに成果物が空」という形で並ぶので、発見が遅れます。私のレビュー要約ツールも検証環境でこの状態になり、空の Slack 通知が3日分並んでいるのを見てようやく気づきました
  • 自前の会話履歴管理が 400 を返す: 前ターンの outputs を次の input に詰め直す実装は、新形式の応答に outputs が存在しないため履歴が空になるか、形式不一致でリクエストが拒否されます

例外が出るケースより、静かに空になるケースのほうが運用上は厄介です。応答が空になる症状つながりでは、スキーマ変更とは別原因のGemini 2.5/3 で本文が空なのに finish_reason が MAX_TOKENS になるときの原因と対処もあわせて確認しておくと、切り分けが早くなります。

基本の書き換え — outputs[0].text は steps の model_output へ

まず unary 呼び出しの最小修正です。旧コードはこう書いていました。

# Before: 6月5日まで動いていた旧スキーマの読み方
from google import genai
 
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
 
interaction = client.interactions.create(
    model="gemini-3-flash-preview",
    input="このアプリレビューを1行で要約してください: ...",
)
 
print(interaction.outputs[0].text)  # 6月6日以降: AttributeError

新スキーマでは応答が steps 配列になり、思考(thought)・ツール呼び出し・モデル出力が時系列で並びます。

# After: 新 steps スキーマの読み方
from google import genai
 
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
 
interaction = client.interactions.create(
    model="gemini-3-flash-preview",
    input="このアプリレビューを1行で要約してください: ...",
)
 
# steps には thought / function_call / model_output が混在し得る。
# 本文が欲しいだけなら model_output ステップに絞って取り出すのが安全。
final_text = ""
for step in interaction.steps:
    if step.type == "model_output":
        final_text = step.content[0].text
 
print(final_text)
# 期待される出力例:
# 星1の主因はダーク表示時の白画面。次回更新での修正要望が2件。

公式サンプルは interaction.steps[-1].content[0].text と末尾参照で書かれていますが、私は type == "model_output" で絞る書き方に落ち着きました。理由は2つあります。まず、思考過程が応答に含まれる設定では先頭側に thought ステップが入るため、steps[0] 参照は本文ではないものを掴みます(私が最初に引っかかったのはここでした)。次に、function calling で statusrequires_action のときは最後のステップが function_call になるため、末尾参照でも本文とは限りません。

もう1つ、地味に重要な仕様差があります。POST /interactions の応答に含まれるのは出力系ステップのみですが、GET /interactions/{id} で同じインタラクションを再取得すると、user_input ステップを含む全タイムラインが返ります。インデックス位置を前提にしたコードは、POST 直後は動くのに再取得処理では1つずれる、という分かりにくい不整合を起こします。種別で絞っておけばどちらの応答でも同じコードが使えます。

ストリーミングはイベント名の総入れ替え

ストリーミングは修正箇所がはっきりしています。新旧のイベント対応は次のとおりです。

  • interaction.startinteraction.created
  • content.startstep.start
  • content.deltastep.delta
  • content.stopstep.stop
  • interaction.completeinteraction.status_updatestatus: "completed"
  • errorinteraction.status_updatestatus: "error"

あわせて、イベントを判別するフィールド名が event_type から type に変わっています。書き換え後の最小形はこうなります。

# After: 新スキーマのストリーミング読み取り
for event in client.interactions.create(
    model="gemini-3-flash-preview",
    input="昨夜のクラッシュレポートの傾向を3行で説明してください。",
    stream=True,
):
    # 旧: chunk.event_type == "content.delta"
    if event.type == "step.delta":
        if event.delta.type == "text":
            print(event.delta.text, end="", flush=True)

function calling をストリーミングで使っている場合は、もう一段の変更があります。step.start イベントが関数名を運び、引数は step.deltaarguments_delta として部分的な JSON 文字列で流れてくるため、受信側で連結してからパースする必要があります。unary では完全な function_call オブジェクトが一度に届くので、この差はガイドの中でも見落としやすい段落だと感じます。

終端処理にも1つ注意があります。移行ガイドの廃止イベント一覧では interaction.completeinteraction.status_update に置き換えとされている一方、同じページの新スキーマの SSE サンプルには interaction.complete が残っています。ドキュメント内で記述が揺れている間は、終端を単一のイベント名に依存させず、step.stop と status 系イベントのどちらが来てもストリームを閉じられる寛容なハンドラにしておくのが安全だと考えています。実際に私のツールでも両対応にしてあり、どちらのイベントで閉じたかをログに残して観察を続けています。

response_mime_type は廃止 — 構造化出力は response_format に集約

構造化出力(JSON モード)を使っているコードは、リクエスト側の書き換えが必要です。

# Before: response_mime_type と素の JSON スキーマを並べる旧形式
interaction = client.interactions.create(
    model="gemini-3-flash-preview",
    input="このレビューを分類してください: 起動直後に落ちます。星1。",
    response_mime_type="application/json",
    response_format={
        "type": "object",
        "properties": {"sentiment": {"type": "string"}},
    },
)
# After: type 判別子つき response_format に mime_type と schema を内包する
interaction = client.interactions.create(
    model="gemini-3-flash-preview",
    input="このレビューを分類してください: 起動直後に落ちます。星1。",
    response_format={
        "type": "text",
        "mime_type": "application/json",
        "schema": {
            "type": "object",
            "properties": {"sentiment": {"type": "string"}},
        },
    },
)
 
print(interaction.steps[-1].content[0].text)
# 期待される出力例: {"sentiment": "negative"}

ポイントは、旧 response_format に直接渡していた JSON スキーマが schema キーの中へ一段深くネストされることです。response_mime_type の行を消すだけ・キー名を変えるだけの機械的な置換では直りません。画像生成の設定も同じ統合の対象で、generation_config の中にあった image_config(アスペクト比やサイズ)は response_formattype: "image" エントリへ移動しました。テキストと画像など複数モダリティを同時に要求する場合は、response_format をオブジェクトではなく配列にします。

自前の会話履歴と、見落としやすい3つの細部

最後に、規模は小さいものの直し忘れやすかった点を3つ挙げます。

  • 会話履歴の持ち回り: クライアント側で履歴を管理する stateless 構成では、これまで応答の outputs を次のリクエストの input に渡していました。新形式では steps 配列をそのまま input へ渡し、新しいユーザー発話を user_input ステップとして末尾に足します
  • 引用(annotations)の形式変更: テキスト中の出典情報が type: "url_citation" の判別子と title フィールドを持つ形になりました。Google Search グラウンディングの引用を自前でレンダリングしている場合は、描画側のコードも直す必要があります
  • 検索結果フィールドの改名: google_search_result ステップの結果は result.rendered_content ではなく result.search_suggestions から読みます。グラウンディング結果を DB に保存している構成では、保存スキーマの不一致が静かに進行するので早めの修正をおすすめします

このあたりは一度に全部直そうとせず、症状が出ている経路から順に潰すほうが確実でした。なお、モデル世代自体の移行(3.1 から 3.2 など)を同時に進めている場合は、Gemini 3.2 API 実装ガイド — 正しいモデルID・3.1 からの移行と本番チェックポイントで書いた本番チェックポイントと作業を分けて、スキーマ移行とモデル移行を別コミットにしておくと切り戻しが楽になります。

まとめ — まず .outputs を grep で棚卸しする

最初の一歩としておすすめしたいのは、修正よりも先にリポジトリ全体へ grep -rn "\.outputs" --include="*.py"(JavaScript なら .outputscontent.delta の両方)をかけて、当たり所を一覧にすることです。そのうえで本稿の症状3分類 — 例外で落ちる unary、無言で空になるストリーミング、形式不一致になる履歴管理 — のどれに該当するかを1ファイルずつ確認していけば、書き換え自体は小さなツールなら30分前後で終わります。2014年から個人開発の運用ツールを少しずつ増やしてきた身として、こうした廃止対応は「気づいた日のうちに棚卸しまで終わらせる」のが結局いちばん安上がりだと感じています。同じように6月6日以降の静かな空出力に気づいた方の参考になれば幸いです。

シェア

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

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

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

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

API / SDK2026-05-01
AI Studio で動いていたコードを Vertex AI に移したら何が変わったか — 個人開発者の移行作業ログ
AI Studio の API キーで動いていた既存コードを Vertex AI 側に移行した際の、SDK 初期化・認証・レスポンス形式の差分を、実際のコードログとともに整理しました。
API / SDK2026-03-30
Gemini Deep Research Agent API 活用ガイド:自動リサーチからレポート生成まで
Gemini Deep Research AgentでWeb検索から分析・レポート生成まで自動化。Interactions APIの使い方と実装パターンを解説します。
API / SDK2026-06-12
Gemini の画像生成 preview モデルが 6月25日に停止します — GA 版への移行で確認したコード差分と検証手順
6月25日に停止する gemini-3.1-flash-image-preview / gemini-3-pro-image-preview から GA 版へ移行した作業記録です。モデルIDの確認手順、Python のコード差分、停止前にしかできない回帰チェック、切り替え順序まで実例で整理しました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →