Google: Gemini Interactions API и function_result
С июня 2026 года Interactions API у Google имеет статус GA и рекомендуется для новых Gemini-проектов. Model steps содержат function_call, а приложение продолжает разговор через previous_interaction_id и function_result. Это ближе к Responses, чем к stateless Messages, но со своими полями.
Минимальная версия SDK. Interactions API доступен в JavaScript-пакете @google/genai начиная с версии 2.3.0. Устанавливайте актуальную версию и фиксируйте реально проверенную сборку в lockfile.Адаптер начинается с клиента и перевода определения tool.
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI({});
const model = process.env.GOOGLE_MODEL ?? "gemini-3.6-flash";
type GoogleState = {
previousInteractionId: string;
instructions: string;
tools: ToolDefinition[];
};
function toGoogleTool(tool: ToolDefinition) {
return {
type: "function" as const,
name: tool.name,
description: tool.description,
parameters: tool.parameters
};
}Первый interaction отправляет сообщение и tools, а состояние - это interaction.id.
async function start(input: AgentInput): Promise<ProviderTurn> {
const interaction = await client.interactions.create({
model,
input: input.message,
system_instruction: input.instructions,
tools: input.tools.map(toGoogleTool),
store: true
});
return fromGoogleInteraction(interaction, {
previousInteractionId: interaction.id,
instructions: input.instructions,
tools: input.tools
});
}Продолжение возвращает результаты как function_result по previous_interaction_id.
async function resume(rawState: unknown, results: ToolResult[]) {
const state = googleStateSchema.parse(rawState);
const interaction = await client.interactions.create({
model,
previous_interaction_id: state.previousInteractionId,
system_instruction: state.instructions,
tools: state.tools.map(toGoogleTool),
input: results.map(function toFunctionResult(result) {
return {
type: "function_result" as const,
name: result.name,
call_id: result.callId,
result: [{
type: "text" as const,
text: JSON.stringify({ ok: !result.isError, value: result.output })
}]
};
})
});
return fromGoogleInteraction(interaction, {
...state,
previousInteractionId: interaction.id
});
}Нормализация steps сводит их к общему ProviderTurn.
function fromGoogleInteraction(interaction: any, state: GoogleState): ProviderTurn {
const calls = interaction.steps
.filter(function isCall(step: any) { return step.type === "function_call"; })
.map(function normalize(step: any): ToolCall {
return { id: step.id, name: step.name, arguments: step.arguments };
});
if (calls.length > 0) return { kind: "tool_calls", calls, state };
return { kind: "text", text: interaction.output_text ?? "", state };
}Две оговорки завершают адаптер. Первая - про то, что previous_interaction_id НЕ переносит.
Повторяйте interaction-scoped поля.previous_interaction_idсохраняет историю, но не переносит tools,system_instructionиgeneration_config. Адаптер обязан передавать их снова на каждом ходе.
Вторая - про то, когда всё же нужен старый generateContent.
Когда нужен legacy generateContent. Google сохраняет его поддержку. В актуальной документации explicit caching, Batch и некоторые специальные возможности пока остаются причиной использовать generateContent. Для нового обычного agent loop начинайте с Interactions.У Google, как и у OpenAI, есть и полноценный фреймворк - ADK. Разберём, когда он оправдан.