- AI
- v1.0.0
- gemini
- agents
- deep-research
Gemini Interactions API
Use the Gemini Interactions API for stateful multi-turn conversations, background deep research tasks, streaming responses, function calling, and agentic workflows.
SKILL.md
Gemini Interactions API Skill
The Interactions API provides stateful, multi-turn conversation management with support for background deep research agents, function calling, and streaming. Use this for agent workflows that require maintaining conversation state across multiple requests.
Dependencies
| Dependency | Required? | Why |
|---|---|---|
gemini-api skill |
No | Recommended: for understanding basic Gemini setup |
$GEMINI_KEY |
Yes | Stand-in for the user's Gemini key (use with vault-curl) |
google-genai >= 1.55.0 |
No | Python SDK (or @google/genai >= 1.33.0 for JavaScript): only with the vault proxy (see below) |
Pre-flight checks:
[ -n "$GEMINI_KEY" ] && echo present || vault-curl --secrets- Not in your env but listed by
vault-curl --secrets(added after you started): use that entry'ssurrogatestring in place of$GEMINI_KEY. No restart is needed. - Agents not yet moved to the vault: if there is no
GEMINI_KEYanywhere but aGEMINI_API_KEYvariable is set, it holds a real key: use plaincurlwith that variable in the samex-goog-api-keyheader. Never print it. - Nothing found: ask the user to add a Gemini key in MyClawBots → Settings → Integrations → Google AI (free at aistudio.google.com). Never ask them to paste a key into chat.
- Verify Python 3.9+ or Node.js 18+ is installed
- Verify
google-genai >= 1.55.0is installed:pip list | grep google-genai - Ensure
gemini-apiskill documentation is available for reference
Prerequisites
- A Gemini key saved in MyClawBots (you get the stand-in
$GEMINI_KEY; see "Your Gemini key" below) - Python 3.9+ or Node.js 18+
google-genai >= 1.55.0(Python) or@google/genai >= 1.33.0(JavaScript)
Your Gemini key
You never see the real key: $GEMINI_KEY holds a stand-in (mcb_sec_…) that only works through vault-curl, which swaps in the real key on the way to generativelanguage.googleapis.com. Put it only in the x-goog-api-key header (never ?key=, the body or a file), and never print it. Don't use OpenClaw's built-in secrets tool: these keys are not stored there.
REST with vault-curl always works:
vault-curl -sS "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"gemini-3-flash-preview","input":"Explain async/await in Python"}'
The Python examples below send the stand-in straight from the SDK, so they work only when AGENTS.md says plain curl and SDKs work (the MyClawBots vault proxy is on). Otherwise use the REST form above.
Installation
pip install google-genai
Current Supported Models
Use these models with the Interactions API:
- gemini-3.1-pro-preview - Advanced reasoning, longest context (128K)
- gemini-3-flash-preview - Fast, efficient, multimodal
- deep-research-pro-preview-12-2025 - For background research tasks (async)
Deprecated: gemini-3-flash, gemini-3-pro are no longer recommended.
Quick Start: Basic Interaction
import os
from google import genai
# The stand-in for the user's key; needs the vault proxy (see "Your Gemini key")
if not os.environ.get('GEMINI_KEY'):
raise ValueError("GEMINI_KEY not set. Run `vault-curl --secrets` or ask the user to add a Gemini key in MyClawBots.")
client = genai.Client(api_key=os.environ['GEMINI_KEY'])
# Create a single interaction
response = client.models.create_interaction(
model="gemini-3.1-pro-preview",
system_instruction="You are a helpful coding assistant.",
user_input="Explain async/await in Python"
)
# Access outputs
for output in response.outputs:
if output.text:
print(output.text)
# Save to gws for persistence
interaction_id = response.interaction_id
print(f"Interaction ID: {interaction_id}")
Stateful Conversations with Memory
Use previous_interaction_id to continue a conversation:
# First turn
response1 = client.models.create_interaction(
model="gemini-3.1-pro-preview",
system_instruction="You are a Python tutor.",
user_input="What is a decorator?"
)
interaction_id = response1.interaction_id
# Second turn - continue with conversation history
response2 = client.models.create_interaction(
model="gemini-3.1-pro-preview",
user_input="Can you show me an example?",
previous_interaction_id=interaction_id
)
for output in response2.outputs:
if output.text:
print(output.text)
Deep Research Agent (Background Task)
Use the deep-research-pro-preview-12-2025 agent for long-running analysis:
# Start async research
response = client.models.create_interaction(
model="deep-research-pro-preview-12-2025",
user_input="Research the latest advances in quantum computing",
config={"background": True} # Runs asynchronously
)
interaction_id = response.interaction_id
print(f"Research started. Interaction ID: {interaction_id}")
# Later, poll for results
import time
while True:
result = client.models.get_interaction(interaction_id)
if result.state == "COMPLETED":
for output in result.outputs:
if output.text:
print(output.text)
break
print("Still researching...")
time.sleep(5)
Streaming Responses
For real-time output streaming:
response = client.models.create_interaction_stream(
model="gemini-3.1-pro-preview",
user_input="Write a Python function to sort a list"
)
for chunk in response:
for output in chunk.outputs:
if output.text:
print(output.text, end="", flush=True)
print()
Function Calling
Define tools for the model to call:
response = client.models.create_interaction(
model="gemini-3.1-pro-preview",
user_input="What's the weather in San Francisco?",
tools=[
{
"name": "get_weather",
"description": "Gets weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"}
}
}
}
]
)
# Check for function calls in outputs
for output in response.outputs:
if output.function_call:
print(f"Called: {output.function_call.name}")
print(f"Args: {output.function_call.args}")
Data Model: Output Types
Each interaction returns an outputs array with multiple possible types:
- text - Plain text response
- thought - Internal reasoning (from deep-research agent)
- function_call - Tool invocation with arguments
- image - Generated or analyzed image
- code_execution_result - Output from code interpreter
Key Differences from generateContent
- Stateful: Interactions maintain conversation history via
interaction_id - Async support: Deep research agents run in background
- Structured outputs: Consistent
outputsarray structure - No streaming limit: Interactions support unlimited streaming
- Cost: Interactions may be cheaper per token for repeated turns
For simple one-shot requests, see the gemini-api skill for basic generateContent.
Storage & Interaction Scope
- Interactions are stored temporarily per request
- Save
interaction_idtogwsfor long-term persistence - Interaction-scoped config applies only within that conversation
- Use
system_instructionat interaction creation for context
Documentation Lookup
For additional capabilities:
- Official Interactions API docs
- Check
llms.txtin this skill directory for model capabilities - See
gemini-apiskill for basic text/image generation, multimodal understanding
Cost
Interactions API pricing:
- Input tokens: $0.05 per 1M (gemini-3.1-pro)
- Output tokens: $0.15 per 1M (gemini-3.1-pro)
- Deep research: Usage-based, may incur higher costs
Costs are the same as the consumer Gemini API.
Related Skills
- gemini-api: Basic text/image generation and multimodal understanding
- gemini-live-api: Real-time voice/video streaming
- vertex-ai-api: Enterprise Interactions API with Vertex AI
Example: Content Writer Agent
# Create an interaction for iterative content writing
response = client.models.create_interaction(
model="gemini-3.1-pro-preview",
system_instruction="You are a professional content writer.",
user_input="Write a blog post intro about AI in healthcare"
)
# Get feedback and refine
if response.outputs[0].text:
draft = response.outputs[0].text
# Continue with feedback
response2 = client.models.create_interaction(
model="gemini-3.1-pro-preview",
user_input="Make it more engaging and add statistics",
previous_interaction_id=response.interaction_id
)
refined = response2.outputs[0].text
print(refined)