SPB Git forge

spb/doc-api

Public
2commits 1branches 0releases
15.7 MBsize
maindefault branch
13 days agolast push
Python 88.3% TypeScript 7.6% Shell 4.1%
39.8 KB · 421 lines markdown
Rendered Raw Blame History
1# Gemini Interactions API, managed agents, Environments API and `dynamic/*`23**Status:** DOCUMENTED + LIVE_VERIFIED (2026-09-18 run — see "Live verification" section at the end)45**Sources** (offline copies under `sources/gemini/`, retrieved 2026-09-18):6- Reference: https://ai.google.dev/api/interactions (v1beta, 186 KB, incl. Credentials CRUD and the `InteractionSseEvent` union), https://ai.google.dev/api/interactions-api (same surface, alternate rendering), https://ai.google.dev/api/interactions-api-v1 (stable v1 subset), https://ai.google.dev/api/environments, https://ai.google.dev/api/all-methods7- Discovery document `generativelanguage` v1beta rev. 20260918 (`sources/gemini/discovery-v1beta.json`): resources `environments`, `environments.files.media`, `dynamic`8- Guides: https://ai.google.dev/gemini-api/docs/interactions-overview, …/interactions, …/streaming, …/background-execution, …/interactions-breaking-changes-may-2026, …/migrate-to-interactions, …/agents, …/managed-agents-quickstart, …/antigravity-agent, …/deep-research, …/custom-agents, …/agent-environment, …/agent-credentials, …/agent-hooks, …/webhooks, …/aistudio-agents, …/flex-inference, …/priority-inference, …/pricing (section "Pricing for agents"), …/api-versions9- Model pages: …/models/deep-research-preview-04-2026, deep-research-max-preview-04-2026, deep-research-pro-preview-12-2025, antigravity-preview-05-202610- SDK surfaces: `google-genai` 2.24 (`google/genai/_gaos/{interactions,agents,environments,files,credentials,triggers,webhooks}.py`), `@google/genai` 2.23 (`dist/genai.d.ts` classes `Interactions_2`, `Agents_2`, `Environments_2`, `Credentials_2`, `Triggers_2`, `Webhooks_2`)11- Live model list `sources/gemini/models-api-raw.json` (agents visible on this key: `deep-research-preview-04-2026`, `deep-research-max-preview-04-2026`, `deep-research-pro-preview-12-2025`, `antigravity-preview-05-2026`, `antigravity-preview-09-2026`)1213**Last verified:** 2026-09-18 (docs only — no live call in this document; see the final section)1415Machine-readable twins: `generated/fragments/parameters/gemini-interactions.json` (258 parameter records), `generated/fragments/streaming-events/gemini-interactions.json` (39 event records), `tmp/gemini-parts/interactions-endpoints.json` (40 endpoint records), `tmp/gemini-parts/interactions-objects.json` (67 object records).1617---1819## 1. What it is, and when to use it instead of `generateContent`2021The **Interactions API** (`POST /v1beta/interactions`) is Google's newer, stateful surface for Gemini. Since June 2026 the docs call it "Generally Available and recommended for all new projects" while `generateContent` is "now considered legacy" but fully supported. One endpoint serves both **models** (`"model": "gemini-3.8-flash"`) and **agents** (`"agent": "deep-research-preview-04-2026"`, `"agent": "antigravity-preview-09-2026"`, or the id of a custom agent you saved). Every call creates an **Interaction** resource whose `steps[]` is the chronological timeline of the turn (thoughts, tool calls/results, `model_output`).2223| Aspect | `models/*:generateContent` (legacy) | Interactions API |24|---|---|---|25| Path | `POST /v1beta/models/{model}:generateContent` (+ `:streamGenerateContent`) | `POST /v1beta/interactions` (stream via body `stream: true`); stable `POST /v1/interactions` |26| Casing | camelCase (`generationConfig`, `systemInstruction`) | **snake_case** everywhere (`generation_config`, `previous_interaction_id`) — camelCase fields are rejected with 400 |27| Request shape | `contents[] { role, parts[] }` | `input`: string \| Content \| Content[] \| Step[] |28| Response shape | `candidates[].content.parts[]` | `steps[]` typed by `type` (`model_output`, `thought`, `function_call`, `google_search_call`…) + `usage` |29| State | stateless only | optional server-side state: `previous_interaction_id` (default `store=true`) |30| Long-running | none (client timeout ~60 s) | `background: true` + polling `GET /interactions/{id}` or resumable SSE (`?stream=true&last_event_id=`) + cancel |31| Agents | none | Deep Research, Antigravity (Linux sandbox), custom managed agents, cron **triggers** |32| Sandboxes | none | `environment` param + Environments API (files PUT/GET, egress allowlist, credentials) |33| Structured output | `responseMimeType` / `responseSchema` | polymorphic `response_format` (`text`/`image`/`audio`/`video`) |34| Tools | `tools[].functionDeclarations`, `googleSearch`, … | flat `tools[] {type: function \| google_search \| google_maps \| code_execution \| url_context \| file_search \| mcp_server \| computer_use}` |35| Thinking | `thinkingConfig.thinkingBudget/includeThoughts` | `generation_config.thinking_level` (minimal/low/medium/high) + `thinking_summaries` (auto/none); `thought` steps with `signature` |36| Tiers | — | `service_tier`: flex (-50 %), standard, priority (+75–100 %) |37| Webhooks | Batch/video LROs | `webhook_config` per request (dynamic) or static webhooks with `interaction.*` events |38| Not (yet) available | — | Batch API, automatic function calling (Python), explicit caching (implicit caching works), custom safety settings, remote MCP on Gemini 3 models |3940Use `generateContent` when you need Batch, explicit caching, custom safety settings, or an SDK/language not yet covered. Use Interactions for anything agentic, multi-turn, long-running, sandboxed, or when you want new features (all new models/tools launch there first).4142---4344## 2. Architecture4546```mermaid47flowchart LR48  subgraph Client49    C[App / SDK<br/>google-genai · @google/genai · curl]50  end51  subgraph API["generativelanguage.googleapis.com"]52    I["POST /v1beta/interactions<br/>GET · DELETE · /cancel"]53    ST[(Stored Interactions<br/>store=true · 55 d paid / 1 d free)]54    A["/v1beta/agents<br/>custom agent defs"]55    T["/v1beta/triggers<br/>cron runs"]56    CR["/v1beta/credentials<br/>write-only secrets"]57    W["/v1/webhooks<br/>static endpoints"]58  end59  subgraph Runtime60    M[Gemini model]61    DR[deep-research-* agent]62    AG[antigravity-* agent<br/>harness]63    TOOLS[server tools<br/>google_search · url_context · code_execution<br/>file_search · google_maps · mcp_server]64  end65  subgraph Sandbox["Environment (Linux sandbox, 4 vCPU / 16 GB)"]66    FS[(/workspace files)]67    PX[egress proxy<br/>allowlist + header/credential injection]68    HK[.agents/hooks.json<br/>pre/post tool hooks]69  end70  C -- "model | agent, input, tools, previous_interaction_id, background, stream" --> I71  I <--> ST72  I --> M73  I --> DR74  I --> AG75  M --> TOOLS76  DR --> TOOLS77  AG --> TOOLS78  AG <--> FS79  AG --> HK80  FS --> PX --> Internet((Internet / MCP servers))81  CR -. "referenced by id" .-> PX82  A -. "agent: <id>" .-> I83  T -- "CreateInteractionRequest on schedule" --> I84  I -- "SSE: interaction.created → step.start/delta/stop → interaction.completed" --> C85  I -- "background: id → poll GET / stream GET?stream=true&last_event_id" --> C86  I -- "webhook_config / static webhooks: interaction.completed|failed|cancelled|requires_action" --> W --> C87  C -- "PUT /upload/v1beta/environments/{id}/files/{path}<br/>GET .../files/{path}?alt=media" --> FS88  M -- "function_call step (status requires_action)" --> C89  C -- "input: function_result + previous_interaction_id" --> I90```9192Chaining: the `id` of a completed interaction goes into `previous_interaction_id` of the next request; only the conversation history is carried over — `tools`, `system_instruction`, `generation_config` are interaction-scoped and must be re-sent. Chaining onto an `in_progress` interaction returns 400. Managed agents additionally need `environment` (the `environment_id` from the previous response) to keep the sandbox.9394---9596## 3. Resource tree (every endpoint)9798Host `https://generativelanguage.googleapis.com`. Auth: header `x-goog-api-key: $GEMINI_API_KEY` (never in the URL). Optional header `Api-Revision: 2026-05-20` (current schema; `2026-05-07` = legacy schema, removed 2026-06-08).99100| Family | Method & path | Purpose | Notes |101|---|---|---|---|102| interactions | `POST /v1beta/interactions` | create (model or agent) | body `stream: true` → SSE; `background: true` → async |103| interactions | `GET /v1beta/interactions/{id}` | get / poll | `?stream=true[&last_event_id=]` resumes SSE |104| interactions | `DELETE /v1beta/interactions/{id}` | delete stored record | empty body; later GET → 404 |105| interactions | `POST /v1beta/interactions/{id}/cancel` | cancel background run | one guide shows `…/{id}:cancel` (UNVERIFIED alias) |106| interactions (v1) | `POST /v1/interactions`, `GET/DELETE /v1/interactions/{id}`, `POST /v1/interactions/{id}/cancel` | stable subset | reference page renders `/v1beta/` URLs (doc bug); path from api-versions guide; SDK `http_options.api_version="v1"` |107| credentials | `POST /v1beta/credentials` | create secret | types `bearer_token`, `oauth2`, `environment_variable` |108| credentials | `GET /v1beta/credentials` | list | `page_size` (50, max 1000), `page_token` |109| credentials | `GET /v1beta/credentials/{id}` | get metadata | never returns secrets |110| credentials | `PATCH /v1beta/credentials/{id}` | rotate | body must repeat `type`; `?update_mask=` |111| credentials | `DELETE /v1beta/credentials/{id}` | delete | fails if referenced by active triggers |112| agents | `POST /v1beta/agents` | create custom managed agent | `id`, `base_agent`, `agent_config`, `system_instruction`, `tools`, `base_environment` |113| agents | `GET /v1beta/agents` | list | `page_size`/`page_token` (SDK) |114| agents | `GET /v1beta/agents/{id}` | get | |115| agents | `DELETE /v1beta/agents/{id}` | delete | existing envs/interactions unaffected |116| triggers | `POST /v1beta/triggers` | cron-scheduled agent run | `schedule`, `time_zone`, `interaction` |117| triggers | `GET /v1beta/triggers`, `GET /v1beta/triggers/{id}` | list / get | |118| triggers | `PATCH /v1beta/triggers/{id}` | pause/resume | `{"status": "paused" \| "active"}` |119| triggers | `DELETE /v1beta/triggers/{id}` | delete | history kept |120| triggers | `POST /v1beta/triggers/{id}/executions` | run now | |121| triggers | `GET /v1beta/triggers/{id}/executions` | executions (status, `interaction_id`, `environment_id`) | |122| webhooks | `POST/GET /v1/webhooks`, `GET/PATCH/DELETE /v1/webhooks/{id}`, `POST /v1/webhooks/{id}/rotate_secret` | static project webhooks | **documented on `/v1`**; shared with Batch/video; SDK also has `ping` (path UNVERIFIED) |123| environments | `POST /v1beta/environments` | create sandbox | discovery flatPath `environments:create`; body `sources[]`, `network`, `from_environment` |124| environments | `GET /v1beta/environments` | list | `page_size`/`page_token` (REST page) vs `pageSize`/`pageToken` (discovery, guide curl) |125| environments | `GET /v1beta/environments/{id}` | get | `status: active \| expired` |126| environments | `DELETE /v1beta/environments/{id}` | delete | otherwise 7-day idle TTL |127| environments | `GET /v1beta/environments/{env}/files[/{path}]` | list dir / file metadata / **download** | `?alt=media` → bytes or POSIX tar; `?recursive=true`; `page_size` 100 (max 1000) |128| environments | `PUT /upload/v1beta/environments/{env}/files/{path}` | upload / extract archive | `?overwrite=true`, `?extract=true`; resumable via `X-Goog-Upload-*`; max 2 GiB; without `/upload/` prefix → 400 |129| environments (legacy) | `GET /v1beta/files/environment-{env}:download?alt=media` | whole-sandbox tar | superseded by `…/files?alt=media` |130| dynamic | `POST /v1beta/dynamic/{dynamicId}:generateContent` | GenerateContentRequest on a `dynamic/*` resource | discovery-only, semantics undocumented |131| dynamic | `POST /v1beta/dynamic/{dynamicId}:streamGenerateContent` | streamed variant | same |132133SDK mapping (google-genai ≥ 2.3 / @google/genai ≥ 2.3): `client.interactions.{create,get,delete,cancel}`, `client.agents.{create,list,get,delete}`, `client.credentials.{create,list,get,update,delete}`, `client.triggers.{create,list,get,update,delete,run,list_executions}`, `client.webhooks.{create,list,get,update,delete,ping,rotate_signing_secret}`, `client.environments.{list,get,delete,create}` + `client.environments.files.{list,download,upload}`. Java: `com.google.genai.gaos.*`.134135---136137## 4. The Interaction object and its lifecycle138139Top-level response fields: `id` (`v1_Chd…`), `object: "interaction"`, `status`, `model` **or** `agent`, `agent_config`, `environment_id` (only when an environment was requested), `steps[]`, `usage`, `errors[] {code, message}`, `created`, `updated`, plus echoes of the request (`input`, `tools`, `system_instruction`, `response_format`, `generation_config` (input only), `previous_interaction_id`, `labels`, `service_tier`, `webhook_config`). SDKs add the convenience property `output_text`.140141`POST` returns only the model-generated steps; `GET` returns the full timeline including the initial `user_input` step.142143```mermaid144stateDiagram-v2145  [*] --> queued: background=true146  [*] --> in_progress147  queued --> in_progress148  in_progress --> requires_action: function_call step emitted149  requires_action --> in_progress: next POST with function_result + previous_interaction_id150  in_progress --> completed151  in_progress --> incomplete: max_output_tokens / max_total_tokens budget hit152  in_progress --> failed153  in_progress --> cancelled: POST /interactions/{id}/cancel154  completed --> [*]155  incomplete --> [*]: continue with previous_interaction_id (+ environment)156  failed --> [*]157  cancelled --> [*]158```159160| `status` | Meaning |161|---|---|162| `queued` | waiting for processing (background) |163| `in_progress` | executing (model, tools, sandbox) |164| `requires_action` | paused for client input (function call) |165| `completed` | done, output available |166| `incomplete` | finished with truncated results (token budget); agent context preserved, continue via `previous_interaction_id` |167| `failed` | error (tool failure, rate limit…) |168| `cancelled` | stopped by client |169| `budget_exceeded` | **deprecated** — now reported as `incomplete` |170171`usage`: `total_input_tokens`, `total_output_tokens`, `total_thought_tokens`, `total_cached_tokens`, `total_tool_use_tokens`, `total_tokens`, `*_tokens_by_modality[] {modality, tokens}`, `grounding_tool_count[] {type: google_search|google_maps, count}`.172173---174175## 5. Create request fields (`POST /v1beta/interactions`)176177| Field | Type | Required | Notes |178|---|---|---|---|179| `model` | string | one of model/agent | 24 ModelOption values on the reference page (gemini-2.5-*, gemini-3-flash-preview, gemini-3.1-pro-preview[-customtools], gemini-3.1-flash-lite, gemini-3.5/3.6/3.7/3.8-flash, image models, gemma-4-*, lyria-3-*, robotics-er) |180| `agent` | string | one of model/agent | `deep-research-pro-preview-12-2025`, `deep-research-preview-04-2026`, `deep-research-max-preview-04-2026`, `antigravity-preview-05-2026` (reference) / `antigravity-preview-09-2026` (guides), or a custom agent id |181| `input` | string \| Content \| Content[] \| Step[] | yes | string prompt; content blocks; or a step history (`user_input`, `model_output`, `function_call`, `function_result`, `thought`…) |182| `system_instruction` | string | no | interaction-scoped; additive with the agent's `AGENTS.md` |183| `tools[]` | Tool[] | no | see §6; interaction-scoped |184| `response_format` | ResponseFormat \| ResponseFormat[] | no | `type` = text/image/audio/video; array = multi-modal output |185| `stream` | boolean | no (false) | SSE response |186| `store` | boolean | no (**true**) | false = stateless, incompatible with `background` and with later `previous_interaction_id` |187| `background` | boolean | no (false) | async; requires `store=true`; effectively required for Deep Research |188| `generation_config` | object | model only | `max_output_tokens`, `seed`, `stop_sequences`, `thinking_level`, `thinking_summaries`, `tool_choice` (`auto`/`any`/`none`/`validated` or `{allowed_tools:{mode,tools[]}}`), `speech_config`, `transcription_config`, `video_config.task`; `temperature` appears in guides but not on the reference page (UNVERIFIED); Antigravity rejects `temperature`/`top_p`/`top_k`/`stop_sequences`/`max_output_tokens` with 400 |189| `agent_config` | object | agent only | `{type: "antigravity", model, max_total_tokens}` · `{type: "deep-research", collaborative_planning, thinking_summaries, visualization}` · `{type: "dynamic"}` · `CodeMenderAgentConfig` (named, undocumented) |190| `environment` | `"remote"` \| env id \| EnvironmentConfig | agents | `{type: "remote", environment_id?, sources[], network, env}` |191| `previous_interaction_id` | string | no | server-side history; 400 if previous still `in_progress` |192| `labels` | map | no | user metadata |193| `safety_settings` | SafetySetting[] | no | listed on the reference but overview says custom safety settings are **not supported** (UNVERIFIED) |194| `service_tier` | `flex` \| `standard` \| `priority` | no | flex −50 %, best-effort (429/503, no fallback); priority +75–100 %, 0.3× rate limit, graceful downgrade (check `x-gemini-service-tier` response header) |195| `webhook_config` | `{uris[], user_metadata}` | no | dynamic webhook (JWKS-signed) for completion events |196197Path/query/headers: path segment `api_version` (v1beta \| v1); headers `x-goog-api-key` (required), `Content-Type: application/json`, `Api-Revision` (optional).198199---200201## 6. Content, Tool, ResponseFormat and Step variants202203**Content** (`type`): `text {text, annotations[]}` · `image {data|uri, mime_type: image/png|jpeg|webp|heic|heif|gif|bmp|tiff, resolution: low|medium|high|ultra_high}` · `audio {data|uri, mime_type (wav, mp3, aiff, aac, ogg, flac, mpeg, m4a, l16, opus, alaw, mulaw, webm), channels, sample_rate}` · `document {data|uri, mime_type: application/pdf|text/csv}` · `video {data|uri, mime_type (mp4, mpeg, mpg, mov, avi, x-flv, webm, wmv, 3gpp), name, processing: "static"|"agentic"|{type:"static", fps, start_offset, end_offset}, resolution}`.204Annotations: `file_citation`, `place_citation`, `url_citation`, `word_info` (ASR word timing/diarization).205206**Tools** (`tools[].type`):207208| type | Fields | Executed by | Steps produced |209|---|---|---|---|210| `function` | `name`, `description`, `parameters` (JSON Schema) | client | `function_call` → status `requires_action`; reply with `function_result {call_id, result, is_error}` |211| `google_search` | `search_types[]: web_search \| image_search` | server | `google_search_call/result` (+ `url_citation`) |212| `google_maps` | `latitude`, `longitude`, `enable_widget` | server | `google_maps_call/result` (+ `place_citation`) |213| `code_execution` | — | server (Python ≥ 3.10; Antigravity: bash/python/node in sandbox) | `code_execution_call/result` |214| `url_context` | — | server | `url_context_call/result` |215| `file_search` | `file_search_store_names[]`, `metadata_filter`, `top_k` | server | `file_search_call/result` (+ `file_citation`) |216| `mcp_server` | `name`, `url`, `headers`, `credential`, `allowed_tools` | server (streamable HTTP) | `mcp_server_tool_call/result`; not on Gemini 3 models yet; Antigravity needs `^[a-z0-9_-]+$` names |217| `computer_use` | `environment: browser\|mobile\|desktop`, `disabled_safety_policies[]`, `enable_prompt_injection_detection`, `excluded_predefined_functions[]` | model `gemini-2.5-computer-use-preview-10-2025` | — |218219**ResponseFormat** (`type`): `text {mime_type: application/json|text/plain, schema}` · `image {aspect_ratio (14 values 1:1…4:1), image_size: 512|1K|2K|4K, mime_type: image/jpeg, delivery: inline|uri}` · `audio {mime_type: audio/mp3|ogg_opus|l16|wav|alaw|mulaw, sample_rate, bit_rate, delivery}` · `video {aspect_ratio: 16:9|9:16, resolution: 360p|720p|1080p|4k, duration, delivery}`.220221**Steps** (`steps[].type`): `user_input {content[]}` · `model_output {content[]}` · `thought {signature, summary[]}` · `function_call {id, name, arguments}` · `function_result {call_id, name, result, is_error}` · `code_execution_call {id, arguments{code, language}, signature}` / `code_execution_result {call_id, result, is_error}` · `google_search_call {id, arguments{queries[]}, search_type}` / `google_search_result {call_id, result[]{search_suggestions}}` · `google_maps_call/result` · `url_context_call {arguments{urls[]}}` / `url_context_result {result[]{url, status: success|error|paywall|unsafe}}` · `file_search_call/result` · `mcp_server_tool_call {id, name, server_name, arguments}` / `mcp_server_tool_result {call_id, result}` · `processing_call/result` (server-side media processing).222223---224225## 7. Streaming events (SSE), in order226227Transport: `text/event-stream`; each frame is `event: <event_type>` + `data: <JSON>`; the JSON repeats `event_type` and may carry `event_id` (resume token for `GET ?stream=true&last_event_id=`). Stream ends with `event: done` / `data: [DONE]`.228229| # | `event_type` | Payload | Notes |230|---|---|---|---|231| 1 | `interaction.created` | `interaction {id, model\|agent, object, status: in_progress}` | first |232| 2 | `interaction.status_update` | `interaction_id`, `status` | may repeat between steps; breaking-changes guide says it is superseded by `interaction.in_progress` / `interaction.requires_action` (neither defined in the reference — UNVERIFIED) |233| 3 | `step.start` | `index`, `step {type, …}` | for `function_call`: `id`, `name`, `arguments: {}` |234| 4 | `step.delta` (×n) | `index`, `delta {type, …}`, `metadata.total_usage?` | delta types: `text`, `text_annotation_delta`, `image`, `audio`, `video`, `document`, `thought_signature`, `thought_summary`, `arguments_delta` (partial JSON — accumulate), `function_result`, `code_execution_call/result`, `google_search_call/result`, `google_maps_call/result`, `url_context_call/result`, `file_search_call/result`, `mcp_server_tool_call/result`, `processing_call/result` |235| 5 | `step.stop` | `index`, `step_usage?`, `usage?` | steps 3–5 repeat per step (thought → model_output, tool pairs…) |236| 6 | `interaction.completed` | `interaction {id, status, usage, …}` (no steps) | last data event |237| — | `error` | `error {code, message}` | any time (`not_found`, `gateway_timeout`…) |238| 7 | `done` | `[DONE]` | terminal marker (guide) |239240Legacy (`Api-Revision: 2026-05-07`, removed 2026-06-08): `interaction.start`, `content.start`, `content.delta`, `content.stop`, `interaction.complete`. Unknown event types must be skipped, not treated as errors.241242---243244## 8. Background mode and cancellation245246- `"background": true` → immediate response with `id` and status `queued`/`in_progress`. Supported for models and managed agents; mandatory in practice for Deep Research (tasks of several minutes, max 60 min).247- Poll `GET /v1beta/interactions/{id}` until a terminal status, or stream `GET …/{id}?stream=true` (reconnect with `last_event_id`).248- `POST /v1beta/interactions/{id}/cancel` → `cancelled` (small lag possible). `DELETE` removes the record (later GET → 404).249- Chaining onto an `in_progress` interaction → 400. Managed agents need `previous_interaction_id` **and** `environment` (the returned `environment_id`).250- Requires `store=true` (default). Webhooks (`webhook_config` or static) fire `interaction.completed | failed | cancelled | requires_action`.251252---253254## 9. `store`, retention, deletion, ZDR notes255256- Default `store=true`: needed for `previous_interaction_id`, `background`, and AI Studio logs.257- Retention: **Paid tier 55 days** (configurable in AI Studio Logs to 7/14/28/55 days), **Free tier 1 day**; automatic deletion afterwards; manual `DELETE /interactions/{id}` anytime.258- `store=false` = stateless: send the full `steps` history in `input` each turn; incompatible with `background=true`; cannot be used as `previous_interaction_id` later. Implicit caching still works in stateless mode.259- No explicit "zero data retention" program is described for this API; data is processed per the Gemini API terms. Not documented: whether `store=false` also excludes the request from abuse-monitoring logs → UNVERIFIED.260- Environments: idle snapshot after 15 min, retained **7 days** since last active, then TTL-deleted (expired id → 404). Credentials: secrets write-only, never returned.261262---263264## 10. Agents265266### Deep Research (`deep-research-preview-04-2026`, `deep-research-max-preview-04-2026`, `deep-research-pro-preview-12-2025`)267- Autonomous plan → search → read → synthesize loop producing cited reports; Interactions-only (not via generateContent). Preview. Always `background: true`.268- `agent_config {type: "deep-research", collaborative_planning, thinking_summaries: auto|none, visualization: off|auto}`. Collaborative planning: turn 1 returns a plan; refine with `previous_interaction_id` keeping `collaborative_planning: true`; approve with `false`/omit.269- Default tools `google_search`, `url_context`, `code_execution`; also `mcp_server`, `file_search`. No custom `function` tools, no structured output, max research time 60 min (typically < 20). Inputs: text, image, PDF, audio, video; output text (+ images when visualization on).270- Live list: input limit 131 072 (API) vs 1 048 576 (model page) — discrepancy noted; output 65 536.271272### Antigravity (`antigravity-preview-05-2026` reference / `antigravity-preview-09-2026` guides & live list)273- General-purpose managed agent (Antigravity IDE harness) in a Google-hosted Linux sandbox: runs bash/python/node, manages files, browses. Context compaction at ~135 k tokens. Preview; free tier has a quota.274- `agent_config {type: "antigravity", model: gemini-3.8-flash (default) | 3.7-flash | 3.6-flash | 3.5-flash | 3.5-flash-lite, max_total_tokens}` — budget → `incomplete`, continue with `previous_interaction_id` + `environment`.275- Default tools `code_execution`, `google_search`, `url_context`; filesystem tools implicit via `environment`; plus `function` (stateful mode only) and `mcp_server` (streamable HTTP; lowercase names). Unsupported: `file_search`, `computer_use`, `google_maps`, structured output, audio/video/document inputs, `temperature`/`top_p`/`top_k`/`stop_sequences`/`max_output_tokens`.276- Hooks: mount `.agents/hooks.json` (+ scripts) — `pre_tool_execution` (allow/deny with reason) and `post_tool_execution` on `code_execution`, `view_file`, `write_to_file`, `replace_file_content`, `list_dir`, `delete_file`; `command` or `http` handlers (timeout 30 s); failures = allow.277- Triggers: `POST /v1beta/triggers {schedule, time_zone, display_name, max_consecutive_failures=5, execution_timeout_seconds=600, interaction}`; pause/resume via PATCH `status`; run now / list executions under `/executions`.278279### Custom (managed) agents — `POST /v1beta/agents`280`{id, description, base_agent: "antigravity-preview-09-2026", agent_config {type: antigravity, model}, system_instruction, tools[], base_environment: "remote" | env id | {type: remote, sources[], network}}`. Invoke with `agent: "<id>"` (+ `environment: "remote"`); each invocation forks the base environment. Overridable per interaction: `system_instruction`, `tools`, `environment.network`; **not** the model. Files: `.agents/AGENTS.md` (instructions), `.agents/skills/<name>/SKILL.md`, `.agents/hooks.json`. Reserved id prefixes: antigravity-, veo-, omni-, lyria-, imagen-, gemma-, gemini-, google-, youtube-, android-, chrome-, pixel-, waze-, fitbit-, nest-, kaggle-. Limits: 1 000 agents, no versioning, no sub-agents.281282### Credentials — `/v1beta/credentials`283| type | required fields | injection |284|---|---|---|285| `bearer_token` | `token` (+ `header_name`=Authorization, `prefix`=Bearer) | header on allowlisted domain / MCP server |286| `oauth2` | `client_id`, `client_secret`, `refresh_token`, `token_url` (+ `scopes`) | live exchange at creation; auto-refresh |287| `environment_variable` | `value`, `injection_location: header\|query\|body` (+ `trusted_domains`) | sandbox var gets `__GEMINI_CRED_<id>__`; proxy substitutes on the wire |288289Referenced from `environment.network.allowlist[].credential`, `tools[](mcp_server).credential`, `environment.env.<VAR>.credential`. Errors: 400 `invalid_request`, 404 `not_found`, 409 `aborted` (duplicate id); unknown/camelCase fields rejected.290291---292293## 11. Environments API (sandboxes)294295Lifecycle: **Created** (interaction with `environment: "remote"`/config, or `POST /v1beta/environments`) → **Active** while an interaction runs → **Idle** (snapshot after 15 min) → **Offline** (7 days, resumable by id) → **Deleted** (TTL or `DELETE`). Fixed resources: 4 vCPU, 16 GB RAM; Ubuntu with Python 3.12 (numpy, pandas, requests, google-genai, beautifulsoup4, pyyaml, ast-grep-cli), Node.js 22 (create-next-app, create-vite, typescript), git/curl/jq/ripgrep/gcloud…; packages installed persist with the same `environment_id`. Startup ≈ 5 s.296297`environment` forms: `"remote"` (fresh), `"env_abc123"` (reuse), `{type: "remote", environment_id?, sources[], network, env}`.298- `sources[]`: `repository` (≤ 500 MB, `https://github.com/...`), `gcs` (≤ 2 GB, `gs://…`), `inline` (≤ 1 MB/file, 2 MB total, optional `encoding: base64`); `target` never `/`.299- `network`: omitted = unrestricted; `"disabled"`; or `{allowlist: [{domain, credential?, transform?}]}` — `*.example.com` does not match the root; add `{domain: "*"}` as catch-all; new rules replace old ones when reusing an env; credential applied first, `transform` headers win on conflict. Loopback blocked for HTTP hooks.300- `env`: literal strings (plaintext, visible to the agent) or `{credential: "<id>"}`.301302Files: `GET /v1beta/environments/{env}/files[/{path}]` (JSON listing / metadata; `recursive`, `page_size` 100 max 1000) and `?alt=media` (raw bytes for a file, POSIX tar for a directory; `recursive=true` for nested). `PUT /upload/v1beta/environments/{env}/files/{path}` with raw bytes (`Content-Type`), `?overwrite=true` (else 409), `?extract=true` for tar/tar.gz; resumable protocol with `X-Goog-Upload-Protocol: resumable`, `X-Goog-Upload-Command: start`, `X-Goog-Upload-Header-Content-Length/Type` → `X-Goog-Upload-URL`; max 2 GiB. Response `{files[]: EnvironmentFile {name, path, type: FILE|DIRECTORY, size_bytes, mime_type, created, modified}}`. Legacy `GET /v1beta/files/environment-{env}:download?alt=media`.303304Field casing caveat: the REST page and guides use snake_case (`file_count`, `last_accessed`, `size_bytes`, `network`, `from_environment`, `page_size`) while the discovery doc uses camelCase (`fileCount`, `lastAccessed`, `sizeBytes`, `networkMode: DISABLED`, `networkAllowlist`, `fromEnvironment`, `pageSize`) and the guide curl uses `?pageSize=10` — which the server accepts for JSON bodies is UNVERIFIED (Google APIs normally accept both).305306Pricing: environment compute (CPU, memory, sandbox execution) **not billed during preview**; only model tokens + tool fees.307308---309310## 12. `dynamic/*` endpoints311312The discovery document (rev. 20260918) exposes `generativelanguage.dynamic.generateContent` and `dynamic.streamGenerateContent` at `POST /v1beta/dynamic/{dynamicId}:generateContent|:streamGenerateContent` with the standard `GenerateContentRequest`/`GenerateContentResponse` schemas (`model` path param pattern `^dynamic/[^/]+$`). No guide or reference page mentions a `dynamic/{id}` resource; the only related documented concept is `agent_config {type: "dynamic"}` (DynamicAgentConfig, the sole config type in the v1 surface) and "dynamic webhooks". Status: DOCUMENTED (discovery) + DOCUMENTATION_INCOMPLETE; nothing in the live model list starts with `dynamic/`.313314---315316## 13. Breaking changes (May 2026) and migration notes317318- `outputs[]` → `steps[]` with `type` discriminators; `POST` returns output steps only, `GET` the full timeline. Stateless clients must replay `steps` (not `outputs`) in `input`.319- Streaming renamed: `interaction.start`→`interaction.created`, `content.*`→`step.*`, `interaction.complete`→`interaction.completed`; function-call arguments now stream as `arguments_delta` partial JSON.320- `response_format` became polymorphic; `response_mime_type` removed; `generation_config.image_config` moved to `response_format {type: image}`.321- Timeline: opt-in May 7 (`Api-Revision: 2026-05-20`, SDK Python/JS ≥ 2.0.0), default flip May 26 (`Api-Revision: 2026-05-07` to opt out), legacy removed **June 8, 2026**.322- From `generateContent`: camelCase → snake_case; `contents[]` → `input`; `candidates[0].content.parts` → `steps[-1].content` / `output_text`; `thinkingConfig` → `thinking_level`; server tools become explicit `*_call/*_result` steps; `previous_interaction_id` replaces resending history.323324---325326## 14. Pricing (from pricing.md "Pricing for agents" + agent guides)327328| Item | Price / rule |329|---|---|330| Model interactions | standard Gemini list rates per model (input / cached / output / thinking tokens); tool fees per existing structure (Search grounding excludes retrieved tokens; url_context / file_search include them) |331| `service_tier: flex` | 50 % of standard, best-effort |332| `service_tier: priority` | +75–100 % over standard; downgraded requests billed standard |333| Deep Research agent | all model inference at list rates incl. intermediate/reasoning tokens + tool fees. Estimates: Deep Research ≈ 80 searches, ~250k input (50–70 % cached), ~60k output → **~$1–3 / task**; Max ≈ 160 searches, ~900k input, ~80k output → **~$3–7 / task** |334| Antigravity / managed agents | tokens at list rates (typically 100k–3M per interaction; up to 3–5M ≈ $5); estimates: research $0.30–1.00, content generation $0.30–1.30, process design $0.25–0.80, data analysis $0.70–3.25. **Environment compute not billed in preview.** Free tier has a free quota |335| Environments / credentials / triggers / webhooks API calls | no separate price documented |336337---338339## 15. Limits and quotas (documented)340341- Interactions retention 55 d (paid) / 1 d (free); Deep Research max 60 min; Antigravity compaction ~135k; agent input context 1 048 576 (model pages) / 131 072 (`inputTokenLimit` in live list for deep-research-*), output 65 536.342- Environments: 4 vCPU / 16 GB; sources 500 MB (git) / 2 GB (gcs) / 1 MB per inline file, 2 MB total; upload ≤ 2 GiB; idle 15 min; TTL 7 days; ≈5 s startup; text/image files only for the agent.343- Agents: 1 000 per project; base_agent only `antigravity-preview-09-2026`; model locked per agent.344- Credentials list: page_size default 50, max 1000. Files listing: default 100, max 1000.345- Triggers: `max_consecutive_failures` 5, `execution_timeout_seconds` 600 by default.346- Priority tier rate limit 0.3× standard; flex shares standard limits. Rate limits per model/tier are account-specific (not recorded here).347- Antigravity function calling only in stateful mode; MCP SSE transport unsupported; Gemini 3 models: remote MCP "coming soon".348349---350351## 16. SDK snippets (tiny prompts, key from env only)352353**curl (create, non-streaming)**354```bash355curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \356  -H "x-goog-api-key: $GEMINI_API_KEY" \357  -H "Content-Type: application/json" \358  -H "Api-Revision: 2026-05-20" \359  -d '{"model": "gemini-3.5-flash-lite", "input": "Reply with OK.", "generation_config": {"max_output_tokens": 16}}'360```361**curl (stream)** — add `"stream": true` and `--no-buffer`; events arrive as `event: step.delta` / `data: {...}`.362**curl (background + poll + cancel + delete)**363```bash364ID=$(curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" -H "x-goog-api-key: $GEMINI_API_KEY" -H "Content-Type: application/json" \365  -d '{"model": "gemini-3.5-flash-lite", "input": "Reply with OK.", "background": true}' | python3 -c 'import sys,json;print(json.load(sys.stdin)["id"])')366curl -s "https://generativelanguage.googleapis.com/v1beta/interactions/$ID" -H "x-goog-api-key: $GEMINI_API_KEY"367curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/interactions/$ID/cancel" -H "x-goog-api-key: $GEMINI_API_KEY"368curl -s -X DELETE "https://generativelanguage.googleapis.com/v1beta/interactions/$ID" -H "x-goog-api-key: $GEMINI_API_KEY"369```370**Python (google-genai ≥ 2.3)**371```python372from google import genai            # reads GEMINI_API_KEY from the environment373client = genai.Client()374it = client.interactions.create(model="gemini-3.5-flash-lite", input="Reply with OK.",375                                generation_config={"max_output_tokens": 16})376print(it.status, it.output_text)377for ev in client.interactions.create(model="gemini-3.5-flash-lite", input="Reply with OK.", stream=True):378    print(ev.event_type)379follow = client.interactions.create(model="gemini-3.5-flash-lite", input="Again.", previous_interaction_id=it.id)380client.interactions.delete(id=it.id)381# agents / sandboxes382# client.interactions.create(agent="deep-research-preview-04-2026", input="...", background=True)383# client.interactions.create(agent="antigravity-preview-09-2026", input="...", environment="remote")384# client.environments.list(page_size=10); client.environments.files.download(environment=env_id, path="src/main.py")385```386**TypeScript (@google/genai ≥ 2.3)**387```ts388import { GoogleGenAI } from "@google/genai";      // GEMINI_API_KEY from env389const ai = new GoogleGenAI({});390const it = await ai.interactions.create({ model: "gemini-3.5-flash-lite", input: "Reply with OK.",391                                          generation_config: { max_output_tokens: 16 } });392console.log(it.status, it.output_text);393const stream = await ai.interactions.create({ model: "gemini-3.5-flash-lite", input: "Reply with OK.", stream: true });394for await (const ev of stream) console.log(ev.event_type);395await ai.interactions.delete(it.id);396```397398---399400## Live verification (2026-09-18)401402Run of 2026-09-18 on `gemini-3.5-flash-lite` (raws `tmp-live/gemini-tools/h*.json`, `env*.json`, `f2_*.json`; examples `examples/gemini/interactions/*` all executed; tests `tests/gemini/test_interactions.py` pass).403404| Probe | Result |405|---|---|406| `POST /v1beta/interactions {model, input:"Reply with OK.", generation_config:{max_output_tokens:16}}` | 200 `{id:"v1_Chd…", object:"interaction", status:"completed", model, created, updated, service_tier:"standard", steps:[{type:"thought", signature}, {type:"model_output", content:[{type:"text", text:"OK."}]}], usage:{total_tokens, total_input_tokens, input_tokens_by_modality, total_cached_tokens, total_output_tokens, total_tool_use_tokens, total_thought_tokens, raw_prompt_token, model_invocation_token_counts}}` — note **`steps`**, not `outputs` |407| `stream:true` (+ `previous_interaction_id`) | SSE `event:`/`data:` frames, order **interaction.created → interaction.status_update → step.start(thought) → step.delta{type:"thought_signature"} → step.stop → step.start(model_output) → step.delta{type:"text"} → step.stop → interaction.completed** (+ terminal `data: [DONE]`) |408| `previous_interaction_id` chaining | 200; the model recalled the earlier turn ("You asked me to reply."); the response does **not** echo `previous_interaction_id` |409| `GET /v1beta/interactions/{id}` | 200 (adds `generation_config` echo); `?include_steps=true` → 400; after DELETE → 404 `Requested entity was not found` |410| `DELETE /v1beta/interactions/{id}` | 200 `{}` |411| `GET /v1beta/interactions` (list, undocumented) | 404 empty body |412| `store:false` | 200, **no `id`** in the response |413| function tool + `generation_config.tool_choice{allowed_tools{mode:"any"}}` | `status:"requires_action"`, step `{id:"call_…", type:"function_call", name, arguments}`; `function_result{name, call_id, result:[{type:"text",text}]}` + `previous_interaction_id` → completed. Top-level `tool_choice` → 400 `Unknown parameter 'tool_choice'`; camelCase (`generationConfig`) → 400 `Did you mean 'generation_config'?` |414| `{"type":"google_search"}` | 429 `too_many_requests` (same free-tier quota block as generateContent `googleSearch`) |415| `{"type":"computer_use","environment":"browser"}` on gemini-3.5-flash-lite | 200 completed (model answered without acting) |416| `agent:"deep-research-preview-04-2026", background:true` | 200 `{id, object, agent, status:"in_progress", created, updated, service_tier}` → `POST …/{id}/cancel` → 200 `status:"cancelled"` → GET `cancelled` → DELETE 200 |417| Environments | `GET /v1beta/environments` → 200 `{}`; `POST /v1beta/environments {}` → 200 `{id}`; `GET /v1beta/environments/{id}` → `{id, status:"active", storage:{tier:"free", project_used_bytes:"0", project_limit_bytes:"1073741824"}, file_count:"0", size_bytes:"0", created, updated}`; `GET …/files/` → 404 once, 200 `{}` once; `DELETE` → 200 `{}`; discovery spelling `GET /v1beta/environments:list` → 200 |418| Rate limiting | a burst of ~10 creates within a minute produced HTTP 429 `too_many_requests` (retry a minute later succeeded) |419420Not exercised: credentials, custom agents, triggers, webhooks, environment file upload/download, `dynamic/*`, antigravity agents.421