Paybond ships a native Google ADK adapter for FunctionTool execute guards in TypeScript and Python. Use this page when you call Gemini through the raw Google AI SDK (function calling without ADK): bind a PaybondAgentRun, register side-effecting tools in paybond.policy.yaml, and wrap your function-call handlers with createPaybondGenericAgentConfig or paybond.instrument().
Model inference stays on the Google AI SDK. Paybond governs paid and side-effecting tools only — Harbor verify, approval holds, spend finalize, and auto-evidence.
Install
npm install @paybond/kit @google/genai # or pip install paybond-kit google-genai
Policy
Declare Gemini-exposed tools in paybond.policy.yaml and optionally fail closed on provider-native tools you do not execute locally:
version: 1 name: gemini-travel-agent-v1 default_deny: true adapter: deny_provider_executed_tools: true tools: travel.book_hotel: side_effecting: true max_spend_cents: 20000 evidence_preset: cost_and_completion search.web: side_effecting: false
The adapter.deny_provider_executed_tools flag is consumed by AI SDK-based adapters (Vercel AI, Cloudflare Agents). For Gemini function calling, keep read-only tools unregistered or map only locally executed handlers.
TypeScript (Google GenAI SDK)
import { GoogleGenAI } from "@google/genai"; import { Paybond } from "@paybond/kit"; const paybond = await Paybond.open({ apiKey: process.env.PAYBOND_API_KEY! }); const gemini = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY! }); const instrumented = await paybond.instrument({ policy: "./paybond.policy.yaml", tools: { "travel.book_hotel": async (args: { city: string; estimatedPriceCents: number }) => bookHotel(args), "search.web": async (args: { query: string }) => searchWeb(args), }, sandbox: true, }); const run = instrumented.run; const tools = instrumented.tools; // When Gemini returns a functionCall, dispatch to the guarded tool by name: async function handleGeminiFunctionCall(name: string, args: Record<string, unknown>) { const tool = tools.find((entry) => entry.name === name); if (!tool) { throw new Error(`unregistered tool: ${name}`); } return tool.execute({ toolName: name, toolCallId: crypto.randomUUID(), arguments: args, }); }
Wire handleGeminiFunctionCall inside your chat loop after generateContent returns tool calls. Keep the Gemini client pointed at Google — do not proxy model traffic through Paybond Gateway.
Python
import os import uuid from google import genai from paybond_kit import Paybond paybond = await Paybond.open(api_key=os.environ["PAYBOND_API_KEY"]) client = genai.Client(api_key=os.environ["GEMINI_API_KEY"]) result = await paybond.instrument( policy="./paybond.policy.yaml", framework="generic", tools={ "travel.book_hotel": book_hotel, "search.web": search_web, }, sandbox=True, ) tools_by_name = {tool.name: tool for tool in result.agent_tools} async def handle_gemini_function_call(name: str, args: dict) -> object: tool = tools_by_name.get(name) if tool is None: raise ValueError(f"unregistered tool: {name}") return await tool.execute( tool_name=name, tool_call_id=str(uuid.uuid4()), arguments=args, )
Roadmap: Google ADK vs raw Gemini SDK
For Google ADK apps (LlmAgent, FunctionTool, multi-agent graphs), use the shipped Google ADK adapter and /guides/google-adk-spend-controls — createPaybondGoogleAdkConfig / create_paybond_google_adk_config replace manual function-call dispatch.
This agent-agnostic guide remains the supported path for raw Gemini SDK function calling and custom orchestrators that do not use ADK runners.
Related
- Agent-agnostic adapter
- Agent policy —
paybond.policy.yamlfields and validation - Support matrix
- Agent integrations