I once opened the Logs page in AI Studio and stared at an empty table.
The calls were going through. Responses were coming back. Nothing was listed. I suspected key permissions, then the project selector, and took a long detour before landing on the real cause. It was not that someone had changed a logging setting. The storage default is inverted between the two APIs, and I had never looked.
Logs from generateContent and logs from the Interactions API land on the same page, but they start from opposite defaults. And this setting is not purely about observability. Flip it the wrong way and your conversations stop continuing.
If the table is empty, check the per-API default first
Here is what the official documentation specifies.
| API | Default for store | What it means |
|---|---|---|
| Interactions API | store=true | Stored by default, which is what makes server-side conversation state convenient |
Generate Content API (generateContent) | store=false | Not stored by default. You enable it per request or at the project level |
I was on the second row. No matter how many times I exercised a feature built on generateContent, nothing was going to appear while the default was in place. The logging feature was not broken. It simply had not been turned on.
There is a second precondition that is easy to skip past: log storage is only available for projects on the Gemini API paid tier. If you are still evaluating on the free tier, correct settings will not fill the table. Start suspecting keys and scopes before you check this, and you will burn an afternoon.
You can enable storage per request, or per project from the Settings panel in AI Studio. The two APIs are toggled independently.
The toggle is not only an observability switch
This is the part worth remembering.
If you turn Interactions API logging off in the AI Studio Settings panel, the API also stops automatically storing and retrieving conversation history unless you explicitly override it on a per-request basis.
The Interactions API is built around passing previous_interaction_id to continue a thread. The assumption that the previous turn is still there is exactly what store=true provides. Log storage and conversation state hang off the same switch.
So you flip it off for observability reasons, and some time later a report arrives saying the assistant has stopped remembering context. Cause and symptom are far apart in time, which makes this a particularly unpleasant class of incident to reconstruct. As an indie developer I had no change log for settings other than my own memory, which did not help.
There are legitimate reasons to reduce what gets stored, whether for privacy or for cost. Even then, I would rather decide it at the call site than drop a project-wide toggle.
Set store explicitly at every call site
Stop relying on defaults and state the value in code. Then nothing shifts when someone changes the project setting, including a future version of yourself several months from now.
from google import genai
client = genai.Client()
# generateContent defaults to store=False.
# Set it to True explicitly for calls you want to inspect later.
response = client.models.generate_content(
model="gemini-3.7-flash",
contents="Explain quantum entanglement in simple terms.",
config={"store": True},
)
print(response.text)The Interactions API runs the other direction. The default is store=True, so you only pass False for calls you deliberately do not want retained. Remember that such a call keeps no conversation state either, so treat it as a marker for genuinely one-shot requests.
from google import genai
client = genai.Client()
# A one-shot call that will not be continued.
# With store=False there is no history, so previous_interaction_id cannot chain to it.
interaction = client.interactions.create(
model="gemini-3.7-flash",
input="Explain quantum entanglement in simple terms.",
store=False,
)
print(interaction.outputs[-1].text)Same idea in JavaScript.
import { GoogleGenAI } from '@google/genai';
const client = new GoogleGenAI({});
// Never drop store on a call that is meant to be continued.
const interaction = await client.interactions.create({
model: 'gemini-3.7-flash',
input: 'Explain quantum entanglement in simple terms.',
store: true,
});
console.log(interaction.outputs[interaction.outputs.length - 1].text);I now treat store as a value decided once per feature rather than once per call. Threaded features are pinned to true; disposable classification and summarization are pinned to false. Consolidating call sites keeps that decision visible as a single line of code, which is the subject of Folding Scattered Call Sites Into One Front Door: Migrating to the Interactions API for Automation.
A project with no keys left is a project with no visible logs
There is one more sharp edge.
Displaying logs requires at least one active API key in the project. Delete every key, and you lose visibility into that project's logs.
This bites hardest during a key leak. You rush to revoke the key you accidentally published. It happens to be the last one in the project. And now, at precisely the moment you want to see what that key was calling, the history is gone.
The fix is unglamorous: create the replacement key before deleting the compromised one. Do not invert the order. Order is exactly what slips under pressure, so it is worth one line in the runbook.
What never gets logged, and the 55-day clock
Knowing what is out of scope shortens triage. The documented exclusions are:
| Excluded | Notes |
|---|---|
| Imagen and Veo | Image and video generation models |
| Gemini embedding models | Any embedding call |
| Gemini Robotics model | Robotics-oriented models |
| Inputs containing videos, GIFs, or PDFs | The whole call is excluded, not just the attachment |
| Public Preview Agents in the Gemini API | Managed Agents calls are outside logging as well |
That fourth row matters if you process documents. Your text calls appear, your PDF calls do not, and it looks like a configuration problem when it is documented behavior.
Retention is worth deciding early too. Logs expire and are marked for deletion after a default window of 55 days. You can set a project to 7, 14, 28, or 55 days. Logs saved into a dataset do not expire: filter the list, select the entries, create a dataset, and export it as CSV, JSONL, or to Google Sheets.
The takeaway is that AI Studio logs are not durable storage. If your operations involve tracing a single call from three weeks ago, you need a record of your own alongside the dashboard. I covered how to split those responsibilities in Don't Let the AI Studio Developer Log Be Your Source of Truth: A Two-Layer Way to Observe the Interactions API.
Where to start
Open the feature you are running right now and check whether store is stated explicitly in the code. Anywhere you are leaning on a default is where behavior will be hardest to explain later.
If your problem is on the other side, where responses come back empty rather than unlogged, Reverse-Engineering Empty Gemini API Responses with finish_reason is the better entry point. Missing logs and empty responses live in different layers, and separating them shortens the search.
There are probably other settings that quietly change conversational assumptions like this one does. I will keep writing them up as I find them. Thank you for reading.