Google ADK agents run tools through FunctionTool.execute. Paybond hooks that boundary — Harbor verifies spend before side effects and auto-submits evidence after success — not as model middleware.
Install @paybond/google-adk (npm) with @google/adk, or paybond-kit[google-adk] (pip). Adapter reference: /docs/kit/google-adk.
Harbor verify before execute
Wrapped FunctionTool handlers authorize operation and amount before paid work.
Auto-evidence
Guarded tools finalize spend and submit signed evidence after success.
Policy budgets
Versioned YAML caps per-call and intent spend for Gemini and GCP agents.
TypeScript and Python
Same google-adk adapter on npm (@paybond/google-adk) and pip (paybond-kit[google-adk]).
Why Paybond (not just ADK callbacks)?
ADK before_tool_callback and host confirmations do not enforce Harbor spend budgets, capability tokens, or signed completion evidence bound to an intent.
Model / input guardrails
- ADK callbacks alone
- Yes — SDK or host checks and approvals
- With Paybond
- Yes — plus Harbor authorize at the tool boundary
Spend boundary
- ADK callbacks alone
- No per-tool Harbor budget or capability token
- With Paybond
- Per-call and intent budgets enforced before invoke
Signed evidence
- ADK callbacks alone
- SDK traces / logs only
- With Paybond
- Signed completion digests bound to the intent
Intent binding
- ADK callbacks alone
- No Harbor intent or settlement receipt
- With Paybond
- Capability token + intentId from authenticated bind
Paid tool deny / HITL
- ADK callbacks alone
- Host or SDK approvals only
- With Paybond
- Harbor verify, deny, or HITL hold before side effects
| Capability | ADK callbacks alone | With Paybond |
|---|---|---|
| Model / input guardrails | Yes — SDK or host checks and approvals | Yes — plus Harbor authorize at the tool boundary |
| Spend boundary | No per-tool Harbor budget or capability token | Per-call and intent budgets enforced before invoke |
| Signed evidence | SDK traces / logs only | Signed completion digests bound to the intent |
| Intent binding | No Harbor intent or settlement receipt | Capability token + intentId from authenticated bind |
| Paid tool deny / HITL | Host or SDK approvals only | Harbor verify, deny, or HITL hold before side effects |
How it works
Adapter flow
FunctionTool.execute
Google ADK agent invokes a side-effecting tool
Paybond wrap
Harbor authorize before your handler runs
- Verify spend and operation
- Deny or HITL hold
- Issue / check capability
Tool runs
Your execute handler performs the paid work
Evidence
Wrapped tool finalizes spend and auto-evidence
Paybond wraps Google ADK FunctionTool execute: Harbor authorize before your handler runs, then auto-evidence after success.
Tool boundary, not model middleware
Paybond wraps FunctionTool.execute (or rebuilds guarded tools) so Harbor authorize runs before your handler and auto-evidence fires after success. Read-only registry tools pass through unchanged. Use Paybond A2A card/contracts discovery beside ADK RemoteA2aAgent — each agent that executes paid tools must wrap locally; there is no A2A spend proxy in v1.
3-minute quickstart
Smoke the google-adk adapter Harbor contract — no Gemini credentials required for this check:
terminal
paybond login
paybond agent demo google-adk smoke \
--operation paid-tool \
--requested-spend-cents 100 \
--evidence-preset cost_and_completion \
--format tableInstall first:
terminal
# TypeScript
npm install @paybond/google-adk @google/adk
# Python
pip install "paybond-kit[google-adk]"When the smoke succeeds you should see:
- ✓ Spend approved
- ✓ Tool completed
- ✓ Evidence verified (
cost_and_completion)
What success looks like
What success looks like
Authorized tool call · illustrative
- Operation
- paid-tool
- Status
- Approved
- Requested
- $1.00
- Evidence
- Verified
- Preset
- cost_and_completion
Scaffold
terminal
# TypeScript
paybond init agent-middleware --framework google-adk --out paybond-google-adk.ts
# Python
paybond init agent-middleware --framework google-adk --out paybond_google_adk.py
paybond policy init --preset saas --out paybond.policy.yamlValidate before deploy:
terminal
paybond policy validate-tools --file paybond.policy.yaml --local-onlyWire middleware
Recommended wiring
paybond.agent with framework google-adk returns guarded tools for your LlmAgent.
paybond-session.ts
import { FunctionTool, LlmAgent } from "@google/adk";
import { Paybond } from "@paybond/kit";
const paybond = await Paybond.open({ apiKey: process.env.PAYBOND_API_KEY! });
const bookHotelTool = new FunctionTool({
name: "travel.book_hotel",
description: "Book a hotel room",
parameters: {
type: "object",
properties: {
city: { type: "string" },
estimatedPriceCents: { type: "integer", minimum: 0 },
},
required: ["city", "estimatedPriceCents"],
},
execute: async (args) => bookHotel(args),
});
const { agentTools: tools } = await paybond.agent({
policy: "saas",
framework: "google-adk",
tools: [bookHotelTool, searchWebTool],
});
const agent = new LlmAgent({ name: "Travel", tools });Manual hook wiring
When you already bound a PaybondAgentRun:
paybond-session.ts
import { createPaybondGoogleAdkConfig } from "@paybond/google-adk";
const config = createPaybondGoogleAdkConfig(run, sdkTools);
const guardedTools = config.tools;Approval holds: when Harbor returns an approval hold, Python guarded tools raise RuntimeError with a Paybond message; TypeScript rethrows a clear Error (Paybond capability approval required: …) with the Harbor error as cause. Approve in the tenant console, store the approval token on the run with the ADK functionCallId, then retry with the same operation, amount, metadata, and approvalToken. Hard denials must not execute the tool.
Bypass classes: GOOGLE_SEARCH and ADK built-ins, unwrapped tools, AgentTool / RemoteA2aAgent remote hops, and before_tool_callback-only checks are not governed.
Production: omit sandbox defaults on paybond.agent() / paybond.instrument(), use deferred bind, then instrumented.bind({ intentId, capabilityToken }) per session. Tenant and intent IDs come from the Paybond session binding — never from unauthenticated tool args.
Production checklist
Production checklist
- Scaffold middleware with paybond init agent-middleware --framework google-adk
- Init a policy preset (e.g. saas) and validate tools
- Wire paybond.agent({ framework: "google-adk", tools })
- Bind intentId and capabilityToken per session in production
- Smoke with paybond agent demo google-adk smoke before ship
Works with
Works with
- Gemini
- OpenAI
- Anthropic
- MCP
Ready to test?
Related guides
- Agent middleware — bind, registry, tenant isolation
- Agent-agnostic spend controls — raw Gemini SDK function calling
- Agent policy-as-code — versioned YAML
- OpenAI Agents spend controls — similar FunctionTool boundary pattern
Developer reference: /docs/kit/google-adk.