Google Gemini
Use @codespar/google-genai to give Google Gemini agents commerce capabilities in Latin America.
Google Gemini Adapter
@codespar/google-genaiv0.4.0The @codespar/google-genai adapter converts CodeSpar session tools into Google's Gemini FunctionDeclaration format. It provides helpers to build the full tools config for getGenerativeModel() and handle function call responses. Works with Gemini 1.5 Pro, Gemini 1.5 Flash, and Gemini 2.0 models.
Pick this adapter when you need multimodal commerce flows (photo-of-receipt → invoice), the very long context windows Gemini provides (2M tokens on 1.5 Pro) for reconciling large transaction histories, or your infrastructure already runs on Google Cloud / Vertex AI.
Framework-specific notes
FunctionDeclarationis flatter than OpenAI/Anthropic — no nestedtype: "function"wrapper. The adapter takes care of the conversion, but if you read thetoolsconfig, it looks different.- Multimodal is the differentiator — pass a
Partwith an image (receipt, screenshot, product photo) in the same prompt as your tool request; Gemini can read the image and pick the rightcodespar_invoiceorcodespar_payarguments from what it sees. - 2M-token context — 1.5 Pro keeps a full month of transaction logs in memory for reconciliation agents without summarization.
- Parallel function calls in 2.0 — Gemini 2.0 Flash + Pro emit multiple
functionCallparts per response. Gemini 1.5 does one at a time. Pick the model intentionally based on the flow's concurrency. - Vertex AI auth — if you are on Google Cloud, prefer Vertex AI credentials over API keys. The adapter accepts both but project-scoped IAM scales better for multi-tenant SaaS.
Installation
npm install @codespar/sdk @codespar/google-genai @google/generative-aipnpm add @codespar/sdk @codespar/google-genai @google/generative-aiyarn add @codespar/sdk @codespar/google-genai @google/generative-ai@codespar/google-genai has a peer dependency on @codespar/sdk@^0.9.0. You also need @google/generative-ai for the Gemini runtime.
API Reference
getToolsConfig(session): Promise<{ functionDeclarations }[]>
Fetches all tools and returns the full tools config array ready to pass to getGenerativeModel(). This is the most common entry point.
import { CodeSpar } from "@codespar/sdk";
import { getToolsConfig } from "@codespar/google-genai";
import { GoogleGenerativeAI } from "@google/generative-ai";
const codespar = new CodeSpar({ apiKey: process.env.CODESPAR_API_KEY });
const session = await codespar.create("user_123", {
servers: ["stripe", "mercadopago"],
});
const toolsConfig = await getToolsConfig(session);
const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);
const model = genAI.getGenerativeModel({
model: "gemini-1.5-pro",
tools: toolsConfig,
});getTools(session): Promise<GeminiFunctionDeclaration[]>
Returns the raw array of FunctionDeclaration objects without the wrapper. Use when you need to manipulate declarations before passing to Gemini.
import { getTools } from "@codespar/google-genai";
const declarations = await getTools(session);
// Filter to only payment tools
const paymentDecls = declarations.filter((d) => d.name.includes("pay"));toGeminiTool(tool): GeminiFunctionDeclaration
Converts a single CodeSpar tool to a Gemini FunctionDeclaration.
import { toGeminiTool } from "@codespar/google-genai";
const allTools = await session.tools();
const decl = toGeminiTool(allTools[0]);
// { name: "codespar_charge", description: "...", parameters: { type: "object", ... } }handleFunctionCall(session, functionCall): Promise<ToolResult>
Executes a Gemini function call response by routing through the CodeSpar session. Takes { name, args } from the Gemini response.
import { handleFunctionCall } from "@codespar/google-genai";
// functionCall comes from response.functionCalls()[0]
const result = await handleFunctionCall(session, {
name: "codespar_charge",
args: { provider: "stripe", amount: 4990, currency: "BRL" },
});Full agent loop
This is a complete example of a Gemini agent with CodeSpar tools:
import { GoogleGenerativeAI } from "@google/generative-ai";
import { CodeSpar } from "@codespar/sdk";
import { getToolsConfig, handleFunctionCall } from "@codespar/google-genai";
const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);
const codespar = new CodeSpar({ apiKey: process.env.CODESPAR_API_KEY });
async function run(userMessage: string) {
// 1. Create a session
const session = await codespar.create("user_123", {
servers: ["stripe", "asaas", "correios"],
});
// 2. Get tools config for Gemini
const toolsConfig = await getToolsConfig(session);
// 3. Create the model with tools
const model = genAI.getGenerativeModel({
model: "gemini-1.5-pro",
tools: toolsConfig,
systemInstruction:
"You are a commerce assistant for a Brazilian e-commerce store. " +
"Use the available tools to handle payments, invoicing, and shipping. " +
"Respond in the same language the user writes in.",
});
// 4. Start a chat
const chat = model.startChat();
let response = await chat.sendMessage(userMessage);
// 5. Tool call loop
const MAX_ITERATIONS = 10;
let iterations = 0;
while (iterations < MAX_ITERATIONS) {
const functionCalls = response.functionCalls();
if (!functionCalls || functionCalls.length === 0) break;
// Execute each function call
const functionResponses = [];
for (const fc of functionCalls) {
let resultData: unknown;
try {
const result = await handleFunctionCall(session, fc);
resultData = result.data;
} catch (error) {
resultData = {
error: error instanceof Error ? error.message : "Function call failed",
};
}
functionResponses.push({
functionResponse: {
name: fc.name,
response: resultData,
},
});
}
// Send function results back
response = await chat.sendMessage(functionResponses);
iterations++;
}
// 6. Clean up
await session.close();
return response.text();
}
const reply = await run("Generate a boleto for R$250 due in 7 days");
console.log(reply);Handling parallel tool calls
Gemini may return multiple function calls in a single response. Execute them in parallel:
const functionCalls = response.functionCalls() ?? [];
const results = await Promise.all(
functionCalls.map(async (fc) => {
const result = await handleFunctionCall(session, fc);
return {
functionResponse: { name: fc.name, response: result.data },
};
})
);
response = await chat.sendMessage(results);You must return a response for every function call. Omitting a response will cause Gemini to return an error.
Streaming
Use sendMessageStream for streaming responses:
import { GoogleGenerativeAI } from "@google/generative-ai";
import { CodeSpar } from "@codespar/sdk";
import { getToolsConfig, handleFunctionCall } from "@codespar/google-genai";
const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY);
const codespar = new CodeSpar({ apiKey: process.env.CODESPAR_API_KEY });
async function runStreaming(userMessage: string) {
const session = await codespar.create("user_123", {
servers: ["stripe", "mercadopago"],
});
const toolsConfig = await getToolsConfig(session);
const model = genAI.getGenerativeModel({
model: "gemini-1.5-flash",
tools: toolsConfig,
});
const chat = model.startChat();
const streamResult = await chat.sendMessageStream(userMessage);
for await (const chunk of streamResult.stream) {
const text = chunk.text();
if (text) process.stdout.write(text);
}
const response = await streamResult.response;
const functionCalls = response.functionCalls();
if (functionCalls && functionCalls.length > 0) {
for (const fc of functionCalls) {
const result = await handleFunctionCall(session, fc);
console.log(`\nTool ${fc.name}:`, result.data);
}
}
await session.close();
}
await runStreaming("Create a Pix payment for R$150");Error handling
Wrap handleFunctionCall in try-catch and return errors as function responses:
for (const fc of functionCalls) {
let resultData: unknown;
try {
const result = await handleFunctionCall(session, fc);
resultData = result.data;
} catch (error) {
resultData = {
error: error instanceof Error ? error.message : "Function call failed",
function_name: fc.name,
};
}
functionResponses.push({
functionResponse: { name: fc.name, response: resultData },
});
}Returning errors as function responses lets Gemini reason about the failure and decide to retry or try a different approach.
Best practices
-
Always close sessions. Use
try/finallyto ensuresession.close()runs. -
Use
getToolsConfig. It returns the correct envelope format forgetGenerativeModel(). UsegetToolsonly when you need to manipulate declarations. -
Prefer Gemini 1.5 Pro for tool calling. It has the best function-calling accuracy. Flash works but may be less reliable with complex schemas.
-
Set a descriptive system instruction. Tell Gemini what domain it operates in.
-
Limit loop iterations. Add
MAX_ITERATIONSto prevent infinite function-call loops. -
Scope servers narrowly. Fewer tools means better function selection accuracy.
Newer SDK wrappers
The adapter wires Gemini to session.tools() + session.execute(). For higher-level flows you can call typed wrappers on the session directly — same routing infrastructure, no LLM hop:
session.discover(query)/session.charge(args)/session.pay(args)/session.ship(args)— typed shortcuts for the meta-tools.session.connectionWizard(serverId)— open a hosted auth flow for a missing connection.session.paymentStatus(toolCallId)andsession.paymentStatusStream(toolCallId)— async settlement correlation (poll or SSE).session.verificationStatus(toolCallId)andsession.verificationStatusStream(toolCallId)— KYC outcome polling / SSE.
Full reference at /docs/api/sdk.
Next steps
Last updated on