Google ADK
Vectimus governs tool calls in Google Agent Development Kit agents. The same Cedar policies apply whether your agent runs on Gemini, GPT-4o or Claude via LiteLLM.
Installation
pip install vectimus[adk]
Or with uv:
uv add vectimus[adk]
Runner plugin (recommended)
Use VectimusADKPlugin with Runner(plugins=[...]) to apply governance globally across all agents managed by that runner:
from google.adk.agents import Agent
from google.adk.runners import InMemoryRunner
from google.adk.sessions import InMemorySessionService
from vectimus.integrations.adk import VectimusADKPlugin
# 1. Create the Vectimus plugin
plugin = VectimusADKPlugin(
observe_mode=False, # set True to log without blocking
principal="my-adk-agent", # identity for the audit trail
)
# 2. Define tools
def bash(command: str) -> str:
"""Run a shell command and return its output."""
import subprocess
return subprocess.check_output(command, shell=True, text=True)
def file_read(file_path: str) -> str:
"""Read a file and return its contents."""
return open(file_path).read()
# 3. Create the agent
agent = Agent(
name="governed-agent",
model="gemini-2.0-flash",
instruction="You are a helpful assistant.",
tools=[bash, file_read],
)
# 4. Wire the plugin into the Runner
session_service = InMemorySessionService()
runner = InMemoryRunner(
agent=agent,
app_name="my-app",
session_service=session_service,
plugins=[plugin], # <-- governance applied here
)
When a tool call is denied, the agent receives a dict like {"error": "Blocked by Vectimus policy vectimus-supchain-001: npm publish is not permitted."} and can try a different approach.
Per-agent callback
For governing a single agent without a plugin, use create_before_tool_callback:
from google.adk.agents import LlmAgent
from vectimus.integrations.adk import create_before_tool_callback
callback = create_before_tool_callback(
observe_mode=False,
)
agent = LlmAgent(
name="MyAgent",
model="gemini-2.0-flash",
before_tool_callback=callback,
)
The plugin approach is recommended over callbacks for consistent governance across all agents in a runner.
How it works
Vectimus maps ADK tool calls to the same canonical action types used by the CLI integrations:
| ADK tool name | Vectimus action type |
|---|---|
bash, shell, terminal | shell_command |
file_write | file_write |
file_read | file_read |
google_search, web_search | web_request |
server__tool (MCP pattern) | mcp_tool |
Shell commands are further classified into git_operation, infrastructure and package_operation based on the command content. Shell commands that perform file I/O (redirects, tee, inline scripts like python3 -c "open('f','w').write('x')") are reclassified to file_read or file_write with the file path extracted for Cedar policy matching.
Plugin options
| Parameter | Default | Description |
|---|---|---|
policy_dir | Built-in policies | Path to a directory of Cedar policy files |
observe_mode | False | Log decisions but never block (trial mode) |
principal | "adk-agent" | Identity string for the audit trail |
cwd | None | Working directory context for policy evaluation |
log_dir | ~/.vectimus/logs | Directory for audit log JSONL files |
Observe mode
Both the plugin and callback support observe mode for trialling without enforcement:
plugin = VectimusADKPlugin(observe_mode=True)
Or via environment variable:
export VECTIMUS_OBSERVE=true
Review the audit log at ~/.vectimus/logs/ to understand which actions your policies would block. When you’re satisfied, set observe_mode=False or unset the environment variable.
Custom policies
Load custom Cedar policies from a directory:
plugin = VectimusADKPlugin(
policy_dir="./my-policies",
)
See Writing policies for the full guide on creating custom Cedar rules.
Audit trail
Every tool call is logged to the audit trail regardless of the decision. The plugin logs both pre-action evaluations (before tool execution) and post-action results (after tool execution) so you have a complete picture of what your agents did and what was blocked.
Audit logs are JSONL files at ~/.vectimus/logs/audit-YYYY-MM-DD.jsonl.
Every evaluation also produces an Ed25519-signed governance receipt stored in .vectimus/receipts/. Receipts provide tamper-evident proof of each decision for audit compliance. The daemon cleans up receipts older than 7 days by default (configurable via [receipts] retention_days in config). Use vectimus verify to validate receipts and vectimus receipts prune for manual cleanup.