Gemini Interactions API, managed agents, Environments API and dynamic/*
Status: DOCUMENTED + LIVE_VERIFIED (2026-09-18 run — see "Live verification" section at the end)
Sources (offline copies under sources/gemini/, retrieved 2026-09-18):
- Reference: https://ai.google.dev/api/interactions (v1beta, 186 KB, incl. Credentials CRUD and the
InteractionSseEventunion), 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-methods - Discovery document
generativelanguagev1beta rev. 20260918 (sources/gemini/discovery-v1beta.json): resourcesenvironments,environments.files.media,dynamic - 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-versions
- Model pages: …/models/deep-research-preview-04-2026, deep-research-max-preview-04-2026, deep-research-pro-preview-12-2025, antigravity-preview-05-2026
- SDK surfaces:
google-genai2.24 (google/genai/_gaos/{interactions,agents,environments,files,credentials,triggers,webhooks}.py),@google/genai2.23 (dist/genai.d.tsclassesInteractions_2,Agents_2,Environments_2,Credentials_2,Triggers_2,Webhooks_2) - 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)
Last verified: 2026-09-18 (docs only — no live call in this document; see the final section)
Machine-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).
1. What it is, and when to use it instead of generateContent
The 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).
| Aspect | models/*:generateContent (legacy) |
Interactions API |
|---|---|---|
| Path | POST /v1beta/models/{model}:generateContent (+ :streamGenerateContent) |
POST /v1beta/interactions (stream via body stream: true); stable POST /v1/interactions |
| Casing | camelCase (generationConfig, systemInstruction) |
snake_case everywhere (generation_config, previous_interaction_id) — camelCase fields are rejected with 400 |
| Request shape | contents[] { role, parts[] } |
input: string | Content | Content[] | Step[] |
| Response shape | candidates[].content.parts[] |
steps[] typed by type (model_output, thought, function_call, google_search_call…) + usage |
| State | stateless only | optional server-side state: previous_interaction_id (default store=true) |
| Long-running | none (client timeout ~60 s) | background: true + polling GET /interactions/{id} or resumable SSE (?stream=true&last_event_id=) + cancel |
| Agents | none | Deep Research, Antigravity (Linux sandbox), custom managed agents, cron triggers |
| Sandboxes | none | environment param + Environments API (files PUT/GET, egress allowlist, credentials) |
| Structured output | responseMimeType / responseSchema |
polymorphic response_format (text/image/audio/video) |
| Tools | tools[].functionDeclarations, googleSearch, … |
flat tools[] {type: function | google_search | google_maps | code_execution | url_context | file_search | mcp_server | computer_use} |
| Thinking | thinkingConfig.thinkingBudget/includeThoughts |
generation_config.thinking_level (minimal/low/medium/high) + thinking_summaries (auto/none); thought steps with signature |
| Tiers | — | service_tier: flex (-50 %), standard, priority (+75–100 %) |
| Webhooks | Batch/video LROs | webhook_config per request (dynamic) or static webhooks with interaction.* events |
| Not (yet) available | — | Batch API, automatic function calling (Python), explicit caching (implicit caching works), custom safety settings, remote MCP on Gemini 3 models |
Use 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).
2. Architecture
flowchart LR
subgraph Client
C[App / SDK<br/>google-genai · @google/genai · curl]
end
subgraph API["generativelanguage.googleapis.com"]
I["POST /v1beta/interactions<br/>GET · DELETE · /cancel"]
ST[(Stored Interactions<br/>store=true · 55 d paid / 1 d free)]
A["/v1beta/agents<br/>custom agent defs"]
T["/v1beta/triggers<br/>cron runs"]
CR["/v1beta/credentials<br/>write-only secrets"]
W["/v1/webhooks<br/>static endpoints"]
end
subgraph Runtime
M[Gemini model]
DR[deep-research-* agent]
AG[antigravity-* agent<br/>harness]
TOOLS[server tools<br/>google_search · url_context · code_execution<br/>file_search · google_maps · mcp_server]
end
subgraph Sandbox["Environment (Linux sandbox, 4 vCPU / 16 GB)"]
FS[(/workspace files)]
PX[egress proxy<br/>allowlist + header/credential injection]
HK[.agents/hooks.json<br/>pre/post tool hooks]
end
C -- "model | agent, input, tools, previous_interaction_id, background, stream" --> I
I <--> ST
I --> M
I --> DR
I --> AG
M --> TOOLS
DR --> TOOLS
AG --> TOOLS
AG <--> FS
AG --> HK
FS --> PX --> Internet((Internet / MCP servers))
CR -. "referenced by id" .-> PX
A -. "agent: <id>" .-> I
T -- "CreateInteractionRequest on schedule" --> I
I -- "SSE: interaction.created → step.start/delta/stop → interaction.completed" --> C
I -- "background: id → poll GET / stream GET?stream=true&last_event_id" --> C
I -- "webhook_config / static webhooks: interaction.completed|failed|cancelled|requires_action" --> W --> C
C -- "PUT /upload/v1beta/environments/{id}/files/{path}<br/>GET .../files/{path}?alt=media" --> FS
M -- "function_call step (status requires_action)" --> C
C -- "input: function_result + previous_interaction_id" --> I
Chaining: 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.
3. Resource tree (every endpoint)
Host 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).
| Family | Method & path | Purpose | Notes |
|---|---|---|---|
| interactions | POST /v1beta/interactions |
create (model or agent) | body stream: true → SSE; background: true → async |
| interactions | GET /v1beta/interactions/{id} |
get / poll | ?stream=true[&last_event_id=] resumes SSE |
| interactions | DELETE /v1beta/interactions/{id} |
delete stored record | empty body; later GET → 404 |
| interactions | POST /v1beta/interactions/{id}/cancel |
cancel background run | one guide shows …/{id}:cancel (UNVERIFIED alias) |
| 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" |
| credentials | POST /v1beta/credentials |
create secret | types bearer_token, oauth2, environment_variable |
| credentials | GET /v1beta/credentials |
list | page_size (50, max 1000), page_token |
| credentials | GET /v1beta/credentials/{id} |
get metadata | never returns secrets |
| credentials | PATCH /v1beta/credentials/{id} |
rotate | body must repeat type; ?update_mask= |
| credentials | DELETE /v1beta/credentials/{id} |
delete | fails if referenced by active triggers |
| agents | POST /v1beta/agents |
create custom managed agent | id, base_agent, agent_config, system_instruction, tools, base_environment |
| agents | GET /v1beta/agents |
list | page_size/page_token (SDK) |
| agents | GET /v1beta/agents/{id} |
get | |
| agents | DELETE /v1beta/agents/{id} |
delete | existing envs/interactions unaffected |
| triggers | POST /v1beta/triggers |
cron-scheduled agent run | schedule, time_zone, interaction |
| triggers | GET /v1beta/triggers, GET /v1beta/triggers/{id} |
list / get | |
| triggers | PATCH /v1beta/triggers/{id} |
pause/resume | {"status": "paused" | "active"} |
| triggers | DELETE /v1beta/triggers/{id} |
delete | history kept |
| triggers | POST /v1beta/triggers/{id}/executions |
run now | |
| triggers | GET /v1beta/triggers/{id}/executions |
executions (status, interaction_id, environment_id) |
|
| 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) |
| environments | POST /v1beta/environments |
create sandbox | discovery flatPath environments:create; body sources[], network, from_environment |
| environments | GET /v1beta/environments |
list | page_size/page_token (REST page) vs pageSize/pageToken (discovery, guide curl) |
| environments | GET /v1beta/environments/{id} |
get | status: active | expired |
| environments | DELETE /v1beta/environments/{id} |
delete | otherwise 7-day idle TTL |
| 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) |
| 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 |
| environments (legacy) | GET /v1beta/files/environment-{env}:download?alt=media |
whole-sandbox tar | superseded by …/files?alt=media |
| dynamic | POST /v1beta/dynamic/{dynamicId}:generateContent |
GenerateContentRequest on a dynamic/* resource |
discovery-only, semantics undocumented |
| dynamic | POST /v1beta/dynamic/{dynamicId}:streamGenerateContent |
streamed variant | same |
SDK 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.*.
4. The Interaction object and its lifecycle
Top-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.
POST returns only the model-generated steps; GET returns the full timeline including the initial user_input step.
stateDiagram-v2
[*] --> queued: background=true
[*] --> in_progress
queued --> in_progress
in_progress --> requires_action: function_call step emitted
requires_action --> in_progress: next POST with function_result + previous_interaction_id
in_progress --> completed
in_progress --> incomplete: max_output_tokens / max_total_tokens budget hit
in_progress --> failed
in_progress --> cancelled: POST /interactions/{id}/cancel
completed --> [*]
incomplete --> [*]: continue with previous_interaction_id (+ environment)
failed --> [*]
cancelled --> [*]
status |
Meaning |
|---|---|
queued |
waiting for processing (background) |
in_progress |
executing (model, tools, sandbox) |
requires_action |
paused for client input (function call) |
completed |
done, output available |
incomplete |
finished with truncated results (token budget); agent context preserved, continue via previous_interaction_id |
failed |
error (tool failure, rate limit…) |
cancelled |
stopped by client |
budget_exceeded |
deprecated — now reported as incomplete |
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}.
5. Create request fields (POST /v1beta/interactions)
| Field | Type | Required | Notes |
|---|---|---|---|
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) |
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 |
input |
string | Content | Content[] | Step[] | yes | string prompt; content blocks; or a step history (user_input, model_output, function_call, function_result, thought…) |
system_instruction |
string | no | interaction-scoped; additive with the agent's AGENTS.md |
tools[] |
Tool[] | no | see §6; interaction-scoped |
response_format |
ResponseFormat | ResponseFormat[] | no | type = text/image/audio/video; array = multi-modal output |
stream |
boolean | no (false) | SSE response |
store |
boolean | no (true) | false = stateless, incompatible with background and with later previous_interaction_id |
background |
boolean | no (false) | async; requires store=true; effectively required for Deep Research |
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 |
agent_config |
object | agent only | {type: "antigravity", model, max_total_tokens} · {type: "deep-research", collaborative_planning, thinking_summaries, visualization} · {type: "dynamic"} · CodeMenderAgentConfig (named, undocumented) |
environment |
"remote" | env id | EnvironmentConfig |
agents | {type: "remote", environment_id?, sources[], network, env} |
previous_interaction_id |
string | no | server-side history; 400 if previous still in_progress |
labels |
map | no | user metadata |
safety_settings |
SafetySetting[] | no | listed on the reference but overview says custom safety settings are not supported (UNVERIFIED) |
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) |
webhook_config |
{uris[], user_metadata} |
no | dynamic webhook (JWKS-signed) for completion events |
Path/query/headers: path segment api_version (v1beta | v1); headers x-goog-api-key (required), Content-Type: application/json, Api-Revision (optional).
6. Content, Tool, ResponseFormat and Step variants
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}.
Annotations: file_citation, place_citation, url_citation, word_info (ASR word timing/diarization).
Tools (tools[].type):
| type | Fields | Executed by | Steps produced |
|---|---|---|---|
function |
name, description, parameters (JSON Schema) |
client | function_call → status requires_action; reply with function_result {call_id, result, is_error} |
google_search |
search_types[]: web_search | image_search |
server | google_search_call/result (+ url_citation) |
google_maps |
latitude, longitude, enable_widget |
server | google_maps_call/result (+ place_citation) |
code_execution |
— | server (Python ≥ 3.10; Antigravity: bash/python/node in sandbox) | code_execution_call/result |
url_context |
— | server | url_context_call/result |
file_search |
file_search_store_names[], metadata_filter, top_k |
server | file_search_call/result (+ file_citation) |
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 |
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 |
— |
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}.
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).
7. Streaming events (SSE), in order
Transport: 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].
| # | event_type |
Payload | Notes |
|---|---|---|---|
| 1 | interaction.created |
interaction {id, model|agent, object, status: in_progress} |
first |
| 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) |
| 3 | step.start |
index, step {type, …} |
for function_call: id, name, arguments: {} |
| 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 |
| 5 | step.stop |
index, step_usage?, usage? |
steps 3–5 repeat per step (thought → model_output, tool pairs…) |
| 6 | interaction.completed |
interaction {id, status, usage, …} (no steps) |
last data event |
| — | error |
error {code, message} |
any time (not_found, gateway_timeout…) |
| 7 | done |
[DONE] |
terminal marker (guide) |
Legacy (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.
8. Background mode and cancellation
"background": true→ immediate response withidand statusqueued/in_progress. Supported for models and managed agents; mandatory in practice for Deep Research (tasks of several minutes, max 60 min).- Poll
GET /v1beta/interactions/{id}until a terminal status, or streamGET …/{id}?stream=true(reconnect withlast_event_id). POST /v1beta/interactions/{id}/cancel→cancelled(small lag possible).DELETEremoves the record (later GET → 404).- Chaining onto an
in_progressinteraction → 400. Managed agents needprevious_interaction_idandenvironment(the returnedenvironment_id). - Requires
store=true(default). Webhooks (webhook_configor static) fireinteraction.completed | failed | cancelled | requires_action.
9. store, retention, deletion, ZDR notes
- Default
store=true: needed forprevious_interaction_id,background, and AI Studio logs. - 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. store=false= stateless: send the fullstepshistory ininputeach turn; incompatible withbackground=true; cannot be used asprevious_interaction_idlater. Implicit caching still works in stateless mode.- No explicit "zero data retention" program is described for this API; data is processed per the Gemini API terms. Not documented: whether
store=falsealso excludes the request from abuse-monitoring logs → UNVERIFIED. - Environments: idle snapshot after 15 min, retained 7 days since last active, then TTL-deleted (expired id → 404). Credentials: secrets write-only, never returned.
10. Agents
Deep Research (deep-research-preview-04-2026, deep-research-max-preview-04-2026, deep-research-pro-preview-12-2025)
- Autonomous plan → search → read → synthesize loop producing cited reports; Interactions-only (not via generateContent). Preview. Always
background: true. agent_config {type: "deep-research", collaborative_planning, thinking_summaries: auto|none, visualization: off|auto}. Collaborative planning: turn 1 returns a plan; refine withprevious_interaction_idkeepingcollaborative_planning: true; approve withfalse/omit.- Default tools
google_search,url_context,code_execution; alsomcp_server,file_search. No customfunctiontools, no structured output, max research time 60 min (typically < 20). Inputs: text, image, PDF, audio, video; output text (+ images when visualization on). - Live list: input limit 131 072 (API) vs 1 048 576 (model page) — discrepancy noted; output 65 536.
Antigravity (antigravity-preview-05-2026 reference / antigravity-preview-09-2026 guides & live list)
- 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.
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 withprevious_interaction_id+environment.- Default tools
code_execution,google_search,url_context; filesystem tools implicit viaenvironment; plusfunction(stateful mode only) andmcp_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. - Hooks: mount
.agents/hooks.json(+ scripts) —pre_tool_execution(allow/deny with reason) andpost_tool_executiononcode_execution,view_file,write_to_file,replace_file_content,list_dir,delete_file;commandorhttphandlers (timeout 30 s); failures = allow. - Triggers:
POST /v1beta/triggers {schedule, time_zone, display_name, max_consecutive_failures=5, execution_timeout_seconds=600, interaction}; pause/resume via PATCHstatus; run now / list executions under/executions.
Custom (managed) agents — POST /v1beta/agents
{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.
Credentials — /v1beta/credentials
| type | required fields | injection |
|---|---|---|
bearer_token |
token (+ header_name=Authorization, prefix=Bearer) |
header on allowlisted domain / MCP server |
oauth2 |
client_id, client_secret, refresh_token, token_url (+ scopes) |
live exchange at creation; auto-refresh |
environment_variable |
value, injection_location: header|query|body (+ trusted_domains) |
sandbox var gets __GEMINI_CRED_<id>__; proxy substitutes on the wire |
Referenced 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.
11. Environments API (sandboxes)
Lifecycle: 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.
environment forms: "remote" (fresh), "env_abc123" (reuse), {type: "remote", environment_id?, sources[], network, env}.
sources[]:repository(≤ 500 MB,https://github.com/...),gcs(≤ 2 GB,gs://…),inline(≤ 1 MB/file, 2 MB total, optionalencoding: base64);targetnever/.network: omitted = unrestricted;"disabled"; or{allowlist: [{domain, credential?, transform?}]}—*.example.comdoes not match the root; add{domain: "*"}as catch-all; new rules replace old ones when reusing an env; credential applied first,transformheaders win on conflict. Loopback blocked for HTTP hooks.env: literal strings (plaintext, visible to the agent) or{credential: "<id>"}.
Files: 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.
Field 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).
Pricing: environment compute (CPU, memory, sandbox execution) not billed during preview; only model tokens + tool fees.
12. dynamic/* endpoints
The 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/.
13. Breaking changes (May 2026) and migration notes
outputs[]→steps[]withtypediscriminators;POSTreturns output steps only,GETthe full timeline. Stateless clients must replaysteps(notoutputs) ininput.- Streaming renamed:
interaction.start→interaction.created,content.*→step.*,interaction.complete→interaction.completed; function-call arguments now stream asarguments_deltapartial JSON. response_formatbecame polymorphic;response_mime_typeremoved;generation_config.image_configmoved toresponse_format {type: image}.- Timeline: opt-in May 7 (
Api-Revision: 2026-05-20, SDK Python/JS ≥ 2.0.0), default flip May 26 (Api-Revision: 2026-05-07to opt out), legacy removed June 8, 2026. - From
generateContent: camelCase → snake_case;contents[]→input;candidates[0].content.parts→steps[-1].content/output_text;thinkingConfig→thinking_level; server tools become explicit*_call/*_resultsteps;previous_interaction_idreplaces resending history.
14. Pricing (from pricing.md "Pricing for agents" + agent guides)
| Item | Price / rule |
|---|---|
| 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) |
service_tier: flex |
50 % of standard, best-effort |
service_tier: priority |
+75–100 % over standard; downgraded requests billed standard |
| 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 |
| 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 |
| Environments / credentials / triggers / webhooks API calls | no separate price documented |
15. Limits and quotas (documented)
- 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 (
inputTokenLimitin live list for deep-research-*), output 65 536. - 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.
- Agents: 1 000 per project; base_agent only
antigravity-preview-09-2026; model locked per agent. - Credentials list: page_size default 50, max 1000. Files listing: default 100, max 1000.
- Triggers:
max_consecutive_failures5,execution_timeout_seconds600 by default. - Priority tier rate limit 0.3× standard; flex shares standard limits. Rate limits per model/tier are account-specific (not recorded here).
- Antigravity function calling only in stateful mode; MCP SSE transport unsupported; Gemini 3 models: remote MCP "coming soon".
16. SDK snippets (tiny prompts, key from env only)
curl (create, non-streaming)
curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-H "Api-Revision: 2026-05-20" \
-d '{"model": "gemini-3.5-flash-lite", "input": "Reply with OK.", "generation_config": {"max_output_tokens": 16}}'curl (stream) — add "stream": true and --no-buffer; events arrive as event: step.delta / data: {...}.
curl (background + poll + cancel + delete)
ID=$(curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" -H "x-goog-api-key: $GEMINI_API_KEY" -H "Content-Type: application/json" \
-d '{"model": "gemini-3.5-flash-lite", "input": "Reply with OK.", "background": true}' | python3 -c 'import sys,json;print(json.load(sys.stdin)["id"])')
curl -s "https://generativelanguage.googleapis.com/v1beta/interactions/$ID" -H "x-goog-api-key: $GEMINI_API_KEY"
curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/interactions/$ID/cancel" -H "x-goog-api-key: $GEMINI_API_KEY"
curl -s -X DELETE "https://generativelanguage.googleapis.com/v1beta/interactions/$ID" -H "x-goog-api-key: $GEMINI_API_KEY"Python (google-genai ≥ 2.3)
from google import genai # reads GEMINI_API_KEY from the environment
client = genai.Client()
it = client.interactions.create(model="gemini-3.5-flash-lite", input="Reply with OK.",
generation_config={"max_output_tokens": 16})
print(it.status, it.output_text)
for ev in client.interactions.create(model="gemini-3.5-flash-lite", input="Reply with OK.", stream=True):
print(ev.event_type)
follow = client.interactions.create(model="gemini-3.5-flash-lite", input="Again.", previous_interaction_id=it.id)
client.interactions.delete(id=it.id)
# agents / sandboxes
# client.interactions.create(agent="deep-research-preview-04-2026", input="...", background=True)
# client.interactions.create(agent="antigravity-preview-09-2026", input="...", environment="remote")
# client.environments.list(page_size=10); client.environments.files.download(environment=env_id, path="src/main.py")TypeScript (@google/genai ≥ 2.3)
import { GoogleGenAI } from "@google/genai"; // GEMINI_API_KEY from env
const ai = new GoogleGenAI({});
const it = await ai.interactions.create({ model: "gemini-3.5-flash-lite", input: "Reply with OK.",
generation_config: { max_output_tokens: 16 } });
console.log(it.status, it.output_text);
const stream = await ai.interactions.create({ model: "gemini-3.5-flash-lite", input: "Reply with OK.", stream: true });
for await (const ev of stream) console.log(ev.event_type);
await ai.interactions.delete(it.id);Live verification (2026-09-18)
Run 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).
| Probe | Result |
|---|---|
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 |
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]) |
previous_interaction_id chaining |
200; the model recalled the earlier turn ("You asked me to reply."); the response does not echo previous_interaction_id |
GET /v1beta/interactions/{id} |
200 (adds generation_config echo); ?include_steps=true → 400; after DELETE → 404 Requested entity was not found |
DELETE /v1beta/interactions/{id} |
200 {} |
GET /v1beta/interactions (list, undocumented) |
404 empty body |
store:false |
200, no id in the response |
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'? |
{"type":"google_search"} |
429 too_many_requests (same free-tier quota block as generateContent googleSearch) |
{"type":"computer_use","environment":"browser"} on gemini-3.5-flash-lite |
200 completed (model answered without acting) |
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 |
| 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 |
| Rate limiting | a burst of ~10 creates within a minute produced HTTP 429 too_many_requests (retry a minute later succeeded) |
Not exercised: credentials, custom agents, triggers, webhooks, environment file upload/download, dynamic/*, antigravity agents.