Skip to main content

Google Agent Development Kit (ADK)

Pavri integrates with the Google Agent Development Kit through a before-tool callback that enforces runtime governance policies.

One-Line Integration

from pavri import PavriConfig, secure

agent = build_adk_agent()
agent = secure(agent, PavriConfig(agent_name="my-agent", plugin="google_adk"))

The secure() call attaches the Pavri runtime to the agent, registers it with the backend, and installs the enforcement hook.

Supported Versions

  • Google ADK >=0.1.0
  • Python >=3.12

How It Works

Plugin Detection

The GoogleADKAdapter matches when either:

  • You pass plugin="google_adk" in the config
  • The target object's module name contains "google_adk"

Hooks Attached

When the runtime has an active policy cache and telemetry emitter, secure() attaches the following hook:

HookPurpose
_pavri_before_toolEvaluates policy before tool execution; returns None to allow or an error dict to block

Before-Tool Enforcement

The _pavri_before_tool hook follows the ADK callback convention. It returns None to allow the tool call to proceed, or a dict with an "error" key to block it:

# Internal flow — you do not call this directly
result = agent._pavri_before_tool("tool_name", tool_input)
# result is None (allow) or {"error": "Policy denied: <reason>"} (block)

This pattern matches how ADK's native before_tool_callback works: returning None means continue normally, returning a value means override/skip the operation.

The hook calls enforce_policy(f"tool:{tool_name}", ctx) against the local policy cache:

  • On allow: Returns None — the tool executes normally.
  • On deny: Catches the PolicyDeniedError and returns {"error": f"Policy denied: {reason}"}.

The configured fail_mode determines behavior when policy evaluation itself fails:

  • fail-open (default): Tool call is allowed.
  • fail-closed: Tool call is blocked.

Configuration

Key PavriConfig options for Google ADK:

from pavri import PavriConfig

config = PavriConfig(
agent_name="my-agent",
plugin="google_adk",
api_key="fab_...",
backend_url="https://pavri.example.com",
org_id="org-acme",
session_id="session-123",
team="platform",
environment="production",
fail_mode="open",
)
FieldDefaultDescription
fail_mode"open"Whether to allow or deny when policy evaluation fails
telemetry_mode"full"Controls telemetry detail level
environment"development"Deployment environment tag
policy_sync.poll_interval_seconds60How often to poll for policy updates

ADK Runner Plugin Pattern

The design spec recommends implementing Pavri as an ADK Plugin registered on the Runner for global enforcement across all agents. The current implementation attaches the hook directly to the agent object. The Runner-level plugin pattern is planned for a future release.

Graceful Degradation

If the Pavri runtime cannot build an enforcement context, the plugin skips hook installation entirely. The agent runs without Pavri enforcement. Check the runtime status to verify:

from pavri.core import get_runtime

runtime = get_runtime(agent)
status = runtime.status()
print(status.connected, status.policy_revision)

Troubleshooting

Agent runs but no policy enforcement

  • Verify the backend is reachable and api_key is set.
  • Check runtime.status().policy_revision — if 0, the SDK has no cached policy.
  • The plugin requires both a policy cache and telemetry emitter.

Tool blocked unexpectedly

  • The _pavri_before_tool hook returns an error dict when a policy denies the call. Check the "error" value for the denial reason.
  • Review policies in the dashboard.
  • Check fail_mode"closed" denies on evaluation failure.

Plugin not detected

  • Pass plugin="google_adk" explicitly in the config.
  • Ensure the agent object's module includes "google_adk" in its path for auto-detection.

What's Deferred

The following capabilities are planned for Phase 2:

  • Log forwarding from the ADK plugin
  • Trace-link capture for Google's native tracing
  • Runner-level plugin integration (global enforcement across all agents)
  • Before-model callback enforcement
  • Session state monitoring via CallbackContext