# How to Implement Stateful Multi-Turn Conversations with the Gemini Interactions API

> Learn to implement stateful multi turn conversations with the Gemini Interactions API. Easily manage context by setting store on your first request and passing the interaction ID.

- Repository: [Google/skills](https://github.com/google/skills)
- Tags: how-to-guide
- Published: 2026-06-11

---

**Set `store: true` on your first request to persist the interaction, then pass the returned `id` as `previous_interaction_id` in subsequent calls to maintain conversation context across turns.**

The Gemini Interactions API provides a server-managed conversation layer that automatically retains chat history, eliminating the need to manually resend the full message transcript with each request. According to the `google/skills` repository, this stateful approach uses the unified Google Gen AI SDK to handle persistent multi-turn dialogues through simple identifier linking.

## Prerequisites and SDK Setup

You must use the **unified Google Gen AI SDK** to access the Interactions API. Legacy packages are explicitly not supported.

- **Python**: `google-genai >= 2.0.0`
- **TypeScript/JavaScript**: `@google/genai >= 2.0.0`

Legacy packages such as `google-cloud-aiplatform` or `google-generativeai` will not work for Interactions API calls. As documented in [`skills/cloud/gemini-interactions-api/SKILL.md`](https://github.com/google/skills/blob/main/skills/cloud/gemini-interactions-api/SKILL.md), all client-side code should initialize using the new unified SDK.

## Core Concepts of Stateful Conversation

### State Persistence with `store` and `previous_interaction_id`

When you set `store: true` on a request, the service persists the interaction in the Gemini Enterprise Agent Platform and returns an `id`. To continue the conversation, include this `id` as `previous_interaction_id` (or `previousInteractionId` in TypeScript) in the next request.

This creates a **chain of linked interactions** where the server automatically retrieves prior user utterances, tool calls, and system messages without requiring you to resend the full transcript.

### Turn-Scoped Parameters

Critical parameters such as `tools`, `system_instruction`, and `generation_config` are **not retained** between turns. You must supply these on every request to ensure the model has the correct context and capabilities for each specific turn.

## Implementing Multi-Turn Conversations in Python

The following example demonstrates a two-turn conversation where the first interaction is stored and the second references it via `previous_interaction_id`.

```python
from google import genai

# Initialise the unified SDK (environment variables already set)

client = genai.Client()

# Turn 1 – store the conversation

turn1 = client.interactions.create(
    model="gemini-3-flash-preview",
    input="Hi! My name is Alice. I'm building an AI agent.",
    store=True,
)
print("Turn 1:", turn1.steps[-1].content[0].text)

# Turn 2 – reference the stored state

turn2 = client.interactions.create(
    model="gemini-3-flash-preview",
    input="What did I tell you about myself?",
    previous_interaction_id=turn1.id,
)
print("Turn 2:", turn2.steps[-1].content[0].text)

```

*Source:* [`skills/cloud/gemini-interactions-api/SKILL.md`](https://github.com/google/skills/blob/main/skills/cloud/gemini-interactions-api/SKILL.md)

## Working with Streaming Responses

Add `stream: true` to receive incremental response chunks, which is ideal for real-time UI updates. The endpoint returns an iterable (Python) or async generator (TypeScript) that yields chunks as they are generated.

```typescript
import { GoogleGenAI } from "@google/genai";

const ai = new GoogleGenAI();

const stream = await ai.interactions.create({
  model: "gemini-3-flash-preview",
  input: "Write a short poem about debugging.",
  stream: true,
});

for await (const chunk of stream) {
  if (chunk.steps) {
    const step = chunk.steps[chunk.steps.length - 1];
    if (step.content && step.content[0].text) {
      process.stdout.write(step.content[0].text);
    }
  }
}
console.log(); // finish line

```

## Advanced Patterns

### Structured JSON Output with Pydantic

The API supports typed JSON responses using Pydantic models in Python. Specify the `response_format` parameter with your model class.

```python
from google import genai
from pydantic import BaseModel, Field

class Book(BaseModel):
    title: str = Field(description="Book title")
    author: str = Field(description="Book author")
    year_published: int

client = genai.Client()

interaction = client.interactions.create(
    model="gemini-3-flash-preview",
    input="Recommend a sci-fi classic.",
    response_format=Book,
)

print(interaction.steps[-1].content[0].text)   # → valid JSON matching Book schema

```

### Function Calling with State Preservation

When the model requests a tool call, you execute the function and send the result back in a follow-up turn, preserving continuity via `previous_interaction_id`.

```python
def get_stock_price(ticker: str) -> float:
    return {"GOOG": 175.5}.get(ticker.upper(), 100.0)

client = genai.Client()

# Turn 1 – ask the model a question and provide the tool

first = client.interactions.create(
    model="gemini-3-flash-preview",
    input="What is the price of GOOG?",
    tools=[get_stock_price],
)

# Detect tool request

if first.steps[-1].tool_calls:
    call = first.steps[-1].tool_calls[0]
    price = get_stock_price(call.args["ticker"])

    # Turn 2 – send the result back, referencing the previous interaction

    second = client.interactions.create(
        model="gemini-3-flash-preview",
        input=f"The price of {call.args['ticker']} is ${price}.",
        previous_interaction_id=first.id,
    )
    print(second.steps[-1].content[0].text)

```

## Raw REST API Implementation

If you cannot use the SDK, the Interactions API accepts standard HTTP POST requests to the `v1beta1` endpoint. The payload includes `agent`, `input`, `store`, and `previous_interaction_id` fields.

```bash
PROJECT_ID="my-project"
AGENT_ID="projects/${PROJECT_ID}/locations/global/agents/my-agent"
ACCESS_TOKEN=$(gcloud auth print-access-token)

# First turn – store interaction

curl -X POST "https://aiplatform.googleapis.com/v1beta1/projects/${PROJECT_ID}/locations/global/interactions" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
        "agent": "'"${AGENT_ID}"'",
        "input": [{"role":"user","content":[{"type":"text","text":"Hello, I'm Sam."}]}],
        "store": true
      }' | jq .id > prev_id.txt

# Second turn – continue conversation

PREV_ID=$(cat prev_id.txt)
curl -X POST "https://aiplatform.googleapis.com/v1beta1/projects/${PROJECT_ID}/locations/global/interactions" \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
        "agent": "'"${AGENT_ID}"'",
        "input": [{"role":"user","content":[{"type":"text","text":"What did I just say?"}]}],
        "previous_interaction_id": "'"${PREV_ID}"'"
      }'

```

## Summary

- **Use the unified SDK** (`google-genai` or `@google/genai` >= 2.0.0) as legacy packages are not supported for the Interactions API.
- **Enable state persistence** by setting `store: true` on the initial request to receive a persistent interaction `id`.
- **Link subsequent turns** by passing the previous interaction's `id` as `previous_interaction_id` in following requests.
- **Resend turn-scoped parameters** (`tools`, `system_instruction`, `generation_config`) on every request since they are not retained server-side.
- **Support streaming and structured output** by setting `stream: true` or `response_format` as needed.

## Frequently Asked Questions

### What happens if I don't set `store: true` on the first turn?

The interaction will not be persisted to the Gemini Enterprise Agent Platform. Subsequent requests will not be able to reference this turn via `previous_interaction_id`, effectively treating each request as a stateless, independent call with no memory of prior context.

### Do I need to resend system instructions and tools on every turn?

Yes. Parameters such as `system_instruction`, `tools`, and `generation_config` are **turn-scoped** and are not retained between interactions. You must include them in every request to ensure the model behaves consistently across the conversation chain.

### Can I use the legacy Google AI Python SDK with the Interactions API?

No. According to [`skills/cloud/gemini-interactions-api/SKILL.md`](https://github.com/google/skills/blob/main/skills/cloud/gemini-interactions-api/SKILL.md), packages like `google-generativeai` and `google-cloud-aiplatform` are **not supported** for Interactions API calls. You must migrate to the unified `google-genai` SDK (Python) or `@google/genai` (TypeScript) version 2.0.0 or higher.

### How does the Interactions API handle function calling across multiple turns?

When the model generates a `tool_calls` request in one turn, you execute the function locally and send the result back in a subsequent turn using `previous_interaction_id` to link to the prior interaction. This preserves the conversation continuity while allowing the model to incorporate the function result into its final response.