এই নির্দেশিকাটি আপনাকে generateContent API থেকে Interactions API-তে স্থানান্তরিত হতে সাহায্য করবে।
জেমিনি দিয়ে কিছু তৈরি করার জন্য ইন্টারঅ্যাকশনস এপিআই হলো আদর্শ ইন্টারফেস। এটি এজেন্টিক ওয়ার্কফ্লো, সার্ভার-সাইড স্টেট ম্যানেজমেন্ট এবং জটিল মাল্টি-মোডাল ও মাল্টি-টার্ন কথোপকথনের জন্য বিশেষভাবে তৈরি, তবে একই সাথে এটি সাধারণ স্টেটলেস সিঙ্গেল-টার্ন অনুরোধগুলোকেও সম্পূর্ণরূপে সমর্থন করে। যদিও generateContent সম্পূর্ণরূপে সমর্থিত, আমরা সমস্ত নতুন ডেভেলপমেন্টের জন্য ইন্টারঅ্যাকশনস এপিআই ব্যবহারের পরামর্শ দিই।
কেন অভিবাসন করবেন?
ইন্টারঅ্যাকশনস এপিআই জেমিনি দিয়ে নির্মাণের জন্য আরও সুসংগঠিত ও শক্তিশালী একটি উপায় প্রদান করে:
- সার্ভার-সাইড হিস্ট্রি ম্যানেজমেন্ট :
previous_interaction_idএর মাধ্যমে একাধিক ধাপের প্রবাহকে সহজ করা হয়েছে। সার্ভার ডিফল্টরূপে স্টেট সক্রিয় করে (store=true), কিন্তু আপনিstore=falseসেট করে স্টেটলেস আচরণ বেছে নিতে পারেন। - পর্যবেক্ষণযোগ্য নির্বাহ ধাপসমূহ : টাইপ করা ধাপগুলো জটিল ফ্লো ডিবাগ করা এবং অন্তর্বর্তী ইভেন্টগুলোর (যেমন চিন্তা বা সার্চ উইজেট) জন্য UI রেন্ডার করা সহজ করে তোলে।
- এজেন্টিক ওয়ার্কফ্লোর জন্য নির্মিত : টাইপ করা এক্সিকিউশন স্টেপগুলোর মাধ্যমে বহু-ধাপের টুল ব্যবহার, অর্কেস্ট্রেশন এবং জটিল রিজনিং ফ্লো-এর জন্য নেটিভ সাপোর্ট।
- দীর্ঘ সময় ধরে চলা এবং ব্যাকগ্রাউন্ড টাস্ক :
background=trueব্যবহার করে Deep Think এবং Deep Research-এর মতো সময়সাপেক্ষ অপারেশনগুলিকে ব্যাকগ্রাউন্ড প্রসেসে অফলোড করা সমর্থন করে। - নতুন মডেল এবং সক্ষমতাগুলিতে অ্যাক্সেস : ভবিষ্যতে, মূল মেইনলাইন ফ্যামিলির বাইরের নতুন মডেলগুলি, নতুন এজেন্টিক সক্ষমতা এবং টুল সহ, শুধুমাত্র ইন্টারঅ্যাকশনস এপিআই-তে চালু করা হবে। বিদ্যমান ব্যবহারের ক্ষেত্রগুলির জন্য
generateContentসম্পূর্ণরূপে সমর্থিত হতে থাকবে।
মৌলিক ইনপুট/আউটপুট
এই বিভাগে দেখানো হয়েছে কীভাবে একটি সাধারণ টেক্সট তৈরির অনুরোধ মাইগ্রেট করতে হয়।
( generateContent ) এর আগে
generateContent API-টি স্টেটলেস এবং সরাসরি রেসপন্স ফেরত দেয়। রেসপন্স স্ট্রাকচারটি আউটপুটকে candidates একটি লিস্টে মোড়কজাত করে, যার প্রতিটিতে পার্স করার জন্য parts একটি তালিকা সহ content থাকে।
পাইথন
from google import genai
client = genai.Client()
response = client.models.generate_content(
model="gemini-2.5-flash", contents="Tell me a joke."
)
print(response.text)
জাভাস্ক্রিপ্ট
import { GoogleGenAI } from '@google/genai';
const ai = new GoogleGenAI({});
const response = await ai.models.generateContent({
model: "gemini-2.5-flash",
contents: "Tell me a joke.",
});
console.log(response.text);
বিশ্রাম
# Request
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"contents": [{
"parts": [{
"text": "Tell me a joke."
}]
}]
}'
# Response
{
"candidates": [
{
"content": {
"parts": [
{
"text": "Why did the chicken cross the road? To get to the other side!"
}
],
"role": "model"
},
"finishReason": "STOP",
"index": 0
}
],
"usageMetadata": {
"promptTokenCount": 4,
"candidatesTokenCount": 12,
"totalTokenCount": 16
}
}
পরে (ইন্টারঅ্যাকশন এপিআই)
ইন্টারঅ্যাকশনস এপিআই একটি steps টাইমলাইন সহ একটি সংরক্ষিত ইন্টারঅ্যাকশন রিসোর্স ফেরত দেয়। ক্যান্ডিডেট এবং পার্টস ট্র্যাভার্স করার পরিবর্তে, কাঙ্ক্ষিত আউটপুট টাইপটি খুঁজে পেতে steps অ্যারেটি পরীক্ষা করুন।
পাইথন
from google import genai
client = genai.Client()
# The input can be a simple string shorthand
interaction = client.interactions.create(
model="gemini-3-flash-preview", input="Tell me a joke."
)
# Inspect the steps manually
for step in interaction.steps:
if step.type == "model_output":
print(step.content[0].text)
জাভাস্ক্রিপ্ট
import { GoogleGenAI } from '@google/genai';
const client = new GoogleGenAI({});
let interaction = await client.interactions.create({
model: 'gemini-3-flash-preview',
input: 'Tell me a joke.'
});
// Manual inspection
const modelStep = interaction.steps.find(s => s.type === 'model_output');
console.log(modelStep.content[0].text);
বিশ্রাম
# Request
curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"model": "gemini-3-flash-preview",
"input": "Tell me a joke."
}'
# Response
{
"id": "int_123",
"status": "completed",
"steps": [
{
"type": "user_input",
"status": "done",
"content": [
{
"type": "text",
"text": "Tell me a joke."
}
]
},
{
"type": "model_output",
"status": "done",
"content": [
{
"type": "text",
"text": "Why did the chicken cross the road?"
}
]
}
]
}
একাধিক পালা কথোপকথন
ইন্টারঅ্যাকশনস এপিআই ডিফল্টরূপে ইন্টারঅ্যাকশনগুলো সংরক্ষণ করে, যা একাধিক পালাবিশিষ্ট কথোপকথনের জন্য সার্ভার-সাইড স্টেট ম্যানেজমেন্ট সক্ষম করে।
( generateContent ) এর আগে
generateContent এ, আপনাকে contents অ্যারে অথবা একটি ক্লায়েন্ট-সাইড চ্যাট হেল্পার ব্যবহার করে কথোপকথনের ইতিহাস ম্যানুয়ালি পরিচালনা করতে হবে।
পাইথন
চ্যাট হেল্পার ব্যবহার করা (প্রস্তাবিত)
from google import genai
client = genai.Client()
chat = client.chats.create(model="gemini-2.5-flash")
response1 = chat.send_message("Hi, my name is Phil.")
print(response1.text)
response2 = chat.send_message("What is my name?")
print(response2.text)
ম্যানুয়ালি ইতিহাস পরিচালনা করা
from google import genai
from google.genai import types
client = genai.Client()
# The second turn requires sending the entire history
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=[
types.Content(
role="user", parts=[types.Part.from_text("Hi, my name is Phil.")]
),
types.Content(
role="model",
parts=[types.Part.from_text("Hi Phil, how can I help you?")],
),
types.Content(
role="user", parts=[types.Part.from_text("What is my name?")]
),
],
)
print(response.text)
জাভাস্ক্রিপ্ট
চ্যাট হেল্পার ব্যবহার করা (প্রস্তাবিত)
import { GoogleGenAI } from '@google/genai';
const client = new GoogleGenAI({});
const chat = client.chats.create({ model: 'gemini-2.5-flash' });
let response = await chat.sendMessage({ message: 'Hi, my name is Phil.' });
console.log(response.text);
response = await chat.sendMessage({ message: 'What is my name?' });
console.log(response.text);
ম্যানুয়ালি ইতিহাস পরিচালনা করা
import { GoogleGenAI } from '@google/genai';
const client = new GoogleGenAI({});
// The second turn requires sending the entire history
const response = await client.models.generateContent({
model: 'gemini-2.5-flash',
contents: [
{ role: 'user', parts: [{ text: 'Hi, my name is Phil.' }] },
{ role: 'model', parts: [{ text: 'Hi Phil, how can I help you?' }] },
{ role: 'user', parts: [{ text: 'What is my name?' }] }
]
});
console.log(response.text);
বিশ্রাম
# Request (the second turn requires sending the entire history)
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"contents": [
{"role": "user", "parts": [{"text": "Hi, my name is Phil."}]},
{"role": "model", "parts": [{"text": "Hi Phil, how can I help you?"}]},
{"role": "user", "parts": [{"text": "What is my name?"}]}
]
}'
# Response
{
"candidates": [
{
"content": {
"parts": [
{
"text": "Your name is Phil."
}
],
"role": "model"
},
"finishReason": "STOP",
"index": 0
}
]
}
পরে (ইন্টারঅ্যাকশন এপিআই)
ইন্টারঅ্যাকশনস এপিআই সার্ভারে স্টেট পরিচালনা করে। আপনি previous_interaction_id উল্লেখ করে কথোপকথন চালিয়ে যেতে পারেন।
পাইথন
from google import genai
client = genai.Client()
# First turn
interaction1 = client.interactions.create(
model="gemini-3-flash-preview", input="Hi, my name is Phil."
)
print(interaction1.steps[-1].content[0].text)
# Second turn (passing previous_interaction_id)
interaction2 = client.interactions.create(
model="gemini-3-flash-preview",
previous_interaction_id=interaction1.id,
input="What is my name?",
)
print(interaction2.steps[-1].content[0].text)
জাভাস্ক্রিপ্ট
import { GoogleGenAI } from '@google/genai';
const client = new GoogleGenAI({});
// First turn
let interaction = await client.interactions.create({
model: 'gemini-3-flash-preview',
input: 'Hi, my name is Phil.'
});
console.log(interaction.steps.at(-1).content[0].text);
// Second turn
interaction = await client.interactions.create({
model: 'gemini-3-flash-preview',
previous_interaction_id: interaction.id,
input: 'What is my name?'
});
console.log(interaction.steps.at(-1).content[0].text);
বিশ্রাম
# First Request
curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"model": "gemini-3-flash-preview",
"input": "Hi, my name is Phil."
}'
# Second Request (using ID from first response)
curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"model": "gemini-3-flash-preview",
"previous_interaction_id": "int_123",
"input": "What is my name?"
}'
# Response to Second Request
{
"id": "int_123",
"steps": [
{
"type": "user_input",
"status": "done",
"content": [{ "type": "text", "text": "Hi, my name is Phil." }]
},
{
"type": "model_output",
"status": "done",
"content": [{ "type": "text", "text": "Hello Phil! How can I help you today?" }]
},
{
"type": "user_input",
"status": "done",
"content": [{ "type": "text", "text": "What is my name?" }]
},
{
"type": "model_output",
"status": "done",
"content": [{ "type": "text", "text": "Your name is Phil." }]
}
]
}
মাল্টিমোডাল ইনপুট
উভয় এপিআই-ই মাল্টিমোডাল ইনপুট (টেক্সট, ছবি, ভিডিও, ইত্যাদি) সমর্থন করে।
( generateContent ) এর আগে
generateContent ফাংশনে, আপনি contents অ্যারের মধ্যে parts একটি তালিকা পাস করেন। রেসপন্সটি প্রথম ক্যান্ডিডেটের parts আউটপুট ফেরত দেয়।
পাইথন
from google import genai
from google.genai import types
client = genai.Client()
with open("sample.jpg", "rb") as f:
image_bytes = f.read()
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=[
types.Part.from_bytes(data=image_bytes, mime_type="image/jpeg"),
"Describe this image.",
],
)
print(response.text)
বিশ্রাম
# Request
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"contents": [{
"parts": [
{
"inlineData": {
"mimeType": "image/jpeg",
"data": "..."
}
},
{
"text": "Describe this image."
}
]
}]
}'
# Response
{
"candidates": [
{
"content": {
"parts": [
{
"text": "This is a picture of a beautiful sunset."
}
],
"role": "model"
}
}
]
}
পরে (ইন্টারঅ্যাকশন এপিআই)
ইন্টারঅ্যাকশনস এপিআই-তে, আপনি input ফিল্ডে একটি অ্যারে পাস করেন। টাইমলাইনে model_output স্টেপটি খুঁজে আপনি আউটপুট কন্টেন্ট পুনরুদ্ধার করেন।
পাইথন
from google import genai
client = genai.Client()
# Assuming you have an image file
with open("sample.jpg", "rb") as f:
image_bytes = f.read()
interaction = client.interactions.create(
model="gemini-3-flash-preview",
input=[
{
"type": "image",
"mime_type": "image/jpeg",
"data": image_bytes,
},
{"type": "text", "text": "Describe this image."},
],
)
for step in interaction.steps:
if step.type == "model_output":
print(step.content[0].text)
জাভাস্ক্রিপ্ট
import { GoogleGenAI } from '@google/genai';
import * as fs from 'fs';
const client = new GoogleGenAI({});
const imageBytes = fs.readFileSync('sample.jpg').toString('base64');
const interaction = await client.interactions.create({
model: 'gemini-3-flash-preview',
input: [
{
type: 'image',
mime_type: 'image/jpeg',
data: imageBytes
},
{
type: 'text',
text: 'Describe this image.'
}
]
});
for (const step of interaction.steps) {
if (step.type === 'model_output') {
console.log(step.content[0].text);
}
}
বিশ্রাম
# Request
curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"model": "gemini-3-flash-preview",
"input": [
{
"type": "image",
"mime_type": "image/jpeg",
"data": "..."
},
{
"type": "text",
"text": "Describe this image."
}
]
}'
# Response
{
"id": "int_multimodal",
"steps": [
{
"type": "user_input",
"status": "done",
"content": [
{
"type": "image",
"mime_type": "image/jpeg",
"data": "..."
},
{
"type": "text",
"text": "Describe this image."
}
]
},
{
"type": "model_output",
"status": "done",
"content": [
{
"type": "text",
"text": "This is a picture of a beautiful sunset over the mountains."
}
]
}
]
}
কাঠামোগত আউটপুট
মডেলটিকে একটি নির্দিষ্ট স্কিমার সাথে মেলে এমন JSON ফেরত দিতে, রেসপন্স ফরম্যাটটি কনফিগার করুন।
( generateContent ) এর আগে
generateContent এ, আপনি generationConfig অবজেক্টের ভিতরে থাকা response_format ফিল্ড ব্যবহার করে আউটপুট ফরম্যাট কনফিগার করেন।
পাইথন
from google import genai
from google.genai import types
from pydantic import BaseModel
client = genai.Client()
class Recipe(BaseModel):
recipe_name: str
ingredients: list[str]
response = client.models.generate_content(
model="gemini-2.5-flash",
contents="Give me a recipe for chocolate chip cookies.",
config=types.GenerateContentConfig(
response_format=[
{
"type": "text",
"mime_type": "application/json",
"schema": Recipe,
}
]
),
)
print(response.text)
বিশ্রাম
# Request
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"contents": [{
"parts": [{
"text": "Give me a recipe for chocolate chip cookies."
}]
}],
"generationConfig": {
"responseFormat": [
{
"type": "text",
"mimeType": "application/json",
"schema": {
"type": "OBJECT",
"properties": {
"recipe_name": { "type": "STRING" },
"ingredients": {
"type": "ARRAY",
"items": { "type": "STRING" }
}
},
"required": ["recipe_name", "ingredients"]
}
}
]
}
}'
# Response
{
"candidates": [
{
"content": {
"parts": [
{
"text": "{\n \"recipe_name\": \"Chocolate Chip Cookies\",\n \"ingredients\": [\n \"1 cup butter\",\n \"1 cup sugar\",\n \"2 cups flour\",\n \"1 cup chocolate chips\"\n ]\n}"
}
],
"role": "model"
}
}
]
}
পরে (ইন্টারঅ্যাকশন এপিআই)
ইন্টারঅ্যাকশনস এপিআই-তে, আউটপুট ফরম্যাট কন্ট্রোলগুলো একটি টপ-লেভেল response_format অ্যারেতে স্থানান্তরিত হয়।
পাইথন
from google import genai
from pydantic import BaseModel
client = genai.Client()
class Recipe(BaseModel):
recipe_name: str
ingredients: list[str]
interaction = client.interactions.create(
model="gemini-3-flash-preview",
input="Give me a recipe for chocolate chip cookies.",
response_format=[
{
"type": "text",
"mime_type": "application/json",
"schema": Recipe,
}
],
)
for step in interaction.steps:
if step.type == "model_output":
print(step.content[0].text)
জাভাস্ক্রিপ্ট
import { GoogleGenAI } from '@google/genai';
const client = new GoogleGenAI({});
const interaction = await client.interactions.create({
model: 'gemini-3-flash-preview',
input: 'Give me a recipe for chocolate chip cookies.',
response_format: [
{
type: 'text',
mime_type: 'application/json',
schema: {
type: 'object',
properties: {
recipe_name: { type: 'string' },
ingredients: {
type: 'array',
items: { type: 'string' }
}
},
required: ['recipe_name', 'ingredients']
}
}
]
});
for (const step of interaction.steps) {
if (step.type === 'model_output') {
console.log(step.content[0].text);
}
}
বিশ্রাম
# Request
curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"model": "gemini-3-flash-preview",
"input": "Give me a recipe for chocolate chip cookies.",
"response_format": [
{
"type": "text",
"mime_type": "application/json",
"schema": {
"type": "OBJECT",
"properties": {
"recipe_name": { "type": "STRING" },
"ingredients": {
"type": "ARRAY",
"items": { "type": "STRING" }
}
},
"required": ["recipe_name", "ingredients"]
}
}
]
}'
# Response
{
"id": "int_structured",
"steps": [
{
"type": "user_input",
"status": "done",
"content": [{ "type": "text", "text": "Give me a recipe for chocolate chip cookies." }]
},
{
"type": "model_output",
"status": "done",
"content": [
{
"type": "text",
"text": "{\n \"recipe_name\": \"Chocolate Chip Cookies\",\n \"ingredients\": [\n \"1 cup butter\",\n \"1 cup sugar\",\n \"2 cups flour\",\n \"1 cup chocolate chips\"\n ]\n}"
}
]
}
]
}
মাল্টিমোডাল জেনারেশন
টেক্সট ছাড়া অন্য কোনো মাধ্যমে (যেমন ছবি বা অডিও) কন্টেন্ট তৈরি করার ক্ষেত্রে মূল পার্থক্যটি হলো, প্রতিক্রিয়াটি কীভাবে তৈরি করা মিডিয়াটিকে কাঠামোবদ্ধ করে।
( generateContent ) এর আগে
generateContent এ, রেসপন্সটি জেনারেট করা মিডিয়াকে সরাসরি ক্যান্ডিডেটের parts -এর মধ্যে রিটার্ন করে, সাধারণত inlineData তে base64 ডেটা হিসেবে।
# Response structure concept
{
"candidates": [
{
"content": {
"parts": [
{
"text": "Here is your generated image:"
},
{
"inlineData": {
"mimeType": "image/jpeg",
"data": "...base64..."
}
}
]
}
}
]
}
পরে (ইন্টারঅ্যাকশন এপিআই)
ইন্টারঅ্যাকশনস এপিআই-তে, তৈরি হওয়া মিডিয়া টাইমলাইনের একটি model_output স্টেপের content অ্যারের মধ্যে স্বতন্ত্র আইটেম হিসেবে প্রদর্শিত হয়, যা ইন্টারঅ্যাকশনটির কালানুক্রমিক প্রবাহ বজায় রাখে।
# Response structure concept
{
"id": "int_123",
"steps": [
{
"type": "model_output",
"status": "done",
"content": [
{
"type": "text",
"text": "Here is your generated image:"
},
{
"type": "image",
"mime_type": "image/jpeg",
"data": "...base64..." // Or a reference URL in future
}
]
}
]
}
এর ফলে ইনপুট এবং টেক্সট আউটপুট যেভাবে পরিচালনা করা হয়, তার সাথে রেসপন্স পার্সিং সামঞ্জস্যপূর্ণ থাকে—সবকিছুই টাইমলাইনের একটি ধাপ।
সার্ভার-সাইড টুলস
জেমিনি গুগল সার্চ গ্রাউন্ডিং-এর মতো বিল্ট-ইন সার্ভার-সাইড টুল সমর্থন করে। মূল পার্থক্য হলো, প্রতিক্রিয়াটি কীভাবে টুলের কার্যকারিতা উপস্থাপন করে।
( generateContent ) এর আগে
generateContent এ, সার্ভার-সাইড টুলগুলো মূলত দুর্বোধ্য। আপনি টুলটি সক্রিয় করেন এবং একটি পৃথক groundingMetadata অবজেক্টের মাধ্যমে চূড়ান্ত উত্তর পান। গুরুত্বপূর্ণ বিষয় হলো, সাইটেশনগুলো ইনলাইন থাকে না; groundingSupports groundingChunks মধ্যে থাকা ওয়েব সোর্সগুলোতে টেক্সট সেগমেন্টগুলোকে ম্যাপ করার জন্য ক্যারেক্টার ইনডেক্স ব্যবহার করে।
পাইথন
from google import genai
from google.genai import types
client = genai.Client()
response = client.models.generate_content(
model="gemini-2.5-flash",
contents="Who won Euro 2024?",
config=types.GenerateContentConfig(
tools=[{"google_search": {}}]
),
)
# Access search entry point (widget) and citations
metadata = response.candidates[0].grounding_metadata
if metadata.search_entry_point:
print(f"Search Entry Point: {metadata.search_entry_point.rendered_content}")
for support in metadata.grounding_supports:
print(f"Citation: {support.segment.text}")
জাভাস্ক্রিপ্ট
import { GoogleGenAI } from '@google/genai';
const client = new GoogleGenAI({});
const response = await client.models.generateContent({
model: 'gemini-2.5-flash',
contents: 'Who won Euro 2024?',
config: {
tools: [{ google_search: {} }]
}
});
const metadata = response.candidates[0].groundingMetadata;
if (metadata.searchEntryPoint) {
console.log(`Search Entry Point: ${metadata.searchEntryPoint.renderedContent}`);
}
for (const support of metadata.groundingSupports) {
console.log(`Citation: ${support.segment.text}`);
}
বিশ্রাম
# Request
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"contents": [{
"parts": [{
"text": "Who won Euro 2024?"
}]
}],
"tools": [{
"googleSearchRetrieval": {}
}]
}'
# Response
{
"candidates": [
{
"content": {
"parts": [
{
"text": "Spain won Euro 2024, defeating England 2-1 in the final. This victory marks Spain's record fourth European Championship title."
}
],
"role": "model"
},
"groundingMetadata": {
"webSearchQueries": [
"UEFA Euro 2024 winner",
"who won euro 2024"
],
"searchEntryPoint": {
"renderedContent": "<!-- HTML and CSS for the search widget -->"
},
"groundingChunks": [
{"web": {"uri": "https://vertexaisearch.cloud.google.com.....", "title": "aljazeera.com"}},
{"web": {"uri": "https://vertexaisearch.cloud.google.com.....", "title": "uefa.com"}}
],
"groundingSupports": [
{
"segment": {"startIndex": 0, "endIndex": 85, "text": "Spain won Euro 2024, defeatin..."},
"groundingChunkIndices": [0]
},
{
"segment": {"startIndex": 86, "endIndex": 210, "text": "This victory marks Spain's..."},
"groundingChunkIndices": [0, 1]
}
]
}
}
]
}
পরে (ইন্টারঅ্যাকশন এপিআই)
ইন্টারঅ্যাকশনস এপিআই-তে, সার্ভার-সাইড টুলগুলো সম্পূর্ণ টাইমলাইন স্বচ্ছতা প্রদান করে। এপিআইটি কল এবং ফলাফলকে স্বতন্ত্র এক্সিকিউশন steps ( google_search_call এবং google_search_result ) হিসেবে রেকর্ড করে, যার ফলে মডেলটি ঠিক কী ডেটা পুনরুদ্ধার করেছে তা প্রকাশ পায়।
তাছাড়া, এপিআইটি সাইটেশনগুলো ইনলাইনভাবেই ফেরত দেয়। একটি আলাদা মেটাডেটা অবজেক্ট থেকে ইনডেক্স ম্যাপ করার পরিবর্তে, model_output স্টেপের ভেতরের টেক্সট আইটেমটিতে নিজস্ব annotations অ্যারে থাকে, যা সরাসরি সোর্সের সাথে লিঙ্ক করা থাকে।
পাইথন
from google import genai
client = genai.Client()
interaction = client.interactions.create(
model="gemini-3-flash-preview",
input="Who won Euro 2024?",
tools=[{"type": "google_search"}],
)
for step in interaction.steps:
if step.type == "google_search_result":
print(f"Search Suggestions: {step.search_suggestions}")
elif step.type == "model_output":
print(f"Answer: {step.content[0].text}")
if step.content[0].annotations:
for anno in step.content[0].annotations:
print(f"Citation: {anno.title} ({anno.uri})")
জাভাস্ক্রিপ্ট
import { GoogleGenAI } from '@google/genai';
const client = new GoogleGenAI({});
const interaction = await client.interactions.create({
model: 'gemini-3-flash-preview',
input: 'Who won Euro 2024?',
tools: [{ type: 'google_search' }]
});
for (const step of interaction.steps) {
if (step.type === 'google_search_result') {
console.log(`Search Suggestions: ${step.search_suggestions}`);
} else if (step.type === 'model_output') {
console.log(`Answer: ${step.content[0].text}`);
if (step.content[0].annotations) {
for (const anno of step.content[0].annotations) {
console.log(`Citation: ${anno.title} (${anno.uri})`);
}
}
}
}
বিশ্রাম
# Request
curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"model": "gemini-3-flash-preview",
"input": "Who won Euro 2024?",
"tools": [{"type": "google_search"}]
}'
# Response (showing grounding)
{
"id": "int_grounded",
"steps": [
{
"type": "user_input",
"status": "done",
"content": [{ "type": "text", "text": "Who won Euro 2024?" }]
},
{
"type": "google_search_call",
"status": "done",
"content": [{ "type": "text", "text": "UEFA Euro 2024 winner" }]
},
{
"type": "google_search_result",
"status": "done",
"content": [
{
"type": "text",
"text": "Spain won Euro 2024..."
}
]
},
{
"type": "model_output",
"status": "done",
"content": [
{
"type": "text",
"text": "Spain won Euro 2024, defeating England 2-1.",
"annotations": [
{
"start_index": 0,
"end_index": 42,
"uri": "https://vertexaisearch...",
"title": "aljazeera.com"
}
]
}
]
}
]
}
ফাংশন কলিং
স্টেপস স্কিমার সাথে সামঞ্জস্য রাখতে ফাংশন কল এবং ফলাফলের কাঠামোও পরিবর্তন করা হয়েছে।
( generateContent ) এর আগে
generateContent এ, রেসপন্সটি ক্যান্ডিডেটগুলোর মধ্যে থাকা ফাংশন কলগুলো রিটার্ন করে।
পাইথন
from google import genai
from google.genai import types
client = genai.Client()
# Step 1: Send prompt with tools
response = client.models.generate_content(
model="gemini-2.5-flash",
contents="What's the weather in Boston?",
config=types.GenerateContentConfig(tools=[weather_tool]),
)
# Assume model returned function_call
function_call = response.candidates[0].content.parts[0].function_call
print(f"Requested tool: {function_call.name}")
# Step 2: Execute local function and send result back
result = "52°F and rain"
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=[
types.Content(
role="user",
parts=[
types.Part.from_text(text="What's the weather in Boston?")
],
),
response.candidates[0].content, # Model turn with function call
types.Content(
role="user",
parts=[
types.Part.from_function_response(
name=function_call.name,
response={"result": result},
)
],
),
],
config=types.GenerateContentConfig(tools=[weather_tool]),
)
print(response.text)
জাভাস্ক্রিপ্ট
import { GoogleGenAI } from '@google/genai';
const client = new GoogleGenAI({});
// Step 1: Send prompt with tools
let response = await client.models.generateContent({
model: 'gemini-2.5-flash',
contents: "What's the weather in Boston?",
config: { tools: [weatherTool] }
});
const functionCall = response.candidates[0].content.parts[0].functionCall;
console.log(`Requested tool: ${functionCall.name}`);
// Step 2: Execute local function and send result back
const result = "52°F and rain";
response = await client.models.generateContent({
model: 'gemini-2.5-flash',
contents: [
{ role: 'user', parts: [{ text: "What's the weather in Boston?" }] },
response.candidates[0].content, // Model turn
{
role: 'user',
parts: [{
functionResponse: {
name: functionCall.name,
response: { result: result }
}
}]
}
],
config: { tools: [weatherTool] }
});
console.log(response.text);
বিশ্রাম
# Request
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"contents": [{
"parts": [{
"text": "What is the weather like in Boston, MA?"
}]
}],
"tools": [{
"functionDeclarations": [{
"name": "get_weather",
"description": "Get the current weather",
"parameters": {
"type": "OBJECT",
"properties": {
"location": {"type": "STRING"}
},
"required": ["location"]
}
}]
}]
}'
# Response
{
"candidates": [
{
"content": {
"parts": [
{
"functionCall": {
"name": "get_weather",
"args": { "location": "Boston, MA" }
}
}
],
"role": "model"
},
"finishReason": "STOP",
"index": 0
}
]
}
পরে (ইন্টারঅ্যাকশন এপিআই)
টুল কল এবং ফলাফল এখন টাইমলাইনের দুটি পৃথক ধাপ।
পাইথন
from google import genai
client = genai.Client()
weather_tool = {
"type": "function",
"name": "get_weather",
"description": "Gets weather",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"}
},
},
}
interaction = client.interactions.create(
model="gemini-3-flash-preview",
input="What's the weather in Boston?",
tools=[weather_tool],
)
# Check if the model requested a tool call
for step in interaction.steps:
if step.type == "function_call":
print(f"Executing {step.name} for {step.arguments}")
# Execute your local function here...
result = "52°F and rain"
# Submit the result back as a step
interaction = client.interactions.create(
model="gemini-3-flash-preview",
previous_interaction_id=interaction.id,
input=[
{
"type": "function_result",
"call_id": step.id,
"name": step.name,
"result": [{"type": "text", "text": result}],
}
],
)
# Inspect steps for final response
for s in interaction.steps:
if s.type == "model_output":
print(s.content[0].text)
জাভাস্ক্রিপ্ট
import { GoogleGenAI } from '@google/genai';
const client = new GoogleGenAI({});
const weatherTool = {
type: "function",
name: "get_weather",
description: "Get weather for a location",
parameters: {
type: "object",
properties: {
location: { type: "string" }
},
required: ["location"]
}
};
const interaction = await client.interactions.create({
model: 'gemini-3-flash-preview',
input: "What's the weather in Boston?",
tools: [weatherTool]
});
// Check if the model requested a tool call
for (const step of interaction.steps) {
if (step.type === 'function_call') {
console.log(`Executing ${step.name} for ${JSON.stringify(step.arguments)}`);
const result = "52°F and rain";
// Submit the result back as a step
const nextInteraction = await client.interactions.create({
model: 'gemini-3-flash-preview',
previous_interaction_id: interaction.id,
input: [
{
type: 'function_result',
call_id: step.id,
name: step.name,
result: [{ type: 'text', text: result }]
}
]
});
// Inspect steps for final response
for (const s of nextInteraction.steps) {
if (s.type === 'model_output') {
console.log(s.content[0].text);
}
}
}
}
বিশ্রাম
# Initial Request
curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"model": "gemini-3-flash-preview",
"input": "What's the weather in Boston?",
"tools": [{
"type": "function",
"name": "get_weather",
"description": "Get weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": { "type": "string" }
},
"required": ["location"]
}
}]
}'
# Response (requires action)
{
"id": "int_001",
"status": "requires_action",
"steps": [
{
"type": "user_input",
"status": "done",
"content": [
{ "type": "text", "text": "What's the weather in Boston?" }
]
},
{
"type": "function_call",
"status": "waiting",
"id": "fc_1",
"name": "get_weather",
"arguments": { "location": "Boston, MA" }
}
]
}
# Submit Tool Result Request
curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"model": "gemini-3-flash-preview",
"previous_interaction_id": "int_001",
"input": {
"type": "function_result",
"call_id": "fc_1",
"name": "get_weather",
"result": [
{ "type": "text", "text": "52°F with rain" }
]
}
}'
# Final Response
{
"id": "int_002",
"status": "completed",
"steps": [
{
"type": "function_result",
"call_id": "fc_1",
"name": "get_weather",
"result": [
{ "type": "text", "text": "52°F with rain" }
]
},
{
"type": "model_output",
"status": "done",
"content": [
{ "type": "text", "text": "It's 52°F with rain in Boston." }
]
}
]
}
স্ট্রিমিং
স্ট্রিমিং-এর ক্ষেত্রে একটি প্রধান পার্থক্য হলো, ইন্টারঅ্যাকশনস এপিআই রিকোয়েস্ট বডিতে "stream": true সহ একই এন্ডপয়েন্ট ব্যবহার করে, যেখানে generateContent এপিআই-এর জন্য একটি ডেডিকেটেড এন্ডপয়েন্ট ( :streamGenerateContent ) কল করার প্রয়োজন হয়।
এছাড়াও, স্ট্রিমিং ইভেন্টগুলো এখন ইন্টারঅ্যাকশন লাইফসাইকেল নিরীক্ষণ করতে এবং টাইমলাইন বরাবর এক্সিকিউশন ধাপগুলো ট্র্যাক করতে বিশেষায়িত টাইপ ব্যবহার করে।
( generateContentStream ) এর আগে
generateContent মাধ্যমে, আপনি রেসপন্স চাঙ্কের একটি স্ট্রিম গ্রহণ করেন।
পাইথন
response = client.models.generate_content_stream(
model="gemini-2.5-flash", contents="Tell me a story"
)
for chunk in response:
print(chunk.text, end="")
জাভাস্ক্রিপ্ট
const responseStream = await client.models.generateContentStream({
model: 'gemini-2.5-flash',
contents: 'Tell me a story',
});
for await (const chunk of responseStream) {
process.stdout.write(chunk.text);
}
বিশ্রাম
# Request
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"contents": [{
"parts": [{
"text": "Tell me a story"
}]
}]
}'
# Response stream
event: content.start
data: {"event_type": "content.start", "index": 0, "content": {"type": "thought"}}
event: content.delta
data: {"event_type": "content.delta", "index": 0, "delta": {"type": "thought_summary", "text": "User wants an explanation."}}
event: content.stop
data: {"event_type": "content.stop", "index": 0}
event: content.start
data: {"event_type": "content.start", "index": 1, "content": {"type": "text"}}
event: content.delta
data: {"event_type": "content.delta", "index": 1, "delta": {"type": "text", "text": "Hello"}}
event: content.stop
data: {"event_type": "content.stop", "index": 1}
পরে (ইন্টারঅ্যাকশন এপিআই)
ইন্টারঅ্যাকশনস এপিআই-তে, স্ট্রিমিং এক্সিকিউশন ধাপগুলোকে সংঘটিত হওয়ার সাথে সাথে উপস্থাপন করার জন্য সার্ভার-সেন্ট ইভেন্টস (SSE) এবং বিশেষায়িত ডেল্টা টাইপ ব্যবহার করে।
পাইথন
from google import genai
client = genai.Client()
stream = client.interactions.create(
model="gemini-3-flash-preview",
input="Tell me a story",
stream=True,
)
for event in stream:
if event.event_type == "step.delta":
if event.delta.type == "text":
print(event.delta.text, end="", flush=True)
elif event.event_type == "interaction.complete":
print(f"\n\n--- Stream Finished ---")
জাভাস্ক্রিপ্ট
import { GoogleGenAI } from '@google/genai';
const client = new GoogleGenAI({});
const stream = await client.interactions.create({
model: 'gemini-3-flash-preview',
input: 'Tell me a story',
stream: true,
});
for await (const event of stream) {
if (event.event_type === 'step.delta') {
if (event.delta.type === 'text' && 'text' in event.delta) {
process.stdout.write(event.delta.text);
}
} else if (event.event_type === 'interaction.complete') {
console.log('\n\n--- Stream Finished ---');
}
}
বিশ্রাম
# SSE স্ট্রিম আউটপুটের উদাহরণ event: interaction.created data: {"type": "interaction.created", "interaction": {"id": "int_xyz", "status": "created"}} event: interaction.status_update data: {"type": "interaction.status_update", "status": "in_progress"} event: step.start data: {"type": "step.start", "index": 0, "step": {"type": "thought"}} event: step.delta data: {"type": "step.delta", "index": 0, "delta": {"type": "thought", "text": "ব্যবহারকারী একটি ব্যাখ্যা চান।"}} event: step.stop data: {"type": "step.stop", "index": 0, "status": "done"} event: step.start data: {"type": "step.start", "index": 1, "step": {"type": "model_output"}} event: step.delta data: {"type": "step.delta", "index": 1, "delta": {"type": "text", "text": "হ্যালো"}} event: step.stop data: {"type": "step.stop", "index": 1, "status": "সম্পন্ন"} event: interaction.complete data: {"type": "interaction.complete", "interaction": {"id": "int_xyz", "status": "সম্পূর্ণ", "usage": {"prompt_tokens": 10, "completion_tokens": 5, "total_tokens": 15}}} ```
স্ট্রিমিং টুল এবং ফাংশন কল
আরও সূক্ষ্ম নিয়ন্ত্রণ এবং দৃশ্যমানতা প্রদানের জন্য স্ট্রিমে টুলগুলির আচরণ generateContent থেকে উল্লেখযোগ্যভাবে পরিবর্তিত হয়েছে।
( generateContent ) এর আগে
generateContent মাধ্যমে, স্ট্রিমিং ফাংশন কলগুলো একটি একক খণ্ডে সম্পূর্ণভাবে এসে পৌঁছাত। আর্গুমেন্টগুলো রিয়েল-টাইমে তৈরি হতে দেখা যেত না, তাই হ্যান্ডলারটি কেবল একটি সম্পূর্ণ functionCall অবজেক্ট আছে কিনা তা পরীক্ষা করত।
পাইথন
from google import genai
from google.genai import types
client = genai.Client()
stream = client.models.generate_content_stream(
model="gemini-2.5-flash",
contents="What's the weather in Boston?",
config=types.GenerateContentConfig(tools=[weather_tool]),
)
for chunk in stream:
# Function calls arrived complete — no partial arguments
if chunk.candidates[0].content.parts[0].function_call:
fc = chunk.candidates[0].content.parts[0].function_call
print(f"Call: {fc.name}({fc.args})")
elif chunk.text:
print(chunk.text, end="")
জাভাস্ক্রিপ্ট
import { GoogleGenAI } from '@google/genai';
const client = new GoogleGenAI({});
const stream = await client.models.generateContentStream({
model: 'gemini-2.5-flash',
contents: "What's the weather in Boston?",
config: { tools: [weatherTool] }
});
for await (const chunk of stream) {
// Function calls arrived complete — no partial arguments
const part = chunk.candidates[0].content.parts[0];
if (part.functionCall) {
console.log(`Call: ${part.functionCall.name}(${JSON.stringify(part.functionCall.args)})`);
} else if (part.text) {
process.stdout.write(part.text);
}
}
বিশ্রাম
# Request
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"contents": [{"parts": [{"text": "What'\''s the weather in Boston?"}]}],
"tools": [{"functionDeclarations": [{"name": "get_weather", "parameters": {"type": "OBJECT", "properties": {"location": {"type": "STRING"}}}}]}]
}'
# Response stream — function call arrives complete in one chunk
{"candidates": [{"content": {"parts": [{"functionCall": {"name": "get_weather", "args": {"location": "Boston, MA"}}}]}}]}
পরে (ইন্টারঅ্যাকশন এপিআই)
ইন্টারঅ্যাকশনস এপিআই ফাংশন কল আর্গুমেন্টগুলোকে অক্ষর-অক্ষর করে arguments ইভেন্ট হিসেবে স্ট্রিম করে। সম্পূর্ণ টুলটির জীবনচক্র — চিন্তা, কল, ফলাফল এবং আউটপুট — কতগুলো স্বতন্ত্র ধাপের একটি ধারাবাহিকতা হিসেবে সম্পন্ন হয়।
পাইথন
from google import genai
client = genai.Client()
stream = client.interactions.create(
model="gemini-3-flash-preview",
input="What's the weather in Boston?",
tools=[get_weather_tool],
stream=True,
)
for event in stream:
if event.event_type == "step.start":
if event.step.type == "function_call":
print(f"Calling: {event.step.name}")
elif event.event_type == "step.delta":
if event.delta.type == "arguments":
print(f" args: {event.delta.partial_arguments}")
elif event.delta.type == "text":
print(event.delta.text, end="")
elif event.event_type == "interaction.complete":
print("\n--- Done ---")
জাভাস্ক্রিপ্ট
import { GoogleGenAI } from '@google/genai';
const client = new GoogleGenAI({});
const stream = await client.interactions.create({
model: 'gemini-3-flash-preview',
input: "What's the weather in Boston?",
tools: [getWeatherTool],
stream: true,
});
for await (const event of stream) {
if (event.event_type === 'step.start') {
if (event.step.type === 'function_call') {
console.log(`Calling: ${event.step.name}`);
}
} else if (event.event_type === 'step.delta') {
if (event.delta.type === 'arguments') {
console.log(` args: ${event.delta.partial_arguments}`);
} else if (event.delta.type === 'text') {
process.stdout.write(event.delta.text);
}
} else if (event.event_type === 'interaction.complete') {
console.log('\n--- Done ---');
}
}
বিশ্রাম
# Request
curl -X POST "https://generativelanguage.googleapis.com/v1beta2/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"model": "gemini-3-flash-preview",
"input": "What'\''s the weather in Boston?",
"tools": [{"type": "function", "name": "get_weather", "parameters": {"type": "object", "properties": {"location": {"type": "string"}}}}],
"stream": true
}'
# Response stream
// Interaction created
event: interaction.created
data: {"type": "interaction.created", "interaction": {"id": "int_xyz", "status": "created"}}
event: interaction.status_update
data: {"type": "interaction.status_update", "status": "in_progress"}
// ── Step 0: Thought ──────────────────────────────────
event: step.start
data: {"type": "step.start", "index": 0, "step": {"type": "thought"}}
event: step.delta
data: {"type": "step.delta", "index": 0, "delta": {"type": "thought", "text": "The user wants weather data for Boston. I'll call the get_weather tool."}}
event: step.stop
data: {"type": "step.stop", "index": 0, "status": "done"}
// ── Step 1: Function Call (arguments streamed) ───────
event: step.start
data: {"type": "step.start", "index": 1, "step": {"type": "function_call", "id": "fc_1", "name": "get_weather"}}
event: step.delta
data: {"type": "step.delta", "index": 1, "delta": {"type": "arguments", "partial_arguments": "{\"location\": \"Boston, MA\"}"}}
event: step.stop
data: {"type": "step.stop", "index": 1, "status": "waiting"}
// The interaction pauses — the model needs the tool result before continuing.
event: interaction.status_update
data: {"type": "interaction.status_update", "status": "requires_action"}
// ── (Client submits the tool result) ──────────────────
// The client calls interactions.create with the function_result as input
// and the previous interaction's ID, then resumes consuming the stream.
event: interaction.status_update
data: {"type": "interaction.status_update", "status": "in_progress"}
// ── Step 2: Function Result (echoed back, no deltas) ─
event: step.start
data: {"type": "step.start", "index": 2, "step": {"type": "function_result", "call_id": "fc_1", "name": "get_weather", "result": [{"type": "text", "text": "52°F, rain"}]}}
event: step.stop
data: {"type": "step.stop", "index": 2, "status": "done"}
// ── Step 3: Thought ──────────────────────────────────
event: step.start
data: {"type": "step.start", "index": 3, "step": {"type": "thought"}}
event: step.delta
data: {"type": "step.delta", "index": 3, "delta": {"type": "thought", "text": "Got weather data. Composing the final response."}}
event: step.stop
data: {"type": "step.stop", "index": 3, "status": "done"}
// ── Step 4: Model Output (text streamed) ─────────────
event: step.start
data: {"type": "step.start", "index": 4, "step": {"type": "model_output"}}
event: step.delta
data: {"type": "step.delta", "index": 4, "delta": {"type": "text", "text": "It's currently 52°F and rainy in Boston."}}
event: step.stop
data: {"type": "step.stop", "index": 4, "status": "done"}
// ── Interaction complete ─────────────────────────────
event: interaction.complete
data: {"type": "interaction.complete", "interaction": {"id": "int_xyz", "status": "completed", "usage": {"prompt_tokens": 256, "completion_tokens": 128, "total_tokens": 384}}}
স্ট্রিমে সার্ভার-সাইড টুলস
গুগল সার্চের মতো সার্ভার-সাইড টুলগুলো স্ট্রিমের ফাংশন কল থেকে ভিন্নভাবে কাজ করে। এদের কল এবং ফলাফল step.start ইভেন্টে কোনো ডেল্টা ছাড়াই সম্পূর্ণভাবে এসে পৌঁছায় — শুধু step.start এবং তার ঠিক পরেই step.stop আসে।
// Server-side tool call — payload arrives complete in step.start
event: step.start
data: {"type": "step.start", "index": 4, "step": {"type": "google_search_call", "id": "gs_2", "query": "Alphabet Q4 2025 earnings"}}
event: step.stop
data: {"type": "step.stop", "index": 4, "status": "done"}
// Server-side tool result — also complete in step.start
event: step.start
data: {"type": "step.start", "index": 5, "step": {"type": "google_search_result", "call_id": "gs_2", "rendered_content": "<div>Alphabet Q4 2025 Revenue: $105.6B</div>", "signature": "abc123..."}}
event: step.stop
data: {"type": "step.stop", "index": 5, "status": "done"}